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