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