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