2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../../SDL_internal.h"
23 #if SDL_AUDIO_DRIVER_OPENSLES
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
29 #include "SDL_audio.h"
30 #include "../SDL_audio_c.h"
31 #include "../../core/android/SDL_android.h"
32 #include "SDL_openslES.h"
34 /* for native audio */
35 #include <SLES/OpenSLES.h>
36 #include <SLES/OpenSLES_Android.h>
38 #include <android/log.h>
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__)
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)
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)
77 /* engine interfaces */
78 static SLObjectItf engineObject;
79 static SLEngineItf engineEngine;
81 /* output mix interfaces */
82 static SLObjectItf outputMixObject;
84 /* buffer queue player interfaces */
85 static SLObjectItf bqPlayerObject;
86 static SLPlayItf bqPlayerPlay;
87 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
89 static SLVolumeItf bqPlayerVolume;
92 /* recorder interfaces */
93 static SLObjectItf recorderObject;
94 static SLRecordItf recorderRecord;
95 static SLAndroidSimpleBufferQueueItf recorderBufferQueue;
98 static const char *sldevaudiorecorderstr = "SLES Audio Recorder";
99 static const char *sldevaudioplayerstr = "SLES Audio Player";
101 #define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr
102 #define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr
103 static void openslES_DetectDevices( int iscapture )
105 LOGI( "openSLES_DetectDevices()" );
107 addfn( SLES_DEV_AUDIO_RECORDER );
109 addfn( SLES_DEV_AUDIO_PLAYER );
113 static void openslES_DestroyEngine(void)
115 LOGI("openslES_DestroyEngine()");
117 /* destroy output mix object, and invalidate all associated interfaces */
118 if (outputMixObject != NULL) {
119 (*outputMixObject)->Destroy(outputMixObject);
120 outputMixObject = NULL;
123 /* destroy engine object, and invalidate all associated interfaces */
124 if (engineObject != NULL) {
125 (*engineObject)->Destroy(engineObject);
132 openslES_CreateEngine(void)
136 LOGI("openSLES_CreateEngine()");
139 result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
140 if (SL_RESULT_SUCCESS != result) {
141 LOGE("slCreateEngine failed: %d", result);
144 LOGI("slCreateEngine OK");
146 /* realize the engine */
147 result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
148 if (SL_RESULT_SUCCESS != result) {
149 LOGE("RealizeEngine failed: %d", result);
152 LOGI("RealizeEngine OK");
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);
160 LOGI("EngineGetInterface OK");
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);
170 LOGI("CreateOutputMix OK");
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);
181 openslES_DestroyEngine();
185 /* this callback handler is called every time a buffer finishes recording */
187 bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
189 struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context;
191 LOGV("SLES: Recording Callback");
192 SDL_SemPost(audiodata->playsem);
196 openslES_DestroyPCMRecorder(_THIS)
198 struct SDL_PrivateAudioData *audiodata = this->hidden;
202 if (recorderRecord != NULL) {
203 result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
204 if (SL_RESULT_SUCCESS != result) {
205 LOGE("SetRecordState stopped: %d", result);
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;
217 if (audiodata->playsem) {
218 SDL_DestroySemaphore(audiodata->playsem);
219 audiodata->playsem = NULL;
222 if (audiodata->mixbuff) {
223 SDL_free(audiodata->mixbuff);
228 openslES_CreatePCMRecorder(_THIS)
230 struct SDL_PrivateAudioData *audiodata = this->hidden;
231 SLDataFormat_PCM format_pcm;
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");
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;*/
245 /* Update the fragment size as size in bytes */
246 SDL_CalculateAudioSpec(&this->spec);
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);
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};
256 /* configure audio sink */
257 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
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;
267 SLDataSink audioSnk = { &loc_bufq, &format_pcm };
269 /* create audio recorder */
270 /* (requires the RECORD_AUDIO permission) */
271 const SLInterfaceID ids[1] = {
272 SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
274 const SLboolean req[1] = {
278 result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc, &audioSnk, 1, ids, req);
279 if (SL_RESULT_SUCCESS != result) {
280 LOGE("CreateAudioRecorder failed: %d", result);
284 /* realize the recorder */
285 result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
286 if (SL_RESULT_SUCCESS != result) {
287 LOGE("RealizeAudioPlayer failed: %d", result);
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);
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);
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);
313 /* Create the audio buffer semaphore */
314 audiodata->playsem = SDL_CreateSemaphore(0);
315 if (!audiodata->playsem) {
316 LOGE("cannot create Semaphore!");
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");
327 for (i = 0; i < NUM_BUFFERS; i++) {
328 audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
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);
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);
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);
358 openslES_DestroyPCMRecorder(this);
360 return SDL_SetError("Open device failed!");
363 /* this callback handler is called every time a buffer finishes playing */
365 bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
367 struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context;
369 LOGV("SLES: Playback Callback");
370 SDL_SemPost(audiodata->playsem);
374 openslES_DestroyPCMPlayer(_THIS)
376 struct SDL_PrivateAudioData *audiodata = this->hidden;
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);
387 /* destroy buffer queue audio player object, and invalidate all associated interfaces */
388 if (bqPlayerObject != NULL) {
390 (*bqPlayerObject)->Destroy(bqPlayerObject);
392 bqPlayerObject = NULL;
394 bqPlayerBufferQueue = NULL;
397 if (audiodata->playsem) {
398 SDL_DestroySemaphore(audiodata->playsem);
399 audiodata->playsem = NULL;
402 if (audiodata->mixbuff) {
403 SDL_free(audiodata->mixbuff);
408 openslES_CreatePCMPlayer(_THIS)
410 struct SDL_PrivateAudioData *audiodata = this->hidden;
411 SLDataFormat_PCM format_pcm;
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
420 /* Just go with signed 16-bit audio as it's the most compatible */
421 this->spec.format = AUDIO_S16SYS;
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)) {
428 test_format = SDL_NextAudioFormat();
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;
436 this->spec.format = test_format;
439 /* Update the fragment size as size in bytes */
440 SDL_CalculateAudioSpec(&this->spec);
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);
446 /* configure audio source */
447 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
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);
455 if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) {
456 format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
458 format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
461 switch (this->spec.channels)
464 format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT;
467 format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO;
470 format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_FRONT_CENTER;
473 format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD;
476 format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER;
479 format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1;
482 format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER;
485 format_pcm.channelMask = SL_ANDROID_SPEAKER_7DOT1;
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;
494 SLDataSource audioSrc = { &loc_bufq, &format_pcm };
496 /* configure audio sink */
497 SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
498 SLDataSink audioSnk = { &loc_outmix, NULL };
500 /* create audio player */
501 const SLInterfaceID ids[2] = {
502 SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
506 const SLboolean req[2] = {
511 result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
512 if (SL_RESULT_SUCCESS != result) {
513 LOGE("CreateAudioPlayer failed: %d", result);
517 /* realize the player */
518 result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
519 if (SL_RESULT_SUCCESS != result) {
520 LOGE("RealizeAudioPlayer failed: %d", result);
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);
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);
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);
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);
555 /* Create the audio buffer semaphore */
556 audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1);
557 if (!audiodata->playsem) {
558 LOGE("cannot create Semaphore!");
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");
569 for (i = 0; i < NUM_BUFFERS; i++) {
570 audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
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);
584 openslES_DestroyPCMPlayer(this);
586 return SDL_SetError("Open device failed!");
590 openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
592 this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
593 if (this->hidden == NULL) {
594 return SDL_OutOfMemory();
598 LOGI("openslES_OpenDevice() %s for capture", devname);
599 return openslES_CreatePCMRecorder(this);
601 LOGI("openslES_OpenDevice() %s for playing", devname);
602 return openslES_CreatePCMPlayer(this);
607 openslES_WaitDevice(_THIS)
609 struct SDL_PrivateAudioData *audiodata = this->hidden;
611 LOGV("openslES_WaitDevice()");
613 /* Wait for an audio chunk to finish */
614 SDL_SemWait(audiodata->playsem);
618 openslES_PlayDevice(_THIS)
620 struct SDL_PrivateAudioData *audiodata = this->hidden;
623 LOGV("======openslES_PlayDevice()======");
626 result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size);
628 audiodata->next_buffer++;
629 if (audiodata->next_buffer >= NUM_BUFFERS) {
630 audiodata->next_buffer = 0;
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);
642 /* fill buff 0 - 1 */
646 /* fill buff 1 0 0 */
653 openslES_GetDeviceBuf(_THIS)
655 struct SDL_PrivateAudioData *audiodata = this->hidden;
657 LOGV("openslES_GetDeviceBuf()");
658 return audiodata->pmixbuff[audiodata->next_buffer];
662 openslES_CaptureFromDevice(_THIS, void *buffer, int buflen)
664 struct SDL_PrivateAudioData *audiodata = this->hidden;
667 /* Wait for new recorded data */
668 SDL_SemWait(audiodata->playsem);
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);
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);
681 audiodata->next_buffer++;
682 if (audiodata->next_buffer >= NUM_BUFFERS) {
683 audiodata->next_buffer = 0;
686 return this->spec.size;
690 openslES_CloseDevice(_THIS)
692 /* struct SDL_PrivateAudioData *audiodata = this->hidden; */
694 if (this->iscapture) {
695 LOGI("openslES_CloseDevice() for capture");
696 openslES_DestroyPCMRecorder(this);
698 LOGI("openslES_CloseDevice() for playing");
699 openslES_DestroyPCMPlayer(this);
702 SDL_free(this->hidden);
706 openslES_Init(SDL_AudioDriverImpl * impl)
708 LOGI("openslES_Init() called");
710 if (!openslES_CreateEngine()) {
714 LOGI("openslES_Init() - set pointers");
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;
726 /* and the capabilities */
727 impl->HasCaptureSupport = 1;
728 impl->OnlyHasDefaultOutputDevice = 1;
729 impl->OnlyHasDefaultCaptureDevice = 1;
731 LOGI("openslES_Init() - success");
733 /* this audio target is available. */
737 AudioBootStrap openslES_bootstrap = {
738 "openslES", "opensl ES audio driver", openslES_Init, 0
741 void openslES_ResumeDevices(void)
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);
752 void openslES_PauseDevices(void)
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);
763 #endif /* SDL_AUDIO_DRIVER_OPENSLES */
765 /* vi: set ts=4 sw=4 expandtab: */