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