Simple Directmedia Layer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 807 lines 27 kB view raw
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2024 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#ifdef 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#include "../SDL_sysaudio.h" 29#include "SDL_openslES.h" 30 31#include "../../core/android/SDL_android.h" 32#include <SLES/OpenSLES.h> 33#include <SLES/OpenSLES_Android.h> 34#include <android/log.h> 35 36 37#define NUM_BUFFERS 2 // -- Don't lower this! 38 39struct SDL_PrivateAudioData 40{ 41 Uint8 *mixbuff; 42 int next_buffer; 43 Uint8 *pmixbuff[NUM_BUFFERS]; 44 SDL_Semaphore *playsem; 45}; 46 47#if 0 48#define LOG_TAG "SDL_openslES" 49#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 50#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 51//#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__) 52#define LOGV(...) 53#else 54#define LOGE(...) 55#define LOGI(...) 56#define LOGV(...) 57#endif 58 59/* 60#define SL_SPEAKER_FRONT_LEFT ((SLuint32) 0x00000001) 61#define SL_SPEAKER_FRONT_RIGHT ((SLuint32) 0x00000002) 62#define SL_SPEAKER_FRONT_CENTER ((SLuint32) 0x00000004) 63#define SL_SPEAKER_LOW_FREQUENCY ((SLuint32) 0x00000008) 64#define SL_SPEAKER_BACK_LEFT ((SLuint32) 0x00000010) 65#define SL_SPEAKER_BACK_RIGHT ((SLuint32) 0x00000020) 66#define SL_SPEAKER_FRONT_LEFT_OF_CENTER ((SLuint32) 0x00000040) 67#define SL_SPEAKER_FRONT_RIGHT_OF_CENTER ((SLuint32) 0x00000080) 68#define SL_SPEAKER_BACK_CENTER ((SLuint32) 0x00000100) 69#define SL_SPEAKER_SIDE_LEFT ((SLuint32) 0x00000200) 70#define SL_SPEAKER_SIDE_RIGHT ((SLuint32) 0x00000400) 71#define SL_SPEAKER_TOP_CENTER ((SLuint32) 0x00000800) 72#define SL_SPEAKER_TOP_FRONT_LEFT ((SLuint32) 0x00001000) 73#define SL_SPEAKER_TOP_FRONT_CENTER ((SLuint32) 0x00002000) 74#define SL_SPEAKER_TOP_FRONT_RIGHT ((SLuint32) 0x00004000) 75#define SL_SPEAKER_TOP_BACK_LEFT ((SLuint32) 0x00008000) 76#define SL_SPEAKER_TOP_BACK_CENTER ((SLuint32) 0x00010000) 77#define SL_SPEAKER_TOP_BACK_RIGHT ((SLuint32) 0x00020000) 78*/ 79#define SL_ANDROID_SPEAKER_STEREO (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) 80#define SL_ANDROID_SPEAKER_QUAD (SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT) 81#define SL_ANDROID_SPEAKER_5DOT1 (SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY) 82#define SL_ANDROID_SPEAKER_7DOT1 (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT) 83 84// engine interfaces 85static SLObjectItf engineObject = NULL; 86static SLEngineItf engineEngine = NULL; 87 88// output mix interfaces 89static SLObjectItf outputMixObject = NULL; 90 91// buffer queue player interfaces 92static SLObjectItf bqPlayerObject = NULL; 93static SLPlayItf bqPlayerPlay = NULL; 94static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue = NULL; 95#if 0 96static SLVolumeItf bqPlayerVolume; 97#endif 98 99// recorder interfaces 100static SLObjectItf recorderObject = NULL; 101static SLRecordItf recorderRecord = NULL; 102static SLAndroidSimpleBufferQueueItf recorderBufferQueue = NULL; 103 104#if 0 105static const char *sldevaudiorecorderstr = "SLES Audio Recorder"; 106static const char *sldevaudioplayerstr = "SLES Audio Player"; 107 108#define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr 109#define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr 110static void OPENSLES_DetectDevices( int recording ) 111{ 112 LOGI( "openSLES_DetectDevices()" ); 113 if ( recording ) 114 addfn( SLES_DEV_AUDIO_RECORDER ); 115 else 116 addfn( SLES_DEV_AUDIO_PLAYER ); 117} 118#endif 119 120static void OPENSLES_DestroyEngine(void) 121{ 122 LOGI("OPENSLES_DestroyEngine()"); 123 124 // destroy output mix object, and invalidate all associated interfaces 125 if (outputMixObject != NULL) { 126 (*outputMixObject)->Destroy(outputMixObject); 127 outputMixObject = NULL; 128 } 129 130 // destroy engine object, and invalidate all associated interfaces 131 if (engineObject != NULL) { 132 (*engineObject)->Destroy(engineObject); 133 engineObject = NULL; 134 engineEngine = NULL; 135 } 136} 137 138static bool OPENSLES_CreateEngine(void) 139{ 140 const SLInterfaceID ids[1] = { SL_IID_VOLUME }; 141 const SLboolean req[1] = { SL_BOOLEAN_FALSE }; 142 SLresult result; 143 144 LOGI("openSLES_CreateEngine()"); 145 146 // create engine 147 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL); 148 if (SL_RESULT_SUCCESS != result) { 149 LOGE("slCreateEngine failed: %d", result); 150 goto error; 151 } 152 LOGI("slCreateEngine OK"); 153 154 // realize the engine 155 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); 156 if (SL_RESULT_SUCCESS != result) { 157 LOGE("RealizeEngine failed: %d", result); 158 goto error; 159 } 160 LOGI("RealizeEngine OK"); 161 162 // get the engine interface, which is needed in order to create other objects 163 result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); 164 if (SL_RESULT_SUCCESS != result) { 165 LOGE("EngineGetInterface failed: %d", result); 166 goto error; 167 } 168 LOGI("EngineGetInterface OK"); 169 170 // create output mix 171 result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req); 172 if (SL_RESULT_SUCCESS != result) { 173 LOGE("CreateOutputMix failed: %d", result); 174 goto error; 175 } 176 LOGI("CreateOutputMix OK"); 177 178 // realize the output mix 179 result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE); 180 if (SL_RESULT_SUCCESS != result) { 181 LOGE("RealizeOutputMix failed: %d", result); 182 goto error; 183 } 184 return true; 185 186error: 187 OPENSLES_DestroyEngine(); 188 return false; 189} 190 191// this callback handler is called every time a buffer finishes recording 192static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) 193{ 194 struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *)context; 195 196 LOGV("SLES: Recording Callback"); 197 SDL_SignalSemaphore(audiodata->playsem); 198} 199 200static void OPENSLES_DestroyPCMRecorder(SDL_AudioDevice *device) 201{ 202 struct SDL_PrivateAudioData *audiodata = device->hidden; 203 SLresult result; 204 205 // stop recording 206 if (recorderRecord != NULL) { 207 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); 208 if (SL_RESULT_SUCCESS != result) { 209 LOGE("SetRecordState stopped: %d", result); 210 } 211 } 212 213 // destroy audio recorder object, and invalidate all associated interfaces 214 if (recorderObject != NULL) { 215 (*recorderObject)->Destroy(recorderObject); 216 recorderObject = NULL; 217 recorderRecord = NULL; 218 recorderBufferQueue = NULL; 219 } 220 221 if (audiodata->playsem) { 222 SDL_DestroySemaphore(audiodata->playsem); 223 audiodata->playsem = NULL; 224 } 225 226 if (audiodata->mixbuff) { 227 SDL_free(audiodata->mixbuff); 228 } 229} 230 231// !!! FIXME: make this non-blocking! 232static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, bool granted) 233{ 234 SDL_SetAtomicInt((SDL_AtomicInt *) userdata, granted ? 1 : -1); 235} 236 237static bool OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) 238{ 239 struct SDL_PrivateAudioData *audiodata = device->hidden; 240 SLDataFormat_PCM format_pcm; 241 SLDataLocator_AndroidSimpleBufferQueue loc_bufq; 242 SLDataSink audioSnk; 243 SLDataLocator_IODevice loc_dev; 244 SLDataSource audioSrc; 245 const SLInterfaceID ids[1] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE }; 246 const SLboolean req[1] = { SL_BOOLEAN_TRUE }; 247 SLresult result; 248 int i; 249 250 // !!! FIXME: make this non-blocking! 251 { 252 SDL_AtomicInt permission_response; 253 SDL_SetAtomicInt(&permission_response, 0); 254 if (!SDL_RequestAndroidPermission("android.permission.RECORD_AUDIO", RequestAndroidPermissionBlockingCallback, &permission_response)) { 255 return false; 256 } 257 258 while (SDL_GetAtomicInt(&permission_response) == 0) { 259 SDL_Delay(10); 260 } 261 262 if (SDL_GetAtomicInt(&permission_response) < 0) { 263 LOGE("This app doesn't have RECORD_AUDIO permission"); 264 return SDL_SetError("This app doesn't have RECORD_AUDIO permission"); 265 } 266 } 267 268 // Just go with signed 16-bit audio as it's the most compatible 269 device->spec.format = SDL_AUDIO_S16; 270 device->spec.channels = 1; 271 //device->spec.freq = SL_SAMPLINGRATE_16 / 1000;*/ 272 273 // Update the fragment size as size in bytes 274 SDL_UpdatedAudioDeviceFormat(device); 275 276 LOGI("Try to open %u hz %u bit %u channels %s samples %u", 277 device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format), 278 device->spec.channels, (device->spec.format & 0x1000) ? "BE" : "LE", device->sample_frames); 279 280 // configure audio source 281 loc_dev.locatorType = SL_DATALOCATOR_IODEVICE; 282 loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT; 283 loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; 284 loc_dev.device = NULL; 285 audioSrc.pLocator = &loc_dev; 286 audioSrc.pFormat = NULL; 287 288 // configure audio sink 289 loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 290 loc_bufq.numBuffers = NUM_BUFFERS; 291 292 format_pcm.formatType = SL_DATAFORMAT_PCM; 293 format_pcm.numChannels = device->spec.channels; 294 format_pcm.samplesPerSec = device->spec.freq * 1000; // / kilo Hz to milli Hz 295 format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(device->spec.format); 296 format_pcm.containerSize = SDL_AUDIO_BITSIZE(device->spec.format); 297 format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 298 format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER; 299 300 audioSnk.pLocator = &loc_bufq; 301 audioSnk.pFormat = &format_pcm; 302 303 // create audio recorder 304 // (requires the RECORD_AUDIO permission) 305 result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc, &audioSnk, 1, ids, req); 306 if (SL_RESULT_SUCCESS != result) { 307 LOGE("CreateAudioRecorder failed: %d", result); 308 goto failed; 309 } 310 311 // realize the recorder 312 result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE); 313 if (SL_RESULT_SUCCESS != result) { 314 LOGE("RealizeAudioPlayer failed: %d", result); 315 goto failed; 316 } 317 318 // get the record interface 319 result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord); 320 if (SL_RESULT_SUCCESS != result) { 321 LOGE("SL_IID_RECORD interface get failed: %d", result); 322 goto failed; 323 } 324 325 // get the buffer queue interface 326 result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue); 327 if (SL_RESULT_SUCCESS != result) { 328 LOGE("SL_IID_BUFFERQUEUE interface get failed: %d", result); 329 goto failed; 330 } 331 332 // register callback on the buffer queue 333 // context is '(SDL_PrivateAudioData *)device->hidden' 334 result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, bqRecorderCallback, device->hidden); 335 if (SL_RESULT_SUCCESS != result) { 336 LOGE("RegisterCallback failed: %d", result); 337 goto failed; 338 } 339 340 // Create the audio buffer semaphore 341 audiodata->playsem = SDL_CreateSemaphore(0); 342 if (!audiodata->playsem) { 343 LOGE("cannot create Semaphore!"); 344 goto failed; 345 } 346 347 // Create the sound buffers 348 audiodata->mixbuff = (Uint8 *)SDL_malloc(NUM_BUFFERS * device->buffer_size); 349 if (!audiodata->mixbuff) { 350 LOGE("mixbuffer allocate - out of memory"); 351 goto failed; 352 } 353 354 for (i = 0; i < NUM_BUFFERS; i++) { 355 audiodata->pmixbuff[i] = audiodata->mixbuff + i * device->buffer_size; 356 } 357 358 // in case already recording, stop recording and clear buffer queue 359 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); 360 if (SL_RESULT_SUCCESS != result) { 361 LOGE("Record set state failed: %d", result); 362 goto failed; 363 } 364 365 // enqueue empty buffers to be filled by the recorder 366 for (i = 0; i < NUM_BUFFERS; i++) { 367 result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, audiodata->pmixbuff[i], device->buffer_size); 368 if (SL_RESULT_SUCCESS != result) { 369 LOGE("Record enqueue buffers failed: %d", result); 370 goto failed; 371 } 372 } 373 374 // start recording 375 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING); 376 if (SL_RESULT_SUCCESS != result) { 377 LOGE("Record set state failed: %d", result); 378 goto failed; 379 } 380 381 return true; 382 383failed: 384 return SDL_SetError("Open device failed!"); 385} 386 387// this callback handler is called every time a buffer finishes playing 388static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) 389{ 390 struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *)context; 391 392 LOGV("SLES: Playback Callback"); 393 SDL_SignalSemaphore(audiodata->playsem); 394} 395 396static void OPENSLES_DestroyPCMPlayer(SDL_AudioDevice *device) 397{ 398 struct SDL_PrivateAudioData *audiodata = device->hidden; 399 400 // set the player's state to 'stopped' 401 if (bqPlayerPlay != NULL) { 402 const SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); 403 if (SL_RESULT_SUCCESS != result) { 404 LOGE("SetPlayState stopped failed: %d", result); 405 } 406 } 407 408 // destroy buffer queue audio player object, and invalidate all associated interfaces 409 if (bqPlayerObject != NULL) { 410 (*bqPlayerObject)->Destroy(bqPlayerObject); 411 412 bqPlayerObject = NULL; 413 bqPlayerPlay = NULL; 414 bqPlayerBufferQueue = NULL; 415 } 416 417 if (audiodata->playsem) { 418 SDL_DestroySemaphore(audiodata->playsem); 419 audiodata->playsem = NULL; 420 } 421 422 if (audiodata->mixbuff) { 423 SDL_free(audiodata->mixbuff); 424 } 425} 426 427static bool OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) 428{ 429 /* If we want to add floating point audio support (requires API level 21) 430 it can be done as described here: 431 https://developer.android.com/ndk/guides/audio/opensl/android-extensions.html#floating-point 432 */ 433 if (SDL_GetAndroidSDKVersion() >= 21) { 434 const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format); 435 SDL_AudioFormat test_format; 436 while ((test_format = *(closefmts++)) != 0) { 437 if (SDL_AUDIO_ISSIGNED(test_format)) { 438 break; 439 } 440 } 441 442 if (!test_format) { 443 // Didn't find a compatible format : 444 LOGI("No compatible audio format, using signed 16-bit audio"); 445 test_format = SDL_AUDIO_S16; 446 } 447 device->spec.format = test_format; 448 } else { 449 // Just go with signed 16-bit audio as it's the most compatible 450 device->spec.format = SDL_AUDIO_S16; 451 } 452 453 // Update the fragment size as size in bytes 454 SDL_UpdatedAudioDeviceFormat(device); 455 456 LOGI("Try to open %u hz %s %u bit %u channels %s samples %u", 457 device->spec.freq, SDL_AUDIO_ISFLOAT(device->spec.format) ? "float" : "pcm", SDL_AUDIO_BITSIZE(device->spec.format), 458 device->spec.channels, (device->spec.format & 0x1000) ? "BE" : "LE", device->sample_frames); 459 460 // configure audio source 461 SLDataLocator_AndroidSimpleBufferQueue loc_bufq; 462 loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 463 loc_bufq.numBuffers = NUM_BUFFERS; 464 465 SLDataFormat_PCM format_pcm; 466 format_pcm.formatType = SL_DATAFORMAT_PCM; 467 format_pcm.numChannels = device->spec.channels; 468 format_pcm.samplesPerSec = device->spec.freq * 1000; // / kilo Hz to milli Hz 469 format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(device->spec.format); 470 format_pcm.containerSize = SDL_AUDIO_BITSIZE(device->spec.format); 471 472 if (SDL_AUDIO_ISBIGENDIAN(device->spec.format)) { 473 format_pcm.endianness = SL_BYTEORDER_BIGENDIAN; 474 } else { 475 format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 476 } 477 478 switch (device->spec.channels) { 479 case 1: 480 format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT; 481 break; 482 case 2: 483 format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO; 484 break; 485 case 3: 486 format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_FRONT_CENTER; 487 break; 488 case 4: 489 format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD; 490 break; 491 case 5: 492 format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER; 493 break; 494 case 6: 495 format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1; 496 break; 497 case 7: 498 format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER; 499 break; 500 case 8: 501 format_pcm.channelMask = SL_ANDROID_SPEAKER_7DOT1; 502 break; 503 default: 504 // Unknown number of channels, fall back to stereo 505 device->spec.channels = 2; 506 format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 507 break; 508 } 509 510 SLDataSink audioSnk; 511 SLDataSource audioSrc; 512 audioSrc.pFormat = (void *)&format_pcm; 513 514 SLAndroidDataFormat_PCM_EX format_pcm_ex; 515 if (SDL_AUDIO_ISFLOAT(device->spec.format)) { 516 // Copy all setup into PCM EX structure 517 format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; 518 format_pcm_ex.endianness = format_pcm.endianness; 519 format_pcm_ex.channelMask = format_pcm.channelMask; 520 format_pcm_ex.numChannels = format_pcm.numChannels; 521 format_pcm_ex.sampleRate = format_pcm.samplesPerSec; 522 format_pcm_ex.bitsPerSample = format_pcm.bitsPerSample; 523 format_pcm_ex.containerSize = format_pcm.containerSize; 524 format_pcm_ex.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT; 525 audioSrc.pFormat = (void *)&format_pcm_ex; 526 } 527 528 audioSrc.pLocator = &loc_bufq; 529 530 // configure audio sink 531 SLDataLocator_OutputMix loc_outmix; 532 loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 533 loc_outmix.outputMix = outputMixObject; 534 audioSnk.pLocator = &loc_outmix; 535 audioSnk.pFormat = NULL; 536 537 // create audio player 538 const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME }; 539 const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE }; 540 SLresult result; 541 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); 542 if (SL_RESULT_SUCCESS != result) { 543 LOGE("CreateAudioPlayer failed: %d", result); 544 goto failed; 545 } 546 547 // realize the player 548 result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); 549 if (SL_RESULT_SUCCESS != result) { 550 LOGE("RealizeAudioPlayer failed: %d", result); 551 goto failed; 552 } 553 554 // get the play interface 555 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); 556 if (SL_RESULT_SUCCESS != result) { 557 LOGE("SL_IID_PLAY interface get failed: %d", result); 558 goto failed; 559 } 560 561 // get the buffer queue interface 562 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue); 563 if (SL_RESULT_SUCCESS != result) { 564 LOGE("SL_IID_BUFFERQUEUE interface get failed: %d", result); 565 goto failed; 566 } 567 568 // register callback on the buffer queue 569 // context is '(SDL_PrivateAudioData *)device->hidden' 570 result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, device->hidden); 571 if (SL_RESULT_SUCCESS != result) { 572 LOGE("RegisterCallback failed: %d", result); 573 goto failed; 574 } 575 576#if 0 577 // get the volume interface 578 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); 579 if (SL_RESULT_SUCCESS != result) { 580 LOGE("SL_IID_VOLUME interface get failed: %d", result); 581 // goto failed; 582 } 583#endif 584 585 struct SDL_PrivateAudioData *audiodata = device->hidden; 586 587 // Create the audio buffer semaphore 588 audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1); 589 if (!audiodata->playsem) { 590 LOGE("cannot create Semaphore!"); 591 goto failed; 592 } 593 594 // Create the sound buffers 595 audiodata->mixbuff = (Uint8 *)SDL_malloc(NUM_BUFFERS * device->buffer_size); 596 if (!audiodata->mixbuff) { 597 LOGE("mixbuffer allocate - out of memory"); 598 goto failed; 599 } 600 601 for (int i = 0; i < NUM_BUFFERS; i++) { 602 audiodata->pmixbuff[i] = audiodata->mixbuff + i * device->buffer_size; 603 } 604 605 // set the player's state to playing 606 result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); 607 if (SL_RESULT_SUCCESS != result) { 608 LOGE("Play set state failed: %d", result); 609 goto failed; 610 } 611 612 return true; 613 614failed: 615 return false; 616} 617 618static bool OPENSLES_OpenDevice(SDL_AudioDevice *device) 619{ 620 device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); 621 if (!device->hidden) { 622 return false; 623 } 624 625 if (device->recording) { 626 LOGI("OPENSLES_OpenDevice() for recording"); 627 return OPENSLES_CreatePCMRecorder(device); 628 } else { 629 bool ret; 630 LOGI("OPENSLES_OpenDevice() for playback"); 631 ret = OPENSLES_CreatePCMPlayer(device); 632 if (!ret) { 633 // Another attempt to open the device with a lower frequency 634 if (device->spec.freq > 48000) { 635 OPENSLES_DestroyPCMPlayer(device); 636 device->spec.freq = 48000; 637 ret = OPENSLES_CreatePCMPlayer(device); 638 } 639 } 640 641 if (!ret) { 642 return SDL_SetError("Open device failed!"); 643 } 644 } 645 646 return true; 647} 648 649static bool OPENSLES_WaitDevice(SDL_AudioDevice *device) 650{ 651 struct SDL_PrivateAudioData *audiodata = device->hidden; 652 653 LOGV("OPENSLES_WaitDevice()"); 654 655 while (!SDL_GetAtomicInt(&device->shutdown)) { 656 // this semaphore won't fire when the app is in the background (OPENSLES_PauseDevices was called). 657 if (SDL_WaitSemaphoreTimeout(audiodata->playsem, 100)) { 658 return true; // semaphore was signaled, let's go! 659 } 660 // Still waiting on the semaphore (or the system), check other things then wait again. 661 } 662 return true; 663} 664 665static bool OPENSLES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) 666{ 667 struct SDL_PrivateAudioData *audiodata = device->hidden; 668 669 LOGV("======OPENSLES_PlayDevice()======"); 670 671 // Queue it up 672 const SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer, buflen); 673 674 audiodata->next_buffer++; 675 if (audiodata->next_buffer >= NUM_BUFFERS) { 676 audiodata->next_buffer = 0; 677 } 678 679 // If Enqueue fails, callback won't be called. 680 // Post the semaphore, not to run out of buffer 681 if (SL_RESULT_SUCCESS != result) { 682 SDL_SignalSemaphore(audiodata->playsem); 683 } 684 685 return true; 686} 687 688/// n playn sem 689// getbuf 0 - 1 690// fill buff 0 - 1 691// play 0 - 0 1 692// wait 1 0 0 693// getbuf 1 0 0 694// fill buff 1 0 0 695// play 0 0 0 696// wait 697// 698// okay.. 699 700static Uint8 *OPENSLES_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize) 701{ 702 struct SDL_PrivateAudioData *audiodata = device->hidden; 703 704 LOGV("OPENSLES_GetDeviceBuf()"); 705 return audiodata->pmixbuff[audiodata->next_buffer]; 706} 707 708static int OPENSLES_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) 709{ 710 struct SDL_PrivateAudioData *audiodata = device->hidden; 711 712 // Copy it to the output buffer 713 SDL_assert(buflen == device->buffer_size); 714 SDL_memcpy(buffer, audiodata->pmixbuff[audiodata->next_buffer], device->buffer_size); 715 716 // Re-enqueue the buffer 717 const SLresult result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], device->buffer_size); 718 if (SL_RESULT_SUCCESS != result) { 719 LOGE("Record enqueue buffers failed: %d", result); 720 return -1; 721 } 722 723 audiodata->next_buffer++; 724 if (audiodata->next_buffer >= NUM_BUFFERS) { 725 audiodata->next_buffer = 0; 726 } 727 728 return device->buffer_size; 729} 730 731static void OPENSLES_CloseDevice(SDL_AudioDevice *device) 732{ 733 // struct SDL_PrivateAudioData *audiodata = device->hidden; 734 if (device->hidden) { 735 if (device->recording) { 736 LOGI("OPENSLES_CloseDevice() for recording"); 737 OPENSLES_DestroyPCMRecorder(device); 738 } else { 739 LOGI("OPENSLES_CloseDevice() for playing"); 740 OPENSLES_DestroyPCMPlayer(device); 741 } 742 743 SDL_free(device->hidden); 744 device->hidden = NULL; 745 } 746} 747 748static bool OPENSLES_Init(SDL_AudioDriverImpl *impl) 749{ 750 LOGI("OPENSLES_Init() called"); 751 752 if (!OPENSLES_CreateEngine()) { 753 return false; 754 } 755 756 LOGI("OPENSLES_Init() - set pointers"); 757 758 // Set the function pointers 759 // impl->DetectDevices = OPENSLES_DetectDevices; 760 impl->ThreadInit = Android_AudioThreadInit; 761 impl->OpenDevice = OPENSLES_OpenDevice; 762 impl->WaitDevice = OPENSLES_WaitDevice; 763 impl->PlayDevice = OPENSLES_PlayDevice; 764 impl->GetDeviceBuf = OPENSLES_GetDeviceBuf; 765 impl->WaitRecordingDevice = OPENSLES_WaitDevice; 766 impl->RecordDevice = OPENSLES_RecordDevice; 767 impl->CloseDevice = OPENSLES_CloseDevice; 768 impl->Deinitialize = OPENSLES_DestroyEngine; 769 770 // and the capabilities 771 impl->HasRecordingSupport = true; 772 impl->OnlyHasDefaultPlaybackDevice = true; 773 impl->OnlyHasDefaultRecordingDevice = true; 774 775 LOGI("OPENSLES_Init() - success"); 776 777 // this audio target is available. 778 return true; 779} 780 781AudioBootStrap OPENSLES_bootstrap = { 782 "openslES", "OpenSL ES audio driver", OPENSLES_Init, false 783}; 784 785void OPENSLES_ResumeDevices(void) 786{ 787 if (bqPlayerPlay != NULL) { 788 // set the player's state to 'playing' 789 SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); 790 if (SL_RESULT_SUCCESS != result) { 791 LOGE("OPENSLES_ResumeDevices failed: %d", result); 792 } 793 } 794} 795 796void OPENSLES_PauseDevices(void) 797{ 798 if (bqPlayerPlay != NULL) { 799 // set the player's state to 'paused' 800 SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED); 801 if (SL_RESULT_SUCCESS != result) { 802 LOGE("OPENSLES_PauseDevices failed: %d", result); 803 } 804 } 805} 806 807#endif // SDL_AUDIO_DRIVER_OPENSLES