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