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