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
swab(const void * from,void * to,ssize_t n)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
squeeze(const short * from,unsigned char * to,ssize_t n)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
squeeze24(const unsigned char * from,unsigned char * to,ssize_t n)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 
callback(SLBufferQueueItf bufq,void * param)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 
file_reader_loop(void * arg __unused)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 
main(int argc,char ** argv)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