Atlas - SDL_openslES.c
Home / ext / SDL / src / audio / openslES Lines: 1 | Size: 27373 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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 SDL_free(audiodata->mixbuff); 227} 228 229// !!! FIXME: make this non-blocking! 230static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, bool granted) 231{ 232 SDL_SetAtomicInt((SDL_AtomicInt *) userdata, granted ? 1 : -1); 233} 234 235static bool OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) 236{ 237 struct SDL_PrivateAudioData *audiodata = device->hidden; 238 SLDataFormat_PCM format_pcm; 239 SLDataLocator_AndroidSimpleBufferQueue loc_bufq; 240 SLDataSink audioSnk; 241 SLDataLocator_IODevice loc_dev; 242 SLDataSource audioSrc; 243 const SLInterfaceID ids[1] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE }; 244 const SLboolean req[1] = { SL_BOOLEAN_TRUE }; 245 SLresult result; 246 int i; 247 248 // !!! FIXME: make this non-blocking! 249 { 250 SDL_AtomicInt permission_response; 251 SDL_SetAtomicInt(&permission_response, 0); 252 if (!SDL_RequestAndroidPermission("android.permission.RECORD_AUDIO", RequestAndroidPermissionBlockingCallback, &permission_response)) { 253 return false; 254 } 255 256 while (SDL_GetAtomicInt(&permission_response) == 0) { 257 SDL_Delay(10); 258 } 259 260 if (SDL_GetAtomicInt(&permission_response) < 0) { 261 LOGE("This app doesn't have RECORD_AUDIO permission"); 262 return SDL_SetError("This app doesn't have RECORD_AUDIO permission"); 263 } 264 } 265 266 // Just go with signed 16-bit audio as it's the most compatible 267 device->spec.format = SDL_AUDIO_S16; 268 device->spec.channels = 1; 269 //device->spec.freq = SL_SAMPLINGRATE_16 / 1000;*/ 270 271 // Update the fragment size as size in bytes 272 SDL_UpdatedAudioDeviceFormat(device); 273 274 LOGI("Try to open %u hz %u bit %u channels %s samples %u", 275 device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format), 276 device->spec.channels, (device->spec.format & 0x1000) ? "BE" : "LE", device->sample_frames); 277 278 // configure audio source 279 loc_dev.locatorType = SL_DATALOCATOR_IODEVICE; 280 loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT; 281 loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; 282 loc_dev.device = NULL; 283 audioSrc.pLocator = &loc_dev; 284 audioSrc.pFormat = NULL; 285 286 // configure audio sink 287 loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 288 loc_bufq.numBuffers = NUM_BUFFERS; 289 290 format_pcm.formatType = SL_DATAFORMAT_PCM; 291 format_pcm.numChannels = device->spec.channels; 292 format_pcm.samplesPerSec = device->spec.freq * 1000; // / kilo Hz to milli Hz 293 format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(device->spec.format); 294 format_pcm.containerSize = SDL_AUDIO_BITSIZE(device->spec.format); 295 format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 296 format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER; 297 298 audioSnk.pLocator = &loc_bufq; 299 audioSnk.pFormat = &format_pcm; 300 301 // create audio recorder 302 // (requires the RECORD_AUDIO permission) 303 result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc, &audioSnk, 1, ids, req); 304 if (SL_RESULT_SUCCESS != result) { 305 LOGE("CreateAudioRecorder failed: %d", result); 306 goto failed; 307 } 308 309 // realize the recorder 310 result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE); 311 if (SL_RESULT_SUCCESS != result) { 312 LOGE("RealizeAudioPlayer failed: %d", result); 313 goto failed; 314 } 315 316 // get the record interface 317 result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord); 318 if (SL_RESULT_SUCCESS != result) { 319 LOGE("SL_IID_RECORD interface get failed: %d", result); 320 goto failed; 321 } 322 323 // get the buffer queue interface 324 result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue); 325 if (SL_RESULT_SUCCESS != result) { 326 LOGE("SL_IID_BUFFERQUEUE interface get failed: %d", result); 327 goto failed; 328 } 329 330 // register callback on the buffer queue 331 // context is '(SDL_PrivateAudioData *)device->hidden' 332 result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, bqRecorderCallback, device->hidden); 333 if (SL_RESULT_SUCCESS != result) { 334 LOGE("RegisterCallback failed: %d", result); 335 goto failed; 336 } 337 338 // Create the audio buffer semaphore 339 audiodata->playsem = SDL_CreateSemaphore(0); 340 if (!audiodata->playsem) { 341 LOGE("cannot create Semaphore!"); 342 goto failed; 343 } 344 345 // Create the sound buffers 346 audiodata->mixbuff = (Uint8 *)SDL_malloc(NUM_BUFFERS * device->buffer_size); 347 if (!audiodata->mixbuff) { 348 LOGE("mixbuffer allocate - out of memory"); 349 goto failed; 350 } 351 352 for (i = 0; i < NUM_BUFFERS; i++) { 353 audiodata->pmixbuff[i] = audiodata->mixbuff + i * device->buffer_size; 354 } 355 356 // in case already recording, stop recording and clear buffer queue 357 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED); 358 if (SL_RESULT_SUCCESS != result) { 359 LOGE("Record set state failed: %d", result); 360 goto failed; 361 } 362 363 // enqueue empty buffers to be filled by the recorder 364 for (i = 0; i < NUM_BUFFERS; i++) { 365 result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, audiodata->pmixbuff[i], device->buffer_size); 366 if (SL_RESULT_SUCCESS != result) { 367 LOGE("Record enqueue buffers failed: %d", result); 368 goto failed; 369 } 370 } 371 372 // start recording 373 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING); 374 if (SL_RESULT_SUCCESS != result) { 375 LOGE("Record set state failed: %d", result); 376 goto failed; 377 } 378 379 return true; 380 381failed: 382 return SDL_SetError("Open device failed!"); 383} 384 385// this callback handler is called every time a buffer finishes playing 386static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) 387{ 388 struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *)context; 389 390 LOGV("SLES: Playback Callback"); 391 SDL_SignalSemaphore(audiodata->playsem); 392} 393 394static void OPENSLES_DestroyPCMPlayer(SDL_AudioDevice *device) 395{ 396 struct SDL_PrivateAudioData *audiodata = device->hidden; 397 398 // set the player's state to 'stopped' 399 if (bqPlayerPlay != NULL) { 400 const SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED); 401 if (SL_RESULT_SUCCESS != result) { 402 LOGE("SetPlayState stopped failed: %d", result); 403 } 404 } 405 406 // destroy buffer queue audio player object, and invalidate all associated interfaces 407 if (bqPlayerObject != NULL) { 408 (*bqPlayerObject)->Destroy(bqPlayerObject); 409 410 bqPlayerObject = NULL; 411 bqPlayerPlay = NULL; 412 bqPlayerBufferQueue = NULL; 413 } 414 415 if (audiodata->playsem) { 416 SDL_DestroySemaphore(audiodata->playsem); 417 audiodata->playsem = NULL; 418 } 419 420 SDL_free(audiodata->mixbuff); 421} 422 423static bool OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) 424{ 425 /* according to https://developer.android.com/ndk/guides/audio/opensl/opensl-for-android, 426 Android's OpenSL ES only supports Uint8 and _littleendian_ Sint16. 427 (and float32, with an extension we use, below.) */ 428 if (SDL_GetAndroidSDKVersion() >= 21) { 429 const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format); 430 SDL_AudioFormat test_format; 431 while ((test_format = *(closefmts++)) != 0) { 432 switch (test_format) { 433 case SDL_AUDIO_U8: 434 case SDL_AUDIO_S16LE: 435 case SDL_AUDIO_F32: 436 break; 437 default: 438 continue; 439 } 440 break; 441 } 442 443 if (!test_format) { 444 // Didn't find a compatible format : 445 LOGI("No compatible audio format, using signed 16-bit LE audio"); 446 test_format = SDL_AUDIO_S16LE; 447 } 448 device->spec.format = test_format; 449 } else { 450 // Just go with signed 16-bit audio as it's the most compatible 451 device->spec.format = SDL_AUDIO_S16LE; 452 } 453 454 // Update the fragment size as size in bytes 455 SDL_UpdatedAudioDeviceFormat(device); 456 457 LOGI("Try to open %u hz %s %u bit %u channels %s samples %u", 458 device->spec.freq, SDL_AUDIO_ISFLOAT(device->spec.format) ? "float" : "pcm", SDL_AUDIO_BITSIZE(device->spec.format), 459 device->spec.channels, (device->spec.format & 0x1000) ? "BE" : "LE", device->sample_frames); 460 461 // configure audio source 462 SLDataLocator_AndroidSimpleBufferQueue loc_bufq; 463 loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 464 loc_bufq.numBuffers = NUM_BUFFERS; 465 466 SLDataFormat_PCM format_pcm; 467 format_pcm.formatType = SL_DATAFORMAT_PCM; 468 format_pcm.numChannels = device->spec.channels; 469 format_pcm.samplesPerSec = device->spec.freq * 1000; // / kilo Hz to milli Hz 470 format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(device->spec.format); 471 format_pcm.containerSize = SDL_AUDIO_BITSIZE(device->spec.format); 472 473 if (SDL_AUDIO_ISBIGENDIAN(device->spec.format)) { 474 format_pcm.endianness = SL_BYTEORDER_BIGENDIAN; 475 } else { 476 format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN; 477 } 478 479 switch (device->spec.channels) { 480 case 1: 481 format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT; 482 break; 483 case 2: 484 format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO; 485 break; 486 case 3: 487 format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_FRONT_CENTER; 488 break; 489 case 4: 490 format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD; 491 break; 492 case 5: 493 format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER; 494 break; 495 case 6: 496 format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1; 497 break; 498 case 7: 499 format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER; 500 break; 501 case 8: 502 format_pcm.channelMask = SL_ANDROID_SPEAKER_7DOT1; 503 break; 504 default: 505 // Unknown number of channels, fall back to stereo 506 device->spec.channels = 2; 507 format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 508 break; 509 } 510 511 SLDataSink audioSnk; 512 SLDataSource audioSrc; 513 audioSrc.pFormat = (void *)&format_pcm; 514 515 SLAndroidDataFormat_PCM_EX format_pcm_ex; 516 if (SDL_AUDIO_ISFLOAT(device->spec.format)) { 517 // Copy all setup into PCM EX structure 518 format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; 519 format_pcm_ex.endianness = format_pcm.endianness; 520 format_pcm_ex.channelMask = format_pcm.channelMask; 521 format_pcm_ex.numChannels = format_pcm.numChannels; 522 format_pcm_ex.sampleRate = format_pcm.samplesPerSec; 523 format_pcm_ex.bitsPerSample = format_pcm.bitsPerSample; 524 format_pcm_ex.containerSize = format_pcm.containerSize; 525 format_pcm_ex.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT; 526 audioSrc.pFormat = (void *)&format_pcm_ex; 527 } 528 529 audioSrc.pLocator = &loc_bufq; 530 531 // configure audio sink 532 SLDataLocator_OutputMix loc_outmix; 533 loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 534 loc_outmix.outputMix = outputMixObject; 535 audioSnk.pLocator = &loc_outmix; 536 audioSnk.pFormat = NULL; 537 538 // create audio player 539 const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME }; 540 const SLboolean req[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE }; 541 SLresult result; 542 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req); 543 if (SL_RESULT_SUCCESS != result) { 544 LOGE("CreateAudioPlayer failed: %d", result); 545 goto failed; 546 } 547 548 // realize the player 549 result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE); 550 if (SL_RESULT_SUCCESS != result) { 551 LOGE("RealizeAudioPlayer failed: %d", result); 552 goto failed; 553 } 554 555 // get the play interface 556 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay); 557 if (SL_RESULT_SUCCESS != result) { 558 LOGE("SL_IID_PLAY interface get failed: %d", result); 559 goto failed; 560 } 561 562 // get the buffer queue interface 563 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue); 564 if (SL_RESULT_SUCCESS != result) { 565 LOGE("SL_IID_BUFFERQUEUE interface get failed: %d", result); 566 goto failed; 567 } 568 569 // register callback on the buffer queue 570 // context is '(SDL_PrivateAudioData *)device->hidden' 571 result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, device->hidden); 572 if (SL_RESULT_SUCCESS != result) { 573 LOGE("RegisterCallback failed: %d", result); 574 goto failed; 575 } 576 577#if 0 578 // get the volume interface 579 result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume); 580 if (SL_RESULT_SUCCESS != result) { 581 LOGE("SL_IID_VOLUME interface get failed: %d", result); 582 // goto failed; 583 } 584#endif 585 586 struct SDL_PrivateAudioData *audiodata = device->hidden; 587 588 // Create the audio buffer semaphore 589 audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1); 590 if (!audiodata->playsem) { 591 LOGE("cannot create Semaphore!"); 592 goto failed; 593 } 594 595 // Create the sound buffers 596 audiodata->mixbuff = (Uint8 *)SDL_malloc(NUM_BUFFERS * device->buffer_size); 597 if (!audiodata->mixbuff) { 598 LOGE("mixbuffer allocate - out of memory"); 599 goto failed; 600 } 601 602 for (int i = 0; i < NUM_BUFFERS; i++) { 603 audiodata->pmixbuff[i] = audiodata->mixbuff + i * device->buffer_size; 604 } 605 606 // set the player's state to playing 607 result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); 608 if (SL_RESULT_SUCCESS != result) { 609 LOGE("Play set state failed: %d", result); 610 goto failed; 611 } 612 613 return true; 614 615failed: 616 return false; 617} 618 619static bool OPENSLES_OpenDevice(SDL_AudioDevice *device) 620{ 621 device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); 622 if (!device->hidden) { 623 return false; 624 } 625 626 if (device->recording) { 627 LOGI("OPENSLES_OpenDevice() for recording"); 628 return OPENSLES_CreatePCMRecorder(device); 629 } else { 630 bool ret; 631 LOGI("OPENSLES_OpenDevice() for playback"); 632 ret = OPENSLES_CreatePCMPlayer(device); 633 if (!ret) { 634 // Another attempt to open the device with a lower frequency 635 if (device->spec.freq > 48000) { 636 OPENSLES_DestroyPCMPlayer(device); 637 device->spec.freq = 48000; 638 ret = OPENSLES_CreatePCMPlayer(device); 639 } 640 } 641 642 if (!ret) { 643 return SDL_SetError("Open device failed!"); 644 } 645 } 646 647 return true; 648} 649 650static bool OPENSLES_WaitDevice(SDL_AudioDevice *device) 651{ 652 struct SDL_PrivateAudioData *audiodata = device->hidden; 653 654 LOGV("OPENSLES_WaitDevice()"); 655 656 while (!SDL_GetAtomicInt(&device->shutdown)) { 657 // this semaphore won't fire when the app is in the background (OPENSLES_PauseDevices was called). 658 if (SDL_WaitSemaphoreTimeout(audiodata->playsem, 100)) { 659 return true; // semaphore was signaled, let's go! 660 } 661 // Still waiting on the semaphore (or the system), check other things then wait again. 662 } 663 return true; 664} 665 666static bool OPENSLES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) 667{ 668 struct SDL_PrivateAudioData *audiodata = device->hidden; 669 670 LOGV("======OPENSLES_PlayDevice()======"); 671 672 // Queue it up 673 const SLresult result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer, buflen); 674 675 audiodata->next_buffer++; 676 if (audiodata->next_buffer >= NUM_BUFFERS) { 677 audiodata->next_buffer = 0; 678 } 679 680 // If Enqueue fails, callback won't be called. 681 // Post the semaphore, not to run out of buffer 682 if (SL_RESULT_SUCCESS != result) { 683 SDL_SignalSemaphore(audiodata->playsem); 684 } 685 686 return true; 687} 688 689/// n playn sem 690// getbuf 0 - 1 691// fill buff 0 - 1 692// play 0 - 0 1 693// wait 1 0 0 694// getbuf 1 0 0 695// fill buff 1 0 0 696// play 0 0 0 697// wait 698// 699// okay.. 700 701static Uint8 *OPENSLES_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize) 702{ 703 struct SDL_PrivateAudioData *audiodata = device->hidden; 704 705 LOGV("OPENSLES_GetDeviceBuf()"); 706 return audiodata->pmixbuff[audiodata->next_buffer]; 707} 708 709static int OPENSLES_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) 710{ 711 struct SDL_PrivateAudioData *audiodata = device->hidden; 712 713 // Copy it to the output buffer 714 SDL_assert(buflen == device->buffer_size); 715 SDL_memcpy(buffer, audiodata->pmixbuff[audiodata->next_buffer], device->buffer_size); 716 717 // Re-enqueue the buffer 718 const SLresult result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], device->buffer_size); 719 if (SL_RESULT_SUCCESS != result) { 720 LOGE("Record enqueue buffers failed: %d", result); 721 return -1; 722 } 723 724 audiodata->next_buffer++; 725 if (audiodata->next_buffer >= NUM_BUFFERS) { 726 audiodata->next_buffer = 0; 727 } 728 729 return device->buffer_size; 730} 731 732static void OPENSLES_CloseDevice(SDL_AudioDevice *device) 733{ 734 // struct SDL_PrivateAudioData *audiodata = device->hidden; 735 if (device->hidden) { 736 if (device->recording) { 737 LOGI("OPENSLES_CloseDevice() for recording"); 738 OPENSLES_DestroyPCMRecorder(device); 739 } else { 740 LOGI("OPENSLES_CloseDevice() for playing"); 741 OPENSLES_DestroyPCMPlayer(device); 742 } 743 744 SDL_free(device->hidden); 745 device->hidden = NULL; 746 } 747} 748 749static bool OPENSLES_Init(SDL_AudioDriverImpl *impl) 750{ 751 LOGI("OPENSLES_Init() called"); 752 753 if (!OPENSLES_CreateEngine()) { 754 return false; 755 } 756 757 LOGI("OPENSLES_Init() - set pointers"); 758 759 // Set the function pointers 760 // impl->DetectDevices = OPENSLES_DetectDevices; 761 impl->ThreadInit = Android_AudioThreadInit; 762 impl->OpenDevice = OPENSLES_OpenDevice; 763 impl->WaitDevice = OPENSLES_WaitDevice; 764 impl->PlayDevice = OPENSLES_PlayDevice; 765 impl->GetDeviceBuf = OPENSLES_GetDeviceBuf; 766 impl->WaitRecordingDevice = OPENSLES_WaitDevice; 767 impl->RecordDevice = OPENSLES_RecordDevice; 768 impl->CloseDevice = OPENSLES_CloseDevice; 769 impl->Deinitialize = OPENSLES_DestroyEngine; 770 771 // and the capabilities 772 impl->HasRecordingSupport = true; 773 impl->OnlyHasDefaultPlaybackDevice = true; 774 impl->OnlyHasDefaultRecordingDevice = true; 775 776 LOGI("OPENSLES_Init() - success"); 777 778 // this audio target is available. 779 return true; 780} 781 782AudioBootStrap OPENSLES_bootstrap = { 783 "openslES", "OpenSL ES audio driver", OPENSLES_Init, false, false 784}; 785 786void OPENSLES_ResumeDevices(void) 787{ 788 if (bqPlayerPlay != NULL) { 789 // set the player's state to 'playing' 790 SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING); 791 if (SL_RESULT_SUCCESS != result) { 792 LOGE("OPENSLES_ResumeDevices failed: %d", result); 793 } 794 } 795} 796 797void OPENSLES_PauseDevices(void) 798{ 799 if (bqPlayerPlay != NULL) { 800 // set the player's state to 'paused' 801 SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED); 802 if (SL_RESULT_SUCCESS != result) { 803 LOGE("OPENSLES_PauseDevices failed: %d", result); 804 } 805 } 806} 807 808#endif // SDL_AUDIO_DRIVER_OPENSLES 809[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.