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