Home | History | Annotate | Download | only in sandbox
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // Play an audio file using buffer queue
     18 
     19 #include <assert.h>
     20 #include <math.h>
     21 #include <pthread.h>
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #include <time.h>
     26 #include <unistd.h>
     27 
     28 #include <SLES/OpenSLES.h>
     29 #ifdef ANDROID
     30 #include <audio_utils/sndfile.h>
     31 #else
     32 #include <sndfile.h>
     33 #endif
     34 
     35 #include <media/nbaio/MonoPipe.h>
     36 #include <media/nbaio/MonoPipeReader.h>
     37 
     38 #define max(a, b) ((a) > (b) ? (a) : (b))
     39 #define min(a, b) ((a) < (b) ? (a) : (b))
     40 
     41 unsigned numBuffers = 2;
     42 int framesPerBuffer = 512;
     43 SNDFILE *sndfile;
     44 SF_INFO sfinfo;
     45 unsigned which; // which buffer to use next
     46 SLboolean eof;  // whether we have hit EOF on input yet
     47 short *buffers;
     48 SLuint32 byteOrder; // desired to use for PCM buffers
     49 SLuint32 nativeByteOrder;   // of platform
     50 SLuint32 bitsPerSample = 16;
     51 
     52 // swap adjacent bytes; this would normally be in <unistd.h> but is missing here
     53 static void swab(const void *from, void *to, ssize_t n)
     54 {
     55     // from and to as char pointers
     56     const char *from_ch = (const char *) from;
     57     char *to_ch = (char *) to;
     58     // note that we don't swap the last odd byte
     59     while (n >= 2) {
     60         to_ch[0] = from_ch[1];
     61         to_ch[1] = from_ch[0];
     62         to_ch += 2;
     63         from_ch += 2;
     64         n -= 2;
     65     }
     66 }
     67 
     68 // squeeze 16-bit signed PCM samples down to 8-bit unsigned PCM samples by truncation; no dithering
     69 static void squeeze(const short *from, unsigned char *to, ssize_t n)
     70 {
     71     // note that we don't squeeze the last odd byte
     72     while (n >= 2) {
     73         *to++ = (*from++ + 32768) >> 8;
     74         n -= 2;
     75     }
     76 }
     77 
     78 static android::MonoPipeReader *pipeReader;
     79 static android::MonoPipe *pipeWriter;
     80 static unsigned underruns = 0;
     81 
     82 // This callback is called each time a buffer finishes playing
     83 
     84 static void callback(SLBufferQueueItf bufq, void *param)
     85 {
     86     assert(NULL == param);
     87     if (!eof) {
     88         short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
     89         ssize_t count = pipeReader->read(buffer, framesPerBuffer, (int64_t) -1);
     90         // on underrun from pipe, substitute silence
     91         if (0 >= count) {
     92             memset(buffer, 0, framesPerBuffer * sfinfo.channels * sizeof(short));
     93             count = framesPerBuffer;
     94             ++underruns;
     95         }
     96         if (count > 0) {
     97             SLuint32 nbytes = count * sfinfo.channels * sizeof(short);
     98             if (byteOrder != nativeByteOrder) {
     99                 swab(buffer, buffer, nbytes);
    100             }
    101             if (bitsPerSample == 8) {
    102                 squeeze(buffer, (unsigned char *) buffer, nbytes);
    103                 nbytes /= 2;
    104             }
    105             SLresult result = (*bufq)->Enqueue(bufq, buffer, nbytes);
    106             assert(SL_RESULT_SUCCESS == result);
    107             if (++which >= numBuffers)
    108                 which = 0;
    109         }
    110     }
    111 }
    112 
    113 // This thread reads from a (slow) filesystem with unpredictable latency and writes to pipe
    114 
    115 static void *file_reader_loop(void *arg)
    116 {
    117 #define READ_FRAMES 256
    118     short *temp = (short *) malloc(READ_FRAMES * sfinfo.channels * sizeof(short));
    119     sf_count_t total = 0;
    120     for (;;) {
    121         sf_count_t count = sf_readf_short(sndfile, temp, (sf_count_t) READ_FRAMES);
    122         if (0 >= count) {
    123             eof = SL_BOOLEAN_TRUE;
    124             break;
    125         }
    126         const short *ptr = temp;
    127         while (count > 0) {
    128             ssize_t actual = pipeWriter->write(ptr, (size_t) count);
    129             if (actual < 0) {
    130                 break;
    131             }
    132             if ((sf_count_t) actual < count) {
    133                 usleep(10000);
    134             }
    135             ptr += actual * sfinfo.channels;
    136             count -= actual;
    137             total += actual;
    138         }
    139         // simulate occasional filesystem latency
    140         if ((total & 0xFF00) == 0xFF00) {
    141             usleep(100000);
    142         }
    143     }
    144     free(temp);
    145     return NULL;
    146 }
    147 
    148 // Main program
    149 
    150 int main(int argc, char **argv)
    151 {
    152     // Determine the native byte order (SL_BYTEORDER_NATIVE not available until 1.1)
    153     union {
    154         short s;
    155         char c[2];
    156     } u;
    157     u.s = 0x1234;
    158     if (u.c[0] == 0x34) {
    159         nativeByteOrder = SL_BYTEORDER_LITTLEENDIAN;
    160     } else if (u.c[0] == 0x12) {
    161         nativeByteOrder = SL_BYTEORDER_BIGENDIAN;
    162     } else {
    163         fprintf(stderr, "Unable to determine native byte order\n");
    164         return EXIT_FAILURE;
    165     }
    166     byteOrder = nativeByteOrder;
    167 
    168     SLboolean enableReverb = SL_BOOLEAN_FALSE;
    169     SLboolean enablePlaybackRate = SL_BOOLEAN_FALSE;
    170     SLpermille initialRate = 0;
    171     SLpermille finalRate = 0;
    172     SLpermille deltaRate = 1;
    173     SLmillisecond deltaRateMs = 0;
    174 
    175     // process command-line options
    176     int i;
    177     for (i = 1; i < argc; ++i) {
    178         char *arg = argv[i];
    179         if (arg[0] != '-') {
    180             break;
    181         }
    182         if (!strcmp(arg, "-b")) {
    183             byteOrder = SL_BYTEORDER_BIGENDIAN;
    184         } else if (!strcmp(arg, "-l")) {
    185             byteOrder = SL_BYTEORDER_LITTLEENDIAN;
    186         } else if (!strcmp(arg, "-8")) {
    187             bitsPerSample = 8;
    188         } else if (!strncmp(arg, "-f", 2)) {
    189             framesPerBuffer = atoi(&arg[2]);
    190         } else if (!strncmp(arg, "-n", 2)) {
    191             numBuffers = atoi(&arg[2]);
    192         } else if (!strncmp(arg, "-p", 2)) {
    193             initialRate = atoi(&arg[2]);
    194             enablePlaybackRate = SL_BOOLEAN_TRUE;
    195         } else if (!strncmp(arg, "-P", 2)) {
    196             finalRate = atoi(&arg[2]);
    197             enablePlaybackRate = SL_BOOLEAN_TRUE;
    198         } else if (!strncmp(arg, "-q", 2)) {
    199             deltaRate = atoi(&arg[2]);
    200             // deltaRate is a magnitude, so take absolute value
    201             if (deltaRate < 0) {
    202                 deltaRate = -deltaRate;
    203             }
    204             enablePlaybackRate = SL_BOOLEAN_TRUE;
    205         } else if (!strncmp(arg, "-Q", 2)) {
    206             deltaRateMs = atoi(&arg[2]);
    207             enablePlaybackRate = SL_BOOLEAN_TRUE;
    208         } else if (!strcmp(arg, "-r")) {
    209             enableReverb = SL_BOOLEAN_TRUE;
    210         } else {
    211             fprintf(stderr, "option %s ignored\n", arg);
    212         }
    213     }
    214 
    215     if (argc - i != 1) {
    216         fprintf(stderr, "usage: [-b/l] [-8] [-f#] [-n#] [-p#] [-r] %s filename\n", argv[0]);
    217         fprintf(stderr, "    -b  force big-endian byte order (default is native byte order)\n");
    218         fprintf(stderr, "    -l  force little-endian byte order (default is native byte order)\n");
    219         fprintf(stderr, "    -8  output 8-bits per sample (default is 16-bits per sample)\n");
    220         fprintf(stderr, "    -f# frames per buffer (default 512)\n");
    221         fprintf(stderr, "    -n# number of buffers (default 2)\n");
    222         fprintf(stderr, "    -p# initial playback rate in per mille (default 1000)\n");
    223         fprintf(stderr, "    -P# final playback rate in per mille (default same as -p#)\n");
    224         fprintf(stderr, "    -q# magnitude of playback rate changes in per mille (default 1)\n");
    225         fprintf(stderr, "    -Q# period between playback rate changes in ms (default 50)\n");
    226         fprintf(stderr, "    -r  enable reverb (default disabled)\n");
    227         return EXIT_FAILURE;
    228     }
    229 
    230     const char *filename = argv[i];
    231     //memset(&sfinfo, 0, sizeof(SF_INFO));
    232     sfinfo.format = 0;
    233     sndfile = sf_open(filename, SFM_READ, &sfinfo);
    234     if (NULL == sndfile) {
    235         perror(filename);
    236         return EXIT_FAILURE;
    237     }
    238 
    239     // The sample rate is a lie, but it doesn't actually matter
    240     const android::NBAIO_Format nbaio_format = android::Format_from_SR_C(44100, sfinfo.channels);
    241 
    242     // verify the file format
    243     switch (sfinfo.channels) {
    244     case 1:
    245     case 2:
    246         break;
    247     default:
    248         fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels);
    249         goto close_sndfile;
    250     }
    251 
    252     switch (sfinfo.samplerate) {
    253     case  8000:
    254     case 11025:
    255     case 12000:
    256     case 16000:
    257     case 22050:
    258     case 24000:
    259     case 32000:
    260     case 44100:
    261     case 48000:
    262         break;
    263     default:
    264         fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate);
    265         goto close_sndfile;
    266     }
    267 
    268     switch (sfinfo.format & SF_FORMAT_TYPEMASK) {
    269     case SF_FORMAT_WAV:
    270         break;
    271     default:
    272         fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK);
    273         goto close_sndfile;
    274     }
    275 
    276     switch (sfinfo.format & SF_FORMAT_SUBMASK) {
    277     case SF_FORMAT_PCM_16:
    278     case SF_FORMAT_PCM_U8:
    279         break;
    280     default:
    281         fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK);
    282         goto close_sndfile;
    283     }
    284 
    285     {
    286 
    287     buffers = (short *) malloc(framesPerBuffer * sfinfo.channels * sizeof(short) * numBuffers);
    288 
    289     // create engine
    290     SLresult result;
    291     SLObjectItf engineObject;
    292     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
    293     assert(SL_RESULT_SUCCESS == result);
    294     SLEngineItf engineEngine;
    295     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    296     assert(SL_RESULT_SUCCESS == result);
    297     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
    298     assert(SL_RESULT_SUCCESS == result);
    299 
    300     // create output mix
    301     SLObjectItf outputMixObject;
    302     SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
    303     SLboolean req[1] = {SL_BOOLEAN_TRUE};
    304     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0,
    305             ids, req);
    306     assert(SL_RESULT_SUCCESS == result);
    307     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
    308     assert(SL_RESULT_SUCCESS == result);
    309 
    310     // configure environmental reverb on output mix
    311     SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL;
    312     if (enableReverb) {
    313         result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
    314                 &mixEnvironmentalReverb);
    315         assert(SL_RESULT_SUCCESS == result);
    316         SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
    317         result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb,
    318                 &settings);
    319         assert(SL_RESULT_SUCCESS == result);
    320     }
    321 
    322     // configure audio source
    323     SLDataLocator_BufferQueue loc_bufq;
    324     loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
    325     loc_bufq.numBuffers = numBuffers;
    326     SLDataFormat_PCM format_pcm;
    327     format_pcm.formatType = SL_DATAFORMAT_PCM;
    328     format_pcm.numChannels = sfinfo.channels;
    329     format_pcm.samplesPerSec = sfinfo.samplerate * 1000;
    330     format_pcm.bitsPerSample = bitsPerSample;
    331     format_pcm.containerSize = format_pcm.bitsPerSample;
    332     format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER :
    333             SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
    334     format_pcm.endianness = byteOrder;
    335     SLDataSource audioSrc;
    336     audioSrc.pLocator = &loc_bufq;
    337     audioSrc.pFormat = &format_pcm;
    338 
    339     // configure audio sink
    340     SLDataLocator_OutputMix loc_outmix;
    341     loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
    342     loc_outmix.outputMix = outputMixObject;
    343     SLDataSink audioSnk;
    344     audioSnk.pLocator = &loc_outmix;
    345     audioSnk.pFormat = NULL;
    346 
    347     // create audio player
    348     SLInterfaceID ids2[3] = {SL_IID_BUFFERQUEUE, SL_IID_PLAYBACKRATE, SL_IID_EFFECTSEND};
    349     SLboolean req2[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
    350     SLObjectItf playerObject;
    351     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
    352             &audioSnk, enableReverb ? 3 : (enablePlaybackRate ? 2 : 1), ids2, req2);
    353     if (SL_RESULT_SUCCESS != result) {
    354         fprintf(stderr, "can't create audio player\n");
    355         goto no_player;
    356     }
    357 
    358     {
    359 
    360     // realize the player
    361     result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
    362     assert(SL_RESULT_SUCCESS == result);
    363 
    364     // get the effect send interface and enable effect send reverb for this player
    365     if (enableReverb) {
    366         SLEffectSendItf playerEffectSend;
    367         result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
    368         assert(SL_RESULT_SUCCESS == result);
    369         result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb,
    370                 SL_BOOLEAN_TRUE, (SLmillibel) 0);
    371         assert(SL_RESULT_SUCCESS == result);
    372     }
    373 
    374     // get the playback rate interface and configure the rate
    375     SLPlaybackRateItf playerPlaybackRate;
    376     SLpermille currentRate;
    377     if (enablePlaybackRate) {
    378         result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAYBACKRATE,
    379                 &playerPlaybackRate);
    380         assert(SL_RESULT_SUCCESS == result);
    381         SLpermille defaultRate;
    382         result = (*playerPlaybackRate)->GetRate(playerPlaybackRate, &defaultRate);
    383         assert(SL_RESULT_SUCCESS == result);
    384         SLuint32 defaultProperties;
    385         result = (*playerPlaybackRate)->GetProperties(playerPlaybackRate, &defaultProperties);
    386         assert(SL_RESULT_SUCCESS == result);
    387         printf("default playback rate %d per mille, properties 0x%x\n", defaultRate,
    388                 defaultProperties);
    389         if (initialRate <= 0) {
    390             initialRate = defaultRate;
    391         }
    392         if (finalRate <= 0) {
    393             finalRate = initialRate;
    394         }
    395         currentRate = defaultRate;
    396         if (finalRate == initialRate) {
    397             deltaRate = 0;
    398         } else if (finalRate < initialRate) {
    399             deltaRate = -deltaRate;
    400         }
    401         if (initialRate != defaultRate) {
    402             result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, initialRate);
    403             if (SL_RESULT_FEATURE_UNSUPPORTED == result) {
    404                 fprintf(stderr, "initial playback rate %d is unsupported\n", initialRate);
    405                 deltaRate = 0;
    406             } else if (SL_RESULT_PARAMETER_INVALID == result) {
    407                 fprintf(stderr, "initial playback rate %d is invalid\n", initialRate);
    408                 deltaRate = 0;
    409             } else {
    410                 assert(SL_RESULT_SUCCESS == result);
    411                 currentRate = initialRate;
    412             }
    413         }
    414     }
    415 
    416     // get the play interface
    417     SLPlayItf playerPlay;
    418     result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
    419     assert(SL_RESULT_SUCCESS == result);
    420 
    421     // get the buffer queue interface
    422     SLBufferQueueItf playerBufferQueue;
    423     result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
    424             &playerBufferQueue);
    425     assert(SL_RESULT_SUCCESS == result);
    426 
    427     // loop until EOF or no more buffers
    428     for (which = 0; which < numBuffers; ++which) {
    429         short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
    430         sf_count_t frames = framesPerBuffer;
    431         sf_count_t count;
    432         count = sf_readf_short(sndfile, buffer, frames);
    433         if (0 >= count) {
    434             eof = SL_BOOLEAN_TRUE;
    435             break;
    436         }
    437 
    438         // enqueue a buffer
    439         SLuint32 nbytes = count * sfinfo.channels * sizeof(short);
    440         if (byteOrder != nativeByteOrder) {
    441             swab(buffer, buffer, nbytes);
    442         }
    443         if (bitsPerSample == 8) {
    444             squeeze(buffer, (unsigned char *) buffer, nbytes);
    445             nbytes /= 2;
    446         }
    447         result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, nbytes);
    448         assert(SL_RESULT_SUCCESS == result);
    449     }
    450     if (which >= numBuffers) {
    451         which = 0;
    452     }
    453 
    454     // register a callback on the buffer queue
    455     result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL);
    456     assert(SL_RESULT_SUCCESS == result);
    457 
    458     pipeWriter = new android::MonoPipe(16384, nbaio_format, false /*writeCanBlock*/);
    459     android::NBAIO_Format offer = nbaio_format;
    460     size_t numCounterOffers = 0;
    461     ssize_t neg = pipeWriter->negotiate(&offer, 1, NULL, numCounterOffers);
    462     assert(0 == neg);
    463     pipeReader = new android::MonoPipeReader(pipeWriter);
    464     numCounterOffers = 0;
    465     neg = pipeReader->negotiate(&offer, 1, NULL, numCounterOffers);
    466     assert(0 == neg);
    467 
    468     // create thread to read from file
    469     pthread_t thread;
    470     int ok = pthread_create(&thread, (const pthread_attr_t *) NULL, file_reader_loop, NULL);
    471     assert(0 == ok);
    472 
    473     // give thread a head start so that the pipe is initially filled
    474     sleep(1);
    475 
    476     // set the player's state to playing
    477     result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
    478     assert(SL_RESULT_SUCCESS == result);
    479 
    480     // get the initial time
    481     struct timespec prevTs;
    482     clock_gettime(CLOCK_MONOTONIC, &prevTs);
    483     long elapsedNs = 0;
    484     long deltaRateNs = deltaRateMs * 1000000;
    485 
    486     // wait until the buffer queue is empty
    487     SLBufferQueueState bufqstate;
    488     for (;;) {
    489         result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate);
    490         assert(SL_RESULT_SUCCESS == result);
    491         if (0 >= bufqstate.count) {
    492             break;
    493         }
    494         if (!enablePlaybackRate || deltaRate == 0) {
    495             sleep(1);
    496         } else {
    497             struct timespec curTs;
    498             clock_gettime(CLOCK_MONOTONIC, &curTs);
    499             elapsedNs += (curTs.tv_sec - prevTs.tv_sec) * 1000000000 +
    500                     // this term can be negative
    501                     (curTs.tv_nsec - prevTs.tv_nsec);
    502             prevTs = curTs;
    503             if (elapsedNs < deltaRateNs) {
    504                 usleep((deltaRateNs - elapsedNs) / 1000);
    505                 continue;
    506             }
    507             elapsedNs -= deltaRateNs;
    508             SLpermille nextRate = currentRate + deltaRate;
    509             result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, nextRate);
    510             if (SL_RESULT_SUCCESS != result) {
    511                 fprintf(stderr, "next playback rate %d is unsupported\n", nextRate);
    512             } else if (SL_RESULT_PARAMETER_INVALID == result) {
    513                 fprintf(stderr, "next playback rate %d is invalid\n", nextRate);
    514             } else {
    515                 assert(SL_RESULT_SUCCESS == result);
    516             }
    517             currentRate = nextRate;
    518             if (currentRate >= max(initialRate, finalRate)) {
    519                 currentRate = max(initialRate, finalRate);
    520                 deltaRate = -abs(deltaRate);
    521             } else if (currentRate <= min(initialRate, finalRate)) {
    522                 currentRate = min(initialRate, finalRate);
    523                 deltaRate = abs(deltaRate);
    524             }
    525         }
    526     }
    527 
    528     // destroy audio player
    529     (*playerObject)->Destroy(playerObject);
    530 
    531     }
    532 
    533 no_player:
    534 
    535     // destroy output mix
    536     (*outputMixObject)->Destroy(outputMixObject);
    537 
    538     // destroy engine
    539     (*engineObject)->Destroy(engineObject);
    540 
    541     }
    542 
    543 close_sndfile:
    544 
    545     (void) sf_close(sndfile);
    546 
    547     return EXIT_SUCCESS;
    548 }
    549