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