SDL  2.0
SDL_openslES.c
Go to the documentation of this file.
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 
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
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
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
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
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 */
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
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
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
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 */
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
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
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
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 *
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
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
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
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 
739  "openslES", "opensl ES audio driver", openslES_Init, 0
740 };
741 
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 
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: */
SDL_FirstAudioFormat
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1647
SDL_AudioSpec::channels
Uint8 channels
Definition: SDL_audio.h:182
SDL_AudioDriverImpl::HasCaptureSupport
int HasCaptureSupport
Definition: SDL_sysaudio.h:90
SDL_PrivateAudioData::mixbuff
Uint8 * mixbuff
Definition: SDL_openslES.h:35
SDL_CreateSemaphore
#define SDL_CreateSemaphore
Definition: SDL_dynapi_overrides.h:264
SDL_PrivateAudioData::playsem
SDL_sem * playsem
Definition: SDL_openslES.h:38
NULL
#define NULL
Definition: begin_code.h:167
handle
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
SDL_AUDIO_ISBIGENDIAN
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
SDL_AudioSpec::format
SDL_AudioFormat format
Definition: SDL_audio.h:181
SDL_AUDIO_ISSIGNED
#define SDL_AUDIO_ISSIGNED(x)
Definition: SDL_audio.h:78
SDL_AudioDriverImpl::OpenDevice
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
SDL_NextAudioFormat
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1659
SDL_PrivateAudioData::iscapture
SDL_bool iscapture
Definition: SDL_qsa_audio.h:37
SDL_AudioFormat
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
SDL_SemPost
#define SDL_SemPost
Definition: SDL_dynapi_overrides.h:269
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9435
AudioBootStrap
Definition: SDL_sysaudio.h:176
AUDIO_S16SYS
#define AUDIO_S16SYS
Definition: SDL_audio.h:128
SDL_PrivateAudioData
Definition: SDL_alsa_audio.h:33
SDL_AudioDriverImpl::WaitDevice
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
buffer
GLuint buffer
Definition: SDL_opengl_glext.h:536
context
static screen_context_t context
Definition: video.c:25
SDL_audio.h
SDL_AudioDriverImpl
Definition: SDL_sysaudio.h:65
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_AudioDriverImpl::OnlyHasDefaultOutputDevice
int OnlyHasDefaultOutputDevice
Definition: SDL_sysaudio.h:91
SDL_PrivateAudioData::pmixbuff
Uint8 * pmixbuff[NUM_BUFFERS]
Definition: SDL_openslES.h:37
SDL_assert.h
SDL_CalculateAudioSpec
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1686
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
SDL_AUDIO_BITSIZE
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
SDL_AudioDriverImpl::PlayDevice
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
SDL_AudioSpec::freq
int freq
Definition: SDL_audio.h:180
SDL_AudioDriverImpl::OnlyHasDefaultCaptureDevice
int OnlyHasDefaultCaptureDevice
Definition: SDL_sysaudio.h:92
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
spec
SDL_AudioSpec spec
Definition: loopwave.c:31
SDL_AudioDriverImpl::CaptureFromDevice
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:75
SDL_AUDIO_ISINT
#define SDL_AUDIO_ISINT(x)
Definition: SDL_audio.h:79
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
NUM_BUFFERS
#define NUM_BUFFERS
Definition: SDL_openslES.h:31
SDL_AudioSpec::size
Uint32 size
Definition: SDL_audio.h:186
SDL_SemWait
#define SDL_SemWait
Definition: SDL_dynapi_overrides.h:266
Android_JNI_RequestPermission
SDL_bool Android_JNI_RequestPermission(const char *permission)
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_AudioDriverImpl::GetDeviceBuf
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74
SDL_PrivateAudioData::next_buffer
int next_buffer
Definition: SDL_openslES.h:36
SDL_DestroySemaphore
#define SDL_DestroySemaphore
Definition: SDL_dynapi_overrides.h:265
openslES_ResumeDevices
void openslES_ResumeDevices(void)
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
openslES_bootstrap
AudioBootStrap openslES_bootstrap
SDL_AudioDriverImpl::CloseDevice
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
SDL_openslES.h
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
ids
GLuint * ids
Definition: SDL_opengl_glext.h:528
SDL_AudioDriverImpl::Deinitialize
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:82
openslES_PauseDevices
void openslES_PauseDevices(void)
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179