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