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