SDL_openslES.c (24490B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20 */ 21 #include "../../SDL_internal.h" 22 23 #if SDL_AUDIO_DRIVER_OPENSLES 24 25 /* For more discussion of low latency audio on Android, see this: 26 https://googlesamples.github.io/android-audio-high-performance/guides/opensl_es.html 27 */ 28 29 #include "SDL_audio.h" 30 #include "../SDL_audio_c.h" 31 #include "../../core/android/SDL_android.h" 32 #include "SDL_openslES.h" 33 34 /* for native audio */ 35 #include <SLES/OpenSLES.h> 36 #include <SLES/OpenSLES_Android.h> 37 38 #include <android/log.h> 39 40 #if 0 41 #define LOG_TAG "SDL_openslES" 42 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) 43 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) 44 //#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__) 45 #define LOGV(...) 46 #else 47 #define LOGE(...) 48 #define LOGI(...) 49 #define LOGV(...) 50 #endif 51 52 /* 53 #define SL_SPEAKER_FRONT_LEFT ((SLuint32) 0x00000001) 54 #define SL_SPEAKER_FRONT_RIGHT ((SLuint32) 0x00000002) 55 #define SL_SPEAKER_FRONT_CENTER ((SLuint32) 0x00000004) 56 #define SL_SPEAKER_LOW_FREQUENCY ((SLuint32) 0x00000008) 57 #define SL_SPEAKER_BACK_LEFT ((SLuint32) 0x00000010) 58 #define SL_SPEAKER_BACK_RIGHT ((SLuint32) 0x00000020) 59 #define SL_SPEAKER_FRONT_LEFT_OF_CENTER ((SLuint32) 0x00000040) 60 #define SL_SPEAKER_FRONT_RIGHT_OF_CENTER ((SLuint32) 0x00000080) 61 #define SL_SPEAKER_BACK_CENTER ((SLuint32) 0x00000100) 62 #define SL_SPEAKER_SIDE_LEFT ((SLuint32) 0x00000200) 63 #define SL_SPEAKER_SIDE_RIGHT ((SLuint32) 0x00000400) 64 #define SL_SPEAKER_TOP_CENTER ((SLuint32) 0x00000800) 65 #define SL_SPEAKER_TOP_FRONT_LEFT ((SLuint32) 0x00001000) 66 #define SL_SPEAKER_TOP_FRONT_CENTER ((SLuint32) 0x00002000) 67 #define SL_SPEAKER_TOP_FRONT_RIGHT ((SLuint32) 0x00004000) 68 #define SL_SPEAKER_TOP_BACK_LEFT ((SLuint32) 0x00008000) 69 #define SL_SPEAKER_TOP_BACK_CENTER ((SLuint32) 0x00010000) 70 #define SL_SPEAKER_TOP_BACK_RIGHT ((SLuint32) 0x00020000) 71 */ 72 #define SL_ANDROID_SPEAKER_STEREO (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) 73 #define SL_ANDROID_SPEAKER_QUAD (SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT) 74 #define SL_ANDROID_SPEAKER_5DOT1 (SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY) 75 #define SL_ANDROID_SPEAKER_7DOT1 (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT) 76 77 /* engine interfaces */ 78 static SLObjectItf engineObject; 79 static SLEngineItf engineEngine; 80 81 /* output mix interfaces */ 82 static SLObjectItf outputMixObject; 83 84 /* buffer queue player interfaces */ 85 static SLObjectItf bqPlayerObject; 86 static SLPlayItf bqPlayerPlay; 87 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; 88 #if 0 89 static SLVolumeItf bqPlayerVolume; 90 #endif 91 92 /* recorder interfaces */ 93 static SLObjectItf recorderObject; 94 static SLRecordItf recorderRecord; 95 static SLAndroidSimpleBufferQueueItf recorderBufferQueue; 96 97 #if 0 98 static const char *sldevaudiorecorderstr = "SLES Audio Recorder"; 99 static const char *sldevaudioplayerstr = "SLES Audio Player"; 100 101 #define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr 102 #define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr 103 static void openslES_DetectDevices( int iscapture ) 104 { 105 LOGI( "openSLES_DetectDevices()" ); 106 if ( iscapture ) 107 addfn( SLES_DEV_AUDIO_RECORDER ); 108 else 109 addfn( SLES_DEV_AUDIO_PLAYER ); 110 } 111 #endif 112 113 static void openslES_DestroyEngine(void) 114 { 115 LOGI("openslES_DestroyEngine()"); 116 117 /* destroy output mix object, and invalidate all associated interfaces */ 118 if (outputMixObject != NULL) { 119 (*outputMixObject)->Destroy(outputMixObject); 120 outputMixObject = NULL; 121 } 122 123 /* destroy engine object, and invalidate all associated interfaces */ 124 if (engineObject != NULL) { 125 (*engineObject)->Destroy(engineObject); 126 engineObject = NULL; 127 engineEngine = NULL; 128 } 129 } 130 131 static int 132 openslES_CreateEngine(void) 133 { 134 SLresult result; 135 136 LOGI("openSLES_CreateEngine()"); 137 138 /* create engine */ 139 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 140 if (SL_RESULT_SUCCESS != result) { 141 LOGE("slCreateEngine failed: %d", result); 142 goto error; 143 } 144 LOGI("slCreateEngine OK"); 145 146 /* realize the engine */ 147 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 148 if (SL_RESULT_SUCCESS != result) { 149 LOGE("RealizeEngine failed: %d", result); 150 goto error; 151 } 152 LOGI("RealizeEngine OK"); 153 154 /* get the engine interface, which is needed in order to create other objects */ 155 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 156 if (SL_RESULT_SUCCESS != result) { 157 LOGE("EngineGetInterface failed: %d", result); 158 goto error; 159 } 160 LOGI("EngineGetInterface OK"); 161 162 /* create output mix */ 163 const SLInterfaceID ids[1] = { SL_IID_VOLUME }; 164 const SLboolean req[1] = { SL_BOOLEAN_FALSE }; 165 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req); 166 if (SL_RESULT_SUCCESS != result) { 167 LOGE("CreateOutputMix failed: %d", result); 168 goto error; 169 } 170 LOGI("CreateOutputMix OK"); 171 172 /* realize the output mix */ 173 result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); 174 if (SL_RESULT_SUCCESS != result) { 175 LOGE("RealizeOutputMix failed: %d", result); 176 goto error; 177 } 178 return 1; 179 180 error: 181 openslES_DestroyEngine(); 182 return 0; 183 } 184 185 /* this callback handler is called every time a buffer finishes recording */ 186 static void 187 bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) 188 { 189 struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context; 190 191 LOGV("SLES: Recording Callback"); 192 SDL_SemPost(audiodata->playsem); 193 } 194 195 static void 196 openslES_DestroyPCMRecorder(_THIS) 197 { 198 struct SDL_PrivateAudioData *audiodata = this->hidden; 199 SLresult result; 200 201 /* stop recording */ 202 if (recorderRecord != NULL) { 203 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); 204 if (SL_RESULT_SUCCESS != result) { 205 LOGE("SetRecordState stopped: %d", result); 206 } 207 } 208 209 /* destroy audio recorder object, and invalidate all associated interfaces */ 210 if (recorderObject != NULL) { 211 (*recorderObject)->Destroy(recorderObject); 212 recorderObject = NULL; 213 recorderRecord = NULL; 214 recorderBufferQueue = NULL; 215 } 216 217 if (audiodata->playsem) { 218 SDL_DestroySemaphore(audiodata->playsem); 219 audiodata->playsem = NULL; 220 } 221 222 if (audiodata->mixbuff) { 223 SDL_free(audiodata->mixbuff); 224 } 225 } 226 227 static int 228 openslES_CreatePCMRecorder(_THIS) 229 { 230 struct SDL_PrivateAudioData *audiodata = this->hidden; 231 SLDataFormat_PCM format_pcm; 232 SLresult result; 233 int i; 234 235 if (!Android_JNI_RequestPermission("android.permission.RECORD_AUDIO")) { 236 LOGE("This app doesn't have RECORD_AUDIO permission"); 237 return SDL_SetError("This app doesn't have RECORD_AUDIO permission"); 238 } 239 240 /* Just go with signed 16-bit audio as it's the most compatible */ 241 this->spec.format = AUDIO_S16SYS; 242 this->spec.channels = 1; 243 /*this->spec.freq = SL_SAMPLINGRATE_16 / 1000;*/ 244 245 /* Update the fragment size as size in bytes */ 246 SDL_CalculateAudioSpec(&this->spec); 247 248 LOGI("Try to open %u hz %u bit chan %u %s samples %u", 249 this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format), 250 this->spec.channels, (this->spec.format & 0x1000) ? "BE" : "LE", this->spec.samples); 251 252 /* configure audio source */ 253 SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL}; 254 SLDataSource audioSrc = {&loc_dev, NULL}; 255 256 /* configure audio sink */ 257 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS }; 258 259 format_pcm.formatType = SL_DATAFORMAT_PCM; 260 format_pcm.numChannels = this->spec.channels; 261 format_pcm.samplesPerSec = this->spec.freq * 1000; /* / kilo Hz to milli Hz */ 262 format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); 263 format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format); 264 format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 265 format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER; 266 267 SLDataSink audioSnk = { &loc_bufq, &format_pcm }; 268 269 /* create audio recorder */ 270 /* (requires the RECORD_AUDIO permission) */ 271 const SLInterfaceID ids[1] = { 272 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 273 }; 274 const SLboolean req[1] = { 275 SL_BOOLEAN_TRUE, 276 }; 277 278 result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc, &audioSnk, 1, ids, req); 279 if (SL_RESULT_SUCCESS != result) { 280 LOGE("CreateAudioRecorder failed: %d", result); 281 goto failed; 282 } 283 284 /* realize the recorder */ 285 result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE); 286 if (SL_RESULT_SUCCESS != result) { 287 LOGE("RealizeAudioPlayer failed: %d", result); 288 goto failed; 289 } 290 291 /* get the record interface */ 292 result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord); 293 if (SL_RESULT_SUCCESS != result) { 294 LOGE("SL_IID_RECORD interface get failed: %d", result); 295 goto failed; 296 } 297 298 /* get the buffer queue interface */ 299 result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue); 300 if (SL_RESULT_SUCCESS != result) { 301 LOGE("SL_IID_BUFFERQUEUE interface get failed: %d", result); 302 goto failed; 303 } 304 305 /* register callback on the buffer queue */ 306 /* context is '(SDL_PrivateAudioData *)this->hidden' */ 307 result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, bqRecorderCallback, this->hidden); 308 if (SL_RESULT_SUCCESS != result) { 309 LOGE("RegisterCallback failed: %d", result); 310 goto failed; 311 } 312 313 /* Create the audio buffer semaphore */ 314 audiodata->playsem = SDL_CreateSemaphore(0); 315 if (!audiodata->playsem) { 316 LOGE("cannot create Semaphore!"); 317 goto failed; 318 } 319 320 /* Create the sound buffers */ 321 audiodata->mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size); 322 if (audiodata->mixbuff == NULL) { 323 LOGE("mixbuffer allocate - out of memory"); 324 goto failed; 325 } 326 327 for (i = 0; i < NUM_BUFFERS; i++) { 328 audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size; 329 } 330 331 /* in case already recording, stop recording and clear buffer queue */ 332 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); 333 if (SL_RESULT_SUCCESS != result) { 334 LOGE("Record set state failed: %d", result); 335 goto failed; 336 } 337 338 /* enqueue empty buffers to be filled by the recorder */ 339 for (i = 0; i < NUM_BUFFERS; i++) { 340 result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, audiodata->pmixbuff[i], this->spec.size); 341 if (SL_RESULT_SUCCESS != result) { 342 LOGE("Record enqueue buffers failed: %d", result); 343 goto failed; 344 } 345 } 346 347 /* start recording */ 348 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING); 349 if (SL_RESULT_SUCCESS != result) { 350 LOGE("Record set state failed: %d", result); 351 goto failed; 352 } 353 354 return 0; 355 356 failed: 357 358 openslES_DestroyPCMRecorder(this); 359 360 return SDL_SetError("Open device failed!"); 361 } 362 363 /* this callback handler is called every time a buffer finishes playing */ 364 static void 365 bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) 366 { 367 struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context; 368 369 LOGV("SLES: Playback Callback"); 370 SDL_SemPost(audiodata->playsem); 371 } 372 373 static void 374 openslES_DestroyPCMPlayer(_THIS) 375 { 376 struct SDL_PrivateAudioData *audiodata = this->hidden; 377 SLresult result; 378 379 /* set the player's state to 'stopped' */ 380 if (bqPlayerPlay != NULL) { 381 result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); 382 if (SL_RESULT_SUCCESS != result) { 383 LOGE("SetPlayState stopped failed: %d", result); 384 } 385 } 386 387 /* destroy buffer queue audio player object, and invalidate all associated interfaces */ 388 if (bqPlayerObject != NULL) { 389 390 (*bqPlayerObject)->Destroy(bqPlayerObject); 391 392 bqPlayerObject = NULL; 393 bqPlayerPlay = NULL; 394 bqPlayerBufferQueue = NULL; 395 } 396 397 if (audiodata->playsem) { 398 SDL_DestroySemaphore(audiodata->playsem); 399 audiodata->playsem = NULL; 400 } 401 402 if (audiodata->mixbuff) { 403 SDL_free(audiodata->mixbuff); 404 } 405 } 406 407 static int 408 openslES_CreatePCMPlayer(_THIS) 409 { 410 struct SDL_PrivateAudioData *audiodata = this->hidden; 411 SLDataFormat_PCM format_pcm; 412 SLresult result; 413 int i; 414 415 /* If we want to add floating point audio support (requires API level 21) 416 it can be done as described here: 417 https://developer.android.com/ndk/guides/audio/opensl/android-extensions.html#floating-point 418 */ 419 #if 1 420 /* Just go with signed 16-bit audio as it's the most compatible */ 421 this->spec.format = AUDIO_S16SYS; 422 #else 423 SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); 424 while (test_format != 0) { 425 if (SDL_AUDIO_ISSIGNED(test_format) && SDL_AUDIO_ISINT(test_format)) { 426 break; 427 } 428 test_format = SDL_NextAudioFormat(); 429 } 430 431 if (test_format == 0) { 432 /* Didn't find a compatible format : */ 433 LOGI( "No compatible audio format, using signed 16-bit audio" ); 434 test_format = AUDIO_S16SYS; 435 } 436 this->spec.format = test_format; 437 #endif 438 439 /* Update the fragment size as size in bytes */ 440 SDL_CalculateAudioSpec(&this->spec); 441 442 LOGI("Try to open %u hz %u bit chan %u %s samples %u", 443 this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format), 444 this->spec.channels, (this->spec.format & 0x1000) ? "BE" : "LE", this->spec.samples); 445 446 /* configure audio source */ 447 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS }; 448 449 format_pcm.formatType = SL_DATAFORMAT_PCM; 450 format_pcm.numChannels = this->spec.channels; 451 format_pcm.samplesPerSec = this->spec.freq * 1000; /* / kilo Hz to milli Hz */ 452 format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); 453 format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format); 454 455 if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) { 456 format_pcm.endianness = SL_BYTEORDER_BIGENDIAN; 457 } else { 458 format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 459 } 460 461 switch (this->spec.channels) 462 { 463 case 1: 464 format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT; 465 break; 466 case 2: 467 format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO; 468 break; 469 case 3: 470 format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_FRONT_CENTER; 471 break; 472 case 4: 473 format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD; 474 break; 475 case 5: 476 format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER; 477 break; 478 case 6: 479 format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1; 480 break; 481 case 7: 482 format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER; 483 break; 484 case 8: 485 format_pcm.channelMask = SL_ANDROID_SPEAKER_7DOT1; 486 break; 487 default: 488 /* Unknown number of channels, fall back to stereo */ 489 this->spec.channels = 2; 490 format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 491 break; 492 } 493 494 SLDataSource audioSrc = { &loc_bufq, &format_pcm }; 495 496 /* configure audio sink */ 497 SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject }; 498 SLDataSink audioSnk = { &loc_outmix, NULL }; 499 500 /* create audio player */ 501 const SLInterfaceID ids[2] = { 502 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 503 SL_IID_VOLUME 504 }; 505 506 const SLboolean req[2] = { 507 SL_BOOLEAN_TRUE, 508 SL_BOOLEAN_FALSE, 509 }; 510 511 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); 512 if (SL_RESULT_SUCCESS != result) { 513 LOGE("CreateAudioPlayer failed: %d", result); 514 goto failed; 515 } 516 517 /* realize the player */ 518 result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); 519 if (SL_RESULT_SUCCESS != result) { 520 LOGE("RealizeAudioPlayer failed: %d", result); 521 goto failed; 522 } 523 524 /* get the play interface */ 525 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); 526 if (SL_RESULT_SUCCESS != result) { 527 LOGE("SL_IID_PLAY interface get failed: %d", result); 528 goto failed; 529 } 530 531 /* get the buffer queue interface */ 532 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue); 533 if (SL_RESULT_SUCCESS != result) { 534 LOGE("SL_IID_BUFFERQUEUE interface get failed: %d", result); 535 goto failed; 536 } 537 538 /* register callback on the buffer queue */ 539 /* context is '(SDL_PrivateAudioData *)this->hidden' */ 540 result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, this->hidden); 541 if (SL_RESULT_SUCCESS != result) { 542 LOGE("RegisterCallback failed: %d", result); 543 goto failed; 544 } 545 546 #if 0 547 /* get the volume interface */ 548 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); 549 if (SL_RESULT_SUCCESS != result) { 550 LOGE("SL_IID_VOLUME interface get failed: %d", result); 551 /* goto failed; */ 552 } 553 #endif 554 555 /* Create the audio buffer semaphore */ 556 audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1); 557 if (!audiodata->playsem) { 558 LOGE("cannot create Semaphore!"); 559 goto failed; 560 } 561 562 /* Create the sound buffers */ 563 audiodata->mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size); 564 if (audiodata->mixbuff == NULL) { 565 LOGE("mixbuffer allocate - out of memory"); 566 goto failed; 567 } 568 569 for (i = 0; i < NUM_BUFFERS; i++) { 570 audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size; 571 } 572 573 /* set the player's state to playing */ 574 result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); 575 if (SL_RESULT_SUCCESS != result) { 576 LOGE("Play set state failed: %d", result); 577 goto failed; 578 } 579 580 return 0; 581 582 failed: 583 584 openslES_DestroyPCMPlayer(this); 585 586 return SDL_SetError("Open device failed!"); 587 } 588 589 static int 590 openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) 591 { 592 this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden)); 593 if (this->hidden == NULL) { 594 return SDL_OutOfMemory(); 595 } 596 597 if (iscapture) { 598 LOGI("openslES_OpenDevice() %s for capture", devname); 599 return openslES_CreatePCMRecorder(this); 600 } else { 601 LOGI("openslES_OpenDevice() %s for playing", devname); 602 return openslES_CreatePCMPlayer(this); 603 } 604 } 605 606 static void 607 openslES_WaitDevice(_THIS) 608 { 609 struct SDL_PrivateAudioData *audiodata = this->hidden; 610 611 LOGV("openslES_WaitDevice()"); 612 613 /* Wait for an audio chunk to finish */ 614 SDL_SemWait(audiodata->playsem); 615 } 616 617 static void 618 openslES_PlayDevice(_THIS) 619 { 620 struct SDL_PrivateAudioData *audiodata = this->hidden; 621 SLresult result; 622 623 LOGV("======openslES_PlayDevice()======"); 624 625 /* Queue it up */ 626 result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size); 627 628 audiodata->next_buffer++; 629 if (audiodata->next_buffer >= NUM_BUFFERS) { 630 audiodata->next_buffer = 0; 631 } 632 633 /* If Enqueue fails, callback won't be called. 634 * Post the semphore, not to run out of buffer */ 635 if (SL_RESULT_SUCCESS != result) { 636 SDL_SemPost(audiodata->playsem); 637 } 638 } 639 640 /*/ n playn sem */ 641 /* getbuf 0 - 1 */ 642 /* fill buff 0 - 1 */ 643 /* play 0 - 0 1 */ 644 /* wait 1 0 0 */ 645 /* getbuf 1 0 0 */ 646 /* fill buff 1 0 0 */ 647 /* play 0 0 0 */ 648 /* wait */ 649 /* */ 650 /* okay.. */ 651 652 static Uint8 * 653 openslES_GetDeviceBuf(_THIS) 654 { 655 struct SDL_PrivateAudioData *audiodata = this->hidden; 656 657 LOGV("openslES_GetDeviceBuf()"); 658 return audiodata->pmixbuff[audiodata->next_buffer]; 659 } 660 661 static int 662 openslES_CaptureFromDevice(_THIS, void *buffer, int buflen) 663 { 664 struct SDL_PrivateAudioData *audiodata = this->hidden; 665 SLresult result; 666 667 /* Wait for new recorded data */ 668 SDL_SemWait(audiodata->playsem); 669 670 /* Copy it to the output buffer */ 671 SDL_assert(buflen == this->spec.size); 672 SDL_memcpy(buffer, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size); 673 674 /* Re-enqueue the buffer */ 675 result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size); 676 if (SL_RESULT_SUCCESS != result) { 677 LOGE("Record enqueue buffers failed: %d", result); 678 return -1; 679 } 680 681 audiodata->next_buffer++; 682 if (audiodata->next_buffer >= NUM_BUFFERS) { 683 audiodata->next_buffer = 0; 684 } 685 686 return this->spec.size; 687 } 688 689 static void 690 openslES_CloseDevice(_THIS) 691 { 692 /* struct SDL_PrivateAudioData *audiodata = this->hidden; */ 693 694 if (this->iscapture) { 695 LOGI("openslES_CloseDevice() for capture"); 696 openslES_DestroyPCMRecorder(this); 697 } else { 698 LOGI("openslES_CloseDevice() for playing"); 699 openslES_DestroyPCMPlayer(this); 700 } 701 702 SDL_free(this->hidden); 703 } 704 705 static int 706 openslES_Init(SDL_AudioDriverImpl * impl) 707 { 708 LOGI("openslES_Init() called"); 709 710 if (!openslES_CreateEngine()) { 711 return 0; 712 } 713 714 LOGI("openslES_Init() - set pointers"); 715 716 /* Set the function pointers */ 717 /* impl->DetectDevices = openslES_DetectDevices; */ 718 impl->OpenDevice = openslES_OpenDevice; 719 impl->WaitDevice = openslES_WaitDevice; 720 impl->PlayDevice = openslES_PlayDevice; 721 impl->GetDeviceBuf = openslES_GetDeviceBuf; 722 impl->CaptureFromDevice = openslES_CaptureFromDevice; 723 impl->CloseDevice = openslES_CloseDevice; 724 impl->Deinitialize = openslES_DestroyEngine; 725 726 /* and the capabilities */ 727 impl->HasCaptureSupport = 1; 728 impl->OnlyHasDefaultOutputDevice = 1; 729 impl->OnlyHasDefaultCaptureDevice = 1; 730 731 LOGI("openslES_Init() - success"); 732 733 /* this audio target is available. */ 734 return 1; 735 } 736 737 AudioBootStrap openslES_bootstrap = { 738 "openslES", "opensl ES audio driver", openslES_Init, 0 739 }; 740 741 void openslES_ResumeDevices(void) 742 { 743 if (bqPlayerPlay != NULL) { 744 /* set the player's state to 'playing' */ 745 SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); 746 if (SL_RESULT_SUCCESS != result) { 747 LOGE("openslES_ResumeDevices failed: %d", result); 748 } 749 } 750 } 751 752 void openslES_PauseDevices(void) 753 { 754 if (bqPlayerPlay != NULL) { 755 /* set the player's state to 'paused' */ 756 SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED); 757 if (SL_RESULT_SUCCESS != result) { 758 LOGE("openslES_PauseDevices failed: %d", result); 759 } 760 } 761 } 762 763 #endif /* SDL_AUDIO_DRIVER_OPENSLES */ 764 765 /* vi: set ts=4 sw=4 expandtab: */