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