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 #ifdef ANDROID
30 #include <audio_utils/sndfile.h>
31 #else
32 #include <sndfile.h>
33 #endif
34
35 #include <media/nbaio/MonoPipe.h>
36 #include <media/nbaio/MonoPipeReader.h>
37
38 #define max(a, b) ((a) > (b) ? (a) : (b))
39 #define min(a, b) ((a) < (b) ? (a) : (b))
40
41 unsigned numBuffers = 2;
42 int framesPerBuffer = 512;
43 SNDFILE *sndfile;
44 SF_INFO sfinfo;
45 unsigned which; // which buffer to use next
46 SLboolean eof; // whether we have hit EOF on input yet
47 short *buffers;
48 SLuint32 byteOrder; // desired to use for PCM buffers
49 SLuint32 nativeByteOrder; // of platform
50 SLuint32 bitsPerSample = 16;
51
52 // swap adjacent bytes; this would normally be in <unistd.h> but is missing here
swab(const void * from,void * to,ssize_t n)53 static void swab(const void *from, void *to, ssize_t n)
54 {
55 // from and to as char pointers
56 const char *from_ch = (const char *) from;
57 char *to_ch = (char *) to;
58 // note that we don't swap the last odd byte
59 while (n >= 2) {
60 to_ch[0] = from_ch[1];
61 to_ch[1] = from_ch[0];
62 to_ch += 2;
63 from_ch += 2;
64 n -= 2;
65 }
66 }
67
68 // 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)69 static void squeeze(const short *from, unsigned char *to, ssize_t n)
70 {
71 // note that we don't squeeze the last odd byte
72 while (n >= 2) {
73 *to++ = (*from++ + 32768) >> 8;
74 n -= 2;
75 }
76 }
77
78 static android::MonoPipeReader *pipeReader;
79 static android::MonoPipe *pipeWriter;
80 static unsigned underruns = 0;
81
82 // This callback is called each time a buffer finishes playing
83
callback(SLBufferQueueItf bufq,void * param)84 static void callback(SLBufferQueueItf bufq, void *param)
85 {
86 assert(NULL == param);
87 if (!eof) {
88 short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
89 ssize_t count = pipeReader->read(buffer, framesPerBuffer, (int64_t) -1);
90 // on underrun from pipe, substitute silence
91 if (0 >= count) {
92 memset(buffer, 0, framesPerBuffer * sfinfo.channels * sizeof(short));
93 count = framesPerBuffer;
94 ++underruns;
95 }
96 if (count > 0) {
97 SLuint32 nbytes = count * sfinfo.channels * sizeof(short);
98 if (byteOrder != nativeByteOrder) {
99 swab(buffer, buffer, nbytes);
100 }
101 if (bitsPerSample == 8) {
102 squeeze(buffer, (unsigned char *) buffer, nbytes);
103 nbytes /= 2;
104 }
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)115 static void *file_reader_loop(void *arg)
116 {
117 #define READ_FRAMES 256
118 short *temp = (short *) malloc(READ_FRAMES * sfinfo.channels * sizeof(short));
119 sf_count_t total = 0;
120 for (;;) {
121 sf_count_t count = sf_readf_short(sndfile, temp, (sf_count_t) READ_FRAMES);
122 if (0 >= count) {
123 eof = SL_BOOLEAN_TRUE;
124 break;
125 }
126 const short *ptr = temp;
127 while (count > 0) {
128 ssize_t actual = pipeWriter->write(ptr, (size_t) count);
129 if (actual < 0) {
130 break;
131 }
132 if ((sf_count_t) actual < count) {
133 usleep(10000);
134 }
135 ptr += actual * sfinfo.channels;
136 count -= actual;
137 total += actual;
138 }
139 // simulate occasional filesystem latency
140 if ((total & 0xFF00) == 0xFF00) {
141 usleep(100000);
142 }
143 }
144 free(temp);
145 return NULL;
146 }
147
148 // Main program
149
main(int argc,char ** argv)150 int main(int argc, char **argv)
151 {
152 // Determine the native byte order (SL_BYTEORDER_NATIVE not available until 1.1)
153 union {
154 short s;
155 char c[2];
156 } u;
157 u.s = 0x1234;
158 if (u.c[0] == 0x34) {
159 nativeByteOrder = SL_BYTEORDER_LITTLEENDIAN;
160 } else if (u.c[0] == 0x12) {
161 nativeByteOrder = SL_BYTEORDER_BIGENDIAN;
162 } else {
163 fprintf(stderr, "Unable to determine native byte order\n");
164 return EXIT_FAILURE;
165 }
166 byteOrder = nativeByteOrder;
167
168 SLboolean enableReverb = SL_BOOLEAN_FALSE;
169 SLboolean enablePlaybackRate = SL_BOOLEAN_FALSE;
170 SLpermille initialRate = 0;
171 SLpermille finalRate = 0;
172 SLpermille deltaRate = 1;
173 SLmillisecond deltaRateMs = 0;
174
175 // process command-line options
176 int i;
177 for (i = 1; i < argc; ++i) {
178 char *arg = argv[i];
179 if (arg[0] != '-') {
180 break;
181 }
182 if (!strcmp(arg, "-b")) {
183 byteOrder = SL_BYTEORDER_BIGENDIAN;
184 } else if (!strcmp(arg, "-l")) {
185 byteOrder = SL_BYTEORDER_LITTLEENDIAN;
186 } else if (!strcmp(arg, "-8")) {
187 bitsPerSample = 8;
188 } else if (!strncmp(arg, "-f", 2)) {
189 framesPerBuffer = atoi(&arg[2]);
190 } else if (!strncmp(arg, "-n", 2)) {
191 numBuffers = atoi(&arg[2]);
192 } else if (!strncmp(arg, "-p", 2)) {
193 initialRate = atoi(&arg[2]);
194 enablePlaybackRate = SL_BOOLEAN_TRUE;
195 } else if (!strncmp(arg, "-P", 2)) {
196 finalRate = atoi(&arg[2]);
197 enablePlaybackRate = SL_BOOLEAN_TRUE;
198 } else if (!strncmp(arg, "-q", 2)) {
199 deltaRate = atoi(&arg[2]);
200 // deltaRate is a magnitude, so take absolute value
201 if (deltaRate < 0) {
202 deltaRate = -deltaRate;
203 }
204 enablePlaybackRate = SL_BOOLEAN_TRUE;
205 } else if (!strncmp(arg, "-Q", 2)) {
206 deltaRateMs = atoi(&arg[2]);
207 enablePlaybackRate = SL_BOOLEAN_TRUE;
208 } else if (!strcmp(arg, "-r")) {
209 enableReverb = SL_BOOLEAN_TRUE;
210 } else {
211 fprintf(stderr, "option %s ignored\n", arg);
212 }
213 }
214
215 if (argc - i != 1) {
216 fprintf(stderr, "usage: [-b/l] [-8] [-f#] [-n#] [-p#] [-r] %s filename\n", argv[0]);
217 fprintf(stderr, " -b force big-endian byte order (default is native byte order)\n");
218 fprintf(stderr, " -l force little-endian byte order (default is native byte order)\n");
219 fprintf(stderr, " -8 output 8-bits per sample (default is 16-bits per sample)\n");
220 fprintf(stderr, " -f# frames per buffer (default 512)\n");
221 fprintf(stderr, " -n# number of buffers (default 2)\n");
222 fprintf(stderr, " -p# initial playback rate in per mille (default 1000)\n");
223 fprintf(stderr, " -P# final playback rate in per mille (default same as -p#)\n");
224 fprintf(stderr, " -q# magnitude of playback rate changes in per mille (default 1)\n");
225 fprintf(stderr, " -Q# period between playback rate changes in ms (default 50)\n");
226 fprintf(stderr, " -r enable reverb (default disabled)\n");
227 return EXIT_FAILURE;
228 }
229
230 const char *filename = argv[i];
231 //memset(&sfinfo, 0, sizeof(SF_INFO));
232 sfinfo.format = 0;
233 sndfile = sf_open(filename, SFM_READ, &sfinfo);
234 if (NULL == sndfile) {
235 perror(filename);
236 return EXIT_FAILURE;
237 }
238
239 // The sample rate is a lie, but it doesn't actually matter
240 const android::NBAIO_Format nbaio_format = android::Format_from_SR_C(44100, sfinfo.channels);
241
242 // verify the file format
243 switch (sfinfo.channels) {
244 case 1:
245 case 2:
246 break;
247 default:
248 fprintf(stderr, "unsupported channel count %d\n", sfinfo.channels);
249 goto close_sndfile;
250 }
251
252 switch (sfinfo.samplerate) {
253 case 8000:
254 case 11025:
255 case 12000:
256 case 16000:
257 case 22050:
258 case 24000:
259 case 32000:
260 case 44100:
261 case 48000:
262 break;
263 default:
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_PCM_16:
278 case SF_FORMAT_PCM_U8:
279 break;
280 default:
281 fprintf(stderr, "unsupported sub-format 0x%x\n", sfinfo.format & SF_FORMAT_SUBMASK);
282 goto close_sndfile;
283 }
284
285 {
286
287 buffers = (short *) malloc(framesPerBuffer * sfinfo.channels * sizeof(short) * numBuffers);
288
289 // create engine
290 SLresult result;
291 SLObjectItf engineObject;
292 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
293 assert(SL_RESULT_SUCCESS == result);
294 SLEngineItf engineEngine;
295 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
296 assert(SL_RESULT_SUCCESS == result);
297 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
298 assert(SL_RESULT_SUCCESS == result);
299
300 // create output mix
301 SLObjectItf outputMixObject;
302 SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
303 SLboolean req[1] = {SL_BOOLEAN_TRUE};
304 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, enableReverb ? 1 : 0,
305 ids, req);
306 assert(SL_RESULT_SUCCESS == result);
307 result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
308 assert(SL_RESULT_SUCCESS == result);
309
310 // configure environmental reverb on output mix
311 SLEnvironmentalReverbItf mixEnvironmentalReverb = NULL;
312 if (enableReverb) {
313 result = (*outputMixObject)->GetInterface(outputMixObject, SL_IID_ENVIRONMENTALREVERB,
314 &mixEnvironmentalReverb);
315 assert(SL_RESULT_SUCCESS == result);
316 SLEnvironmentalReverbSettings settings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
317 result = (*mixEnvironmentalReverb)->SetEnvironmentalReverbProperties(mixEnvironmentalReverb,
318 &settings);
319 assert(SL_RESULT_SUCCESS == result);
320 }
321
322 // configure audio source
323 SLDataLocator_BufferQueue loc_bufq;
324 loc_bufq.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
325 loc_bufq.numBuffers = numBuffers;
326 SLDataFormat_PCM format_pcm;
327 format_pcm.formatType = SL_DATAFORMAT_PCM;
328 format_pcm.numChannels = sfinfo.channels;
329 format_pcm.samplesPerSec = sfinfo.samplerate * 1000;
330 format_pcm.bitsPerSample = bitsPerSample;
331 format_pcm.containerSize = format_pcm.bitsPerSample;
332 format_pcm.channelMask = 1 == format_pcm.numChannels ? SL_SPEAKER_FRONT_CENTER :
333 SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
334 format_pcm.endianness = byteOrder;
335 SLDataSource audioSrc;
336 audioSrc.pLocator = &loc_bufq;
337 audioSrc.pFormat = &format_pcm;
338
339 // configure audio sink
340 SLDataLocator_OutputMix loc_outmix;
341 loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
342 loc_outmix.outputMix = outputMixObject;
343 SLDataSink audioSnk;
344 audioSnk.pLocator = &loc_outmix;
345 audioSnk.pFormat = NULL;
346
347 // create audio player
348 SLInterfaceID ids2[3] = {SL_IID_BUFFERQUEUE, SL_IID_PLAYBACKRATE, SL_IID_EFFECTSEND};
349 SLboolean req2[3] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
350 SLObjectItf playerObject;
351 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &playerObject, &audioSrc,
352 &audioSnk, enableReverb ? 3 : (enablePlaybackRate ? 2 : 1), ids2, req2);
353 if (SL_RESULT_SUCCESS != result) {
354 fprintf(stderr, "can't create audio player\n");
355 goto no_player;
356 }
357
358 {
359
360 // realize the player
361 result = (*playerObject)->Realize(playerObject, SL_BOOLEAN_FALSE);
362 assert(SL_RESULT_SUCCESS == result);
363
364 // get the effect send interface and enable effect send reverb for this player
365 if (enableReverb) {
366 SLEffectSendItf playerEffectSend;
367 result = (*playerObject)->GetInterface(playerObject, SL_IID_EFFECTSEND, &playerEffectSend);
368 assert(SL_RESULT_SUCCESS == result);
369 result = (*playerEffectSend)->EnableEffectSend(playerEffectSend, mixEnvironmentalReverb,
370 SL_BOOLEAN_TRUE, (SLmillibel) 0);
371 assert(SL_RESULT_SUCCESS == result);
372 }
373
374 // get the playback rate interface and configure the rate
375 SLPlaybackRateItf playerPlaybackRate;
376 SLpermille currentRate = 0;
377 if (enablePlaybackRate) {
378 result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAYBACKRATE,
379 &playerPlaybackRate);
380 assert(SL_RESULT_SUCCESS == result);
381 SLpermille defaultRate;
382 result = (*playerPlaybackRate)->GetRate(playerPlaybackRate, &defaultRate);
383 assert(SL_RESULT_SUCCESS == result);
384 SLuint32 defaultProperties;
385 result = (*playerPlaybackRate)->GetProperties(playerPlaybackRate, &defaultProperties);
386 assert(SL_RESULT_SUCCESS == result);
387 printf("default playback rate %d per mille, properties 0x%x\n", defaultRate,
388 defaultProperties);
389 if (initialRate <= 0) {
390 initialRate = defaultRate;
391 }
392 if (finalRate <= 0) {
393 finalRate = initialRate;
394 }
395 currentRate = defaultRate;
396 if (finalRate == initialRate) {
397 deltaRate = 0;
398 } else if (finalRate < initialRate) {
399 deltaRate = -deltaRate;
400 }
401 if (initialRate != defaultRate) {
402 result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, initialRate);
403 if (SL_RESULT_FEATURE_UNSUPPORTED == result) {
404 fprintf(stderr, "initial playback rate %d is unsupported\n", initialRate);
405 deltaRate = 0;
406 } else if (SL_RESULT_PARAMETER_INVALID == result) {
407 fprintf(stderr, "initial playback rate %d is invalid\n", initialRate);
408 deltaRate = 0;
409 } else {
410 assert(SL_RESULT_SUCCESS == result);
411 currentRate = initialRate;
412 }
413 }
414 }
415
416 // get the play interface
417 SLPlayItf playerPlay;
418 result = (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playerPlay);
419 assert(SL_RESULT_SUCCESS == result);
420
421 // get the buffer queue interface
422 SLBufferQueueItf playerBufferQueue;
423 result = (*playerObject)->GetInterface(playerObject, SL_IID_BUFFERQUEUE,
424 &playerBufferQueue);
425 assert(SL_RESULT_SUCCESS == result);
426
427 // loop until EOF or no more buffers
428 for (which = 0; which < numBuffers; ++which) {
429 short *buffer = &buffers[framesPerBuffer * sfinfo.channels * which];
430 sf_count_t frames = framesPerBuffer;
431 sf_count_t count;
432 count = sf_readf_short(sndfile, buffer, frames);
433 if (0 >= count) {
434 eof = SL_BOOLEAN_TRUE;
435 break;
436 }
437
438 // enqueue a buffer
439 SLuint32 nbytes = count * sfinfo.channels * sizeof(short);
440 if (byteOrder != nativeByteOrder) {
441 swab(buffer, buffer, nbytes);
442 }
443 if (bitsPerSample == 8) {
444 squeeze(buffer, (unsigned char *) buffer, nbytes);
445 nbytes /= 2;
446 }
447 result = (*playerBufferQueue)->Enqueue(playerBufferQueue, buffer, nbytes);
448 assert(SL_RESULT_SUCCESS == result);
449 }
450 if (which >= numBuffers) {
451 which = 0;
452 }
453
454 // register a callback on the buffer queue
455 result = (*playerBufferQueue)->RegisterCallback(playerBufferQueue, callback, NULL);
456 assert(SL_RESULT_SUCCESS == result);
457
458 pipeWriter = new android::MonoPipe(16384, nbaio_format, false /*writeCanBlock*/);
459 android::NBAIO_Format offer = nbaio_format;
460 size_t numCounterOffers = 0;
461 ssize_t neg = pipeWriter->negotiate(&offer, 1, NULL, numCounterOffers);
462 assert(0 == neg);
463 pipeReader = new android::MonoPipeReader(pipeWriter);
464 numCounterOffers = 0;
465 neg = pipeReader->negotiate(&offer, 1, NULL, numCounterOffers);
466 assert(0 == neg);
467
468 // create thread to read from file
469 pthread_t thread;
470 int ok = pthread_create(&thread, (const pthread_attr_t *) NULL, file_reader_loop, NULL);
471 assert(0 == ok);
472
473 // give thread a head start so that the pipe is initially filled
474 sleep(1);
475
476 // set the player's state to playing
477 result = (*playerPlay)->SetPlayState(playerPlay, SL_PLAYSTATE_PLAYING);
478 assert(SL_RESULT_SUCCESS == result);
479
480 // get the initial time
481 struct timespec prevTs;
482 clock_gettime(CLOCK_MONOTONIC, &prevTs);
483 long elapsedNs = 0;
484 long deltaRateNs = deltaRateMs * 1000000;
485
486 // wait until the buffer queue is empty
487 SLBufferQueueState bufqstate;
488 for (;;) {
489 result = (*playerBufferQueue)->GetState(playerBufferQueue, &bufqstate);
490 assert(SL_RESULT_SUCCESS == result);
491 if (0 >= bufqstate.count) {
492 break;
493 }
494 if (!enablePlaybackRate || deltaRate == 0) {
495 sleep(1);
496 } else {
497 struct timespec curTs;
498 clock_gettime(CLOCK_MONOTONIC, &curTs);
499 elapsedNs += (curTs.tv_sec - prevTs.tv_sec) * 1000000000 +
500 // this term can be negative
501 (curTs.tv_nsec - prevTs.tv_nsec);
502 prevTs = curTs;
503 if (elapsedNs < deltaRateNs) {
504 usleep((deltaRateNs - elapsedNs) / 1000);
505 continue;
506 }
507 elapsedNs -= deltaRateNs;
508 SLpermille nextRate = currentRate + deltaRate;
509 result = (*playerPlaybackRate)->SetRate(playerPlaybackRate, nextRate);
510 if (SL_RESULT_SUCCESS != result) {
511 fprintf(stderr, "next playback rate %d is unsupported\n", nextRate);
512 } else if (SL_RESULT_PARAMETER_INVALID == result) {
513 fprintf(stderr, "next playback rate %d is invalid\n", nextRate);
514 } else {
515 assert(SL_RESULT_SUCCESS == result);
516 }
517 currentRate = nextRate;
518 if (currentRate >= max(initialRate, finalRate)) {
519 currentRate = max(initialRate, finalRate);
520 deltaRate = -abs(deltaRate);
521 } else if (currentRate <= min(initialRate, finalRate)) {
522 currentRate = min(initialRate, finalRate);
523 deltaRate = abs(deltaRate);
524 }
525 }
526 }
527
528 // destroy audio player
529 (*playerObject)->Destroy(playerObject);
530
531 }
532
533 no_player:
534
535 // destroy output mix
536 (*outputMixObject)->Destroy(outputMixObject);
537
538 // destroy engine
539 (*engineObject)->Destroy(engineObject);
540
541 }
542
543 close_sndfile:
544
545 (void) sf_close(sndfile);
546
547 return EXIT_SUCCESS;
548 }
549