playbq.c revision 208a2dae4b1bc98de4282f08c5b5acad0d797eb0
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/sndfile.h>
33
34#define max(a, b) ((a) > (b) ? (a) : (b))
35#define min(a, b) ((a) < (b) ? (a) : (b))
36
37unsigned numBuffers = 2;
38int framesPerBuffer = 512;
39SNDFILE *sndfile;
40SF_INFO sfinfo;
41unsigned which; // which buffer to use next
42SLboolean eof;  // whether we have hit EOF on input yet
43void *buffers;
44SLuint32 byteOrder; // desired to use for PCM buffers
45SLuint32 nativeByteOrder;   // of platform
46audio_format_t transferFormat = AUDIO_FORMAT_PCM_16_BIT;
47size_t sfframesize = 0;
48
49// swap adjacent bytes; this would normally be in <unistd.h> but is missing here
50static void swab(const void *from, void *to, ssize_t n)
51{
52    // from and to as char pointers
53    const char *from_ch = (const char *) from;
54    char *to_ch = (char *) to;
55    // note that we don't swap the last odd byte
56    while (n >= 2) {
57        to_ch[0] = from_ch[1];
58        to_ch[1] = from_ch[0];
59        to_ch += 2;
60        from_ch += 2;
61        n -= 2;
62    }
63}
64
65// squeeze 16-bit signed PCM samples down to 8-bit unsigned PCM samples by truncation; no dithering
66static void squeeze(const short *from, unsigned char *to, ssize_t n)
67{
68    // note that we don't squeeze the last odd byte
69    while (n >= 2) {
70        *to++ = (*from++ + 32768) >> 8;
71        n -= 2;
72    }
73}
74
75// squeeze 32-bit signed PCM samples down to 24-bit unsigned PCM samples by truncation
76static void squeeze24(const unsigned char *from, unsigned char *to, ssize_t n)
77{
78    // note that we don't squeeze the last odd bytes
79    while (n >= 3) {
80        ++from;
81        *to++ = *from++;
82        *to++ = *from++;
83        *to++ = *from++;
84        n -= 4;
85    }
86}
87
88static audio_utils_fifo fifo;
89static unsigned underruns = 0;
90
91// This callback is called each time a buffer finishes playing
92
93static void callback(SLBufferQueueItf bufq, void *param)
94{
95    assert(NULL == param);
96    if (!eof) {
97        void *buffer = (char *)buffers + framesPerBuffer * sfframesize * which;
98        ssize_t count = audio_utils_fifo_read(&fifo, buffer, framesPerBuffer);
99        // on underrun from pipe, substitute silence
100        if (0 >= count) {
101            memset(buffer, 0, framesPerBuffer * sfframesize);
102            count = framesPerBuffer;
103            ++underruns;
104        }
105        if (count > 0) {
106            SLuint32 nbytes = count * sfframesize;
107            if (byteOrder != nativeByteOrder) {
108                swab(buffer, buffer, nbytes);
109            }
110            if (transferFormat == AUDIO_FORMAT_PCM_8_BIT) {
111                squeeze((short *) buffer, (unsigned char *) buffer, nbytes);
112                nbytes /= 2;
113            } else if (transferFormat == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
114                squeeze24((unsigned char *) buffer, (unsigned char *) buffer, nbytes);
115                nbytes = nbytes * 3 / 4;
116            }
117            SLresult result = (*bufq)->Enqueue(bufq, buffer, nbytes);
118            assert(SL_RESULT_SUCCESS == result);
119            if (++which >= numBuffers)
120                which = 0;
121        }
122    }
123}
124
125// This thread reads from a (slow) filesystem with unpredictable latency and writes to pipe
126
127static void *file_reader_loop(void *arg __unused)
128{
129#define READ_FRAMES 256
130    void *temp = malloc(READ_FRAMES * sfframesize);
131    sf_count_t total = 0;
132    sf_count_t count;
133    for (;;) {
134        switch (transferFormat) {
135        case AUDIO_FORMAT_PCM_FLOAT:
136            count = sf_readf_float(sndfile, (float *) temp, READ_FRAMES);
137            break;
138        case AUDIO_FORMAT_PCM_32_BIT:
139        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
140            count = sf_readf_int(sndfile, (int *) temp, READ_FRAMES);
141            break;
142        case AUDIO_FORMAT_PCM_16_BIT:
143        case AUDIO_FORMAT_PCM_8_BIT:
144            count = sf_readf_short(sndfile, (short *) temp, READ_FRAMES);
145            break;
146        default:
147            count = 0;
148            break;
149        }
150        if (0 >= count) {
151            eof = SL_BOOLEAN_TRUE;
152            break;
153        }
154        const unsigned char *ptr = (unsigned char *) temp;
155        while (count > 0) {
156            ssize_t actual = audio_utils_fifo_write(&fifo, ptr, (size_t) count);
157            if (actual < 0) {
158                break;
159            }
160            if ((sf_count_t) actual < count) {
161                usleep(10000);
162            }
163            ptr += actual * sfframesize;
164            count -= actual;
165            total += actual;
166        }
167        // simulate occasional filesystem latency
168        if ((total & 0xFF00) == 0xFF00) {
169            usleep(100000);
170        }
171    }
172    free(temp);
173    return NULL;
174}
175
176// Main program
177
178int main(int argc, char **argv)
179{
180    // Determine the native byte order (SL_BYTEORDER_NATIVE not available until 1.1)
181    union {
182        short s;
183        char c[2];
184    } u;
185    u.s = 0x1234;
186    if (u.c[0] == 0x34) {
187        nativeByteOrder = SL_BYTEORDER_LITTLEENDIAN;
188    } else if (u.c[0] == 0x12) {
189        nativeByteOrder = SL_BYTEORDER_BIGENDIAN;
190    } else {
191        fprintf(stderr, "Unable to determine native byte order\n");
192        return EXIT_FAILURE;
193    }
194    byteOrder = nativeByteOrder;
195
196    SLboolean enableReverb = SL_BOOLEAN_FALSE;
197    SLboolean enablePlaybackRate = SL_BOOLEAN_FALSE;
198    SLpermille initialRate = 0;
199    SLpermille finalRate = 0;
200    SLpermille deltaRate = 1;
201    SLmillisecond deltaRateMs = 0;
202
203    // process command-line options
204    int i;
205    for (i = 1; i < argc; ++i) {
206        char *arg = argv[i];
207        if (arg[0] != '-') {
208            break;
209        }
210        if (!strcmp(arg, "-b")) {
211            byteOrder = SL_BYTEORDER_BIGENDIAN;
212        } else if (!strcmp(arg, "-l")) {
213            byteOrder = SL_BYTEORDER_LITTLEENDIAN;
214        } else if (!strcmp(arg, "-8")) {
215            transferFormat = AUDIO_FORMAT_PCM_8_BIT;
216        } else if (!strcmp(arg, "-24")) {
217            transferFormat = AUDIO_FORMAT_PCM_24_BIT_PACKED;
218        } else if (!strcmp(arg, "-32")) {
219            transferFormat = AUDIO_FORMAT_PCM_32_BIT;
220        } else if (!strcmp(arg, "-32f")) {
221            transferFormat = AUDIO_FORMAT_PCM_FLOAT;
222        } else if (!strncmp(arg, "-f", 2)) {
223            framesPerBuffer = atoi(&arg[2]);
224        } else if (!strncmp(arg, "-n", 2)) {
225            numBuffers = atoi(&arg[2]);
226        } else if (!strncmp(arg, "-p", 2)) {
227            initialRate = atoi(&arg[2]);
228            enablePlaybackRate = SL_BOOLEAN_TRUE;
229        } else if (!strncmp(arg, "-P", 2)) {
230            finalRate = atoi(&arg[2]);
231            enablePlaybackRate = SL_BOOLEAN_TRUE;
232        } else if (!strncmp(arg, "-q", 2)) {
233            deltaRate = atoi(&arg[2]);
234            // deltaRate is a magnitude, so take absolute value
235            if (deltaRate < 0) {
236                deltaRate = -deltaRate;
237            }
238            enablePlaybackRate = SL_BOOLEAN_TRUE;
239        } else if (!strncmp(arg, "-Q", 2)) {
240            deltaRateMs = atoi(&arg[2]);
241            enablePlaybackRate = SL_BOOLEAN_TRUE;
242        } else if (!strcmp(arg, "-r")) {
243            enableReverb = SL_BOOLEAN_TRUE;
244        } else {
245            fprintf(stderr, "option %s ignored\n", arg);
246        }
247    }
248
249    if (argc - i != 1) {
250        fprintf(stderr, "usage: [-b/l] [-8 | -24 | -32 | -32f] [-f#] [-n#] [-p#] [-r]"
251                " %s filename\n", argv[0]);
252        fprintf(stderr, "    -b  force big-endian byte order (default is native byte order)\n");
253        fprintf(stderr, "    -l  force little-endian byte order (default is native byte order)\n");
254        fprintf(stderr, "    -8  output 8-bits per sample (default is 16-bits per sample)\n");
255        fprintf(stderr, "    -24 output 24-bits per sample\n");
256        fprintf(stderr, "    -32 output 32-bits per sample\n");
257        fprintf(stderr, "    -32f output float 32-bits per sample\n");
258        fprintf(stderr, "    -f# frames per buffer (default 512)\n");
259        fprintf(stderr, "    -n# number of buffers (default 2)\n");
260        fprintf(stderr, "    -p# initial playback rate in per mille (default 1000)\n");
261        fprintf(stderr, "    -P# final playback rate in per mille (default same as -p#)\n");
262        fprintf(stderr, "    -q# magnitude of playback rate changes in per mille (default 1)\n");
263        fprintf(stderr, "    -Q# period between playback rate changes in ms (default 50)\n");
264        fprintf(stderr, "    -r  enable reverb (default disabled)\n");
265        return EXIT_FAILURE;
266    }
267
268    const char *filename = argv[i];
269    //memset(&sfinfo, 0, sizeof(SF_INFO));
270    sfinfo.format = 0;
271    sndfile = sf_open(filename, SFM_READ, &sfinfo);
272    if (NULL == sndfile) {
273        perror(filename);
274        return EXIT_FAILURE;
275    }
276
277    // verify the file format
278    switch (sfinfo.channels) {
279    case 1:
280    case 2:
281        break;
282    default:
283        fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels);
284        goto close_sndfile;
285    }
286
287    switch (sfinfo.samplerate) {
288    case  8000:
289    case 11025:
290    case 12000:
291    case 16000:
292    case 22050:
293    case 24000:
294    case 32000:
295    case 44100:
296    case 48000:
297        break;
298    default:
299        fprintf(stderr, "unsupported sample rate %d\n", sfinfo.samplerate);
300        goto close_sndfile;
301    }
302
303    switch (sfinfo.format & SF_FORMAT_TYPEMASK) {
304    case SF_FORMAT_WAV:
305        break;
306    default:
307        fprintf(stderr, "unsupported format type 0x%x\n", sfinfo.format & SF_FORMAT_TYPEMASK);
308        goto close_sndfile;
309    }
310
311    switch (sfinfo.format & SF_FORMAT_SUBMASK) {
312    case SF_FORMAT_FLOAT:
313    case SF_FORMAT_PCM_32:
314    case SF_FORMAT_PCM_16:
315    case SF_FORMAT_PCM_U8:
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        if (byteOrder != nativeByteOrder) {
526            swab(buffer, buffer, nbytes);
527        }
528        if (transferFormat == AUDIO_FORMAT_PCM_8_BIT) {
529            squeeze((short *) buffer, (unsigned char *) buffer, nbytes);
530            nbytes /= 2;
531        } else if (transferFormat == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
532            squeeze24((unsigned char *) buffer, (unsigned char *) buffer, nbytes);
533            nbytes = nbytes * 3 / 4;
534        }
535        result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, nbytes);
536        assert(SL_RESULT_SUCCESS == result);
537    }
538    if (which >= numBuffers) {
539        which = 0;
540    }
541
542    // register a callback on the buffer queue
543    result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL);
544    assert(SL_RESULT_SUCCESS == result);
545
546    size_t frameSize = sfinfo.channels * audio_bytes_per_sample(transferFormat);
547#define FIFO_FRAMES 16384
548    void *fifoBuffer = malloc(FIFO_FRAMES * frameSize);
549    audio_utils_fifo_init(&fifo, FIFO_FRAMES, frameSize, fifoBuffer);
550
551    // create thread to read from file
552    pthread_t thread;
553    int ok = pthread_create(&thread, (const pthread_attr_t *) NULL, file_reader_loop, NULL);
554    assert(0 == ok);
555
556    // give thread a head start so that the pipe is initially filled
557    sleep(1);
558
559    // set the player's state to playing
560    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
561    assert(SL_RESULT_SUCCESS == result);
562
563    // get the initial time
564    struct timespec prevTs;
565    clock_gettime(CLOCK_MONOTONIC, &prevTs);
566    long elapsedNs = 0;
567    long deltaRateNs = deltaRateMs * 1000000;
568
569    // wait until the buffer queue is empty
570    SLBufferQueueState bufqstate;
571    for (;;) {
572        result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate);
573        assert(SL_RESULT_SUCCESS == result);
574        if (0 >= bufqstate.count) {
575            break;
576        }
577        if (!enablePlaybackRate || deltaRate == 0) {
578            sleep(1);
579        } else {
580            struct timespec curTs;
581            clock_gettime(CLOCK_MONOTONIC, &curTs);
582            elapsedNs += (curTs.tv_sec - prevTs.tv_sec) * 1000000000 +
583                    // this term can be negative
584                    (curTs.tv_nsec - prevTs.tv_nsec);
585            prevTs = curTs;
586            if (elapsedNs < deltaRateNs) {
587                usleep((deltaRateNs - elapsedNs) / 1000);
588                continue;
589            }
590            elapsedNs -= deltaRateNs;
591            SLpermille nextRate = currentRate + deltaRate;
592            result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, nextRate);
593            if (SL_RESULT_SUCCESS != result) {
594                fprintf(stderr, "next playback rate %d is unsupported\n", nextRate);
595            } else if (SL_RESULT_PARAMETER_INVALID == result) {
596                fprintf(stderr, "next playback rate %d is invalid\n", nextRate);
597            } else {
598                assert(SL_RESULT_SUCCESS == result);
599            }
600            currentRate = nextRate;
601            if (currentRate >= max(initialRate, finalRate)) {
602                currentRate = max(initialRate, finalRate);
603                deltaRate = -abs(deltaRate);
604            } else if (currentRate <= min(initialRate, finalRate)) {
605                currentRate = min(initialRate, finalRate);
606                deltaRate = abs(deltaRate);
607            }
608        }
609
610    }
611
612    // wait for reader thread to exit
613    ok = pthread_join(thread, (void **) NULL);
614    assert(0 == ok);
615
616    // set the player's state to stopped
617    result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_STOPPED);
618    assert(SL_RESULT_SUCCESS == result);
619
620    // destroy audio player
621    (*playerObject)->Destroy(playerObject);
622
623    audio_utils_fifo_deinit(&fifo);
624    free(fifoBuffer);
625
626    }
627
628no_player:
629
630    // destroy output mix
631    (*outputMixObject)->Destroy(outputMixObject);
632
633    // destroy engine
634    (*engineObject)->Destroy(engineObject);
635
636    }
637
638close_sndfile:
639
640    (void) sf_close(sndfile);
641
642    return EXIT_SUCCESS;
643}
644