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_audio.h"
30 #include "../SDL_audio_c.h"
31 #include "../../core/android/SDL_android.h"
32 #include "SDL_openslES.h"
33 
34 /* for native audio */
35 #include <SLES/OpenSLES.h>
36 #include <SLES/OpenSLES_Android.h>
37 
38 #include <android/log.h>
39 
40 #if 0
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__)
45 #define LOGV(...)
46 #else
47 #define LOGE(...)
48 #define LOGI(...)
49 #define LOGV(...)
50 #endif
51 
52 /*
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)
71 */
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)
76 
77 /* engine interfaces */
78 static SLObjectItf engineObject;
79 static SLEngineItf engineEngine;
80 
81 /* output mix interfaces */
82 static SLObjectItf outputMixObject;
83 
84 /* buffer queue player interfaces */
85 static SLObjectItf bqPlayerObject;
86 static SLPlayItf bqPlayerPlay;
87 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
88 #if 0
89 static SLVolumeItf bqPlayerVolume;
90 #endif
91 
92 /* recorder interfaces */
93 static SLObjectItf recorderObject;
94 static SLRecordItf recorderRecord;
95 static SLAndroidSimpleBufferQueueItf recorderBufferQueue;
96 
97 #if 0
98 static const char *sldevaudiorecorderstr = "SLES Audio Recorder";
99 static const char *sldevaudioplayerstr = "SLES Audio Player";
100 
101 #define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr
102 #define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr
103 static void openslES_DetectDevices( int iscapture )
104 {
105  LOGI( "openSLES_DetectDevices()" );
106  if ( iscapture )
107  addfn( SLES_DEV_AUDIO_RECORDER );
108  else
109  addfn( SLES_DEV_AUDIO_PLAYER );
110 }
111 #endif
112 
113 static void openslES_DestroyEngine(void)
114 {
115  LOGI("openslES_DestroyEngine()");
116 
117  /* destroy output mix object, and invalidate all associated interfaces */
118  if (outputMixObject != NULL) {
119  (*outputMixObject)->Destroy(outputMixObject);
120  outputMixObject = NULL;
121  }
122 
123  /* destroy engine object, and invalidate all associated interfaces */
124  if (engineObject != NULL) {
125  (*engineObject)->Destroy(engineObject);
126  engineObject = NULL;
127  engineEngine = NULL;
128  }
129 }
130 
131 static int
132 openslES_CreateEngine(void)
133 {
134  SLresult result;
135 
136  LOGI("openSLES_CreateEngine()");
137 
138  /* create engine */
139  result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
140  if (SL_RESULT_SUCCESS != result) {
141  LOGE("slCreateEngine failed: %d", result);
142  goto error;
143  }
144  LOGI("slCreateEngine OK");
145 
146  /* realize the engine */
147  result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
148  if (SL_RESULT_SUCCESS != result) {
149  LOGE("RealizeEngine failed: %d", result);
150  goto error;
151  }
152  LOGI("RealizeEngine OK");
153 
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);
158  goto error;
159  }
160  LOGI("EngineGetInterface OK");
161 
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);
168  goto error;
169  }
170  LOGI("CreateOutputMix OK");
171 
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);
176  goto error;
177  }
178  return 1;
179 
180 error:
181  openslES_DestroyEngine();
182  return 0;
183 }
184 
185 /* this callback handler is called every time a buffer finishes recording */
186 static void
187 bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
188 {
189  struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context;
190 
191  LOGV("SLES: Recording Callback");
192  SDL_SemPost(audiodata->playsem);
193 }
194 
195 static void
196 openslES_DestroyPCMRecorder(_THIS)
197 {
198  struct SDL_PrivateAudioData *audiodata = this->hidden;
199  SLresult result;
200 
201  /* stop recording */
202  if (recorderRecord != NULL) {
203  result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
204  if (SL_RESULT_SUCCESS != result) {
205  LOGE("SetRecordState stopped: %d", result);
206  }
207  }
208 
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;
215  }
216 
217  if (audiodata->playsem) {
218  SDL_DestroySemaphore(audiodata->playsem);
219  audiodata->playsem = NULL;
220  }
221 
222  if (audiodata->mixbuff) {
223  SDL_free(audiodata->mixbuff);
224  }
225 }
226 
227 static int
228 openslES_CreatePCMRecorder(_THIS)
229 {
230  struct SDL_PrivateAudioData *audiodata = this->hidden;
231  SLDataFormat_PCM format_pcm;
232  SLresult result;
233  int i;
234 
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");
238  }
239 
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;*/
244 
245  /* Update the fragment size as size in bytes */
247 
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);
251 
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};
255 
256  /* configure audio sink */
257  SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
258 
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;
266 
267  SLDataSink audioSnk = { &loc_bufq, &format_pcm };
268 
269  /* create audio recorder */
270  /* (requires the RECORD_AUDIO permission) */
271  const SLInterfaceID ids[1] = {
272  SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
273  };
274  const SLboolean req[1] = {
275  SL_BOOLEAN_TRUE,
276  };
277 
278  result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc, &audioSnk, 1, ids, req);
279  if (SL_RESULT_SUCCESS != result) {
280  LOGE("CreateAudioRecorder failed: %d", result);
281  goto failed;
282  }
283 
284  /* realize the recorder */
285  result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
286  if (SL_RESULT_SUCCESS != result) {
287  LOGE("RealizeAudioPlayer failed: %d", result);
288  goto failed;
289  }
290 
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);
295  goto failed;
296  }
297 
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);
302  goto failed;
303  }
304 
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);
310  goto failed;
311  }
312 
313  /* Create the audio buffer semaphore */
314  audiodata->playsem = SDL_CreateSemaphore(0);
315  if (!audiodata->playsem) {
316  LOGE("cannot create Semaphore!");
317  goto failed;
318  }
319 
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");
324  goto failed;
325  }
326 
327  for (i = 0; i < NUM_BUFFERS; i++) {
328  audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
329  }
330 
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);
335  goto failed;
336  }
337 
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);
343  goto failed;
344  }
345  }
346 
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);
351  goto failed;
352  }
353 
354  return 0;
355 
356 failed:
357 
358  openslES_DestroyPCMRecorder(this);
359 
360  return SDL_SetError("Open device failed!");
361 }
362 
363 /* this callback handler is called every time a buffer finishes playing */
364 static void
365 bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
366 {
367  struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context;
368 
369  LOGV("SLES: Playback Callback");
370  SDL_SemPost(audiodata->playsem);
371 }
372 
373 static void
374 openslES_DestroyPCMPlayer(_THIS)
375 {
376  struct SDL_PrivateAudioData *audiodata = this->hidden;
377  SLresult result;
378 
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);
384  }
385  }
386 
387  /* destroy buffer queue audio player object, and invalidate all associated interfaces */
388  if (bqPlayerObject != NULL) {
389 
390  (*bqPlayerObject)->Destroy(bqPlayerObject);
391 
392  bqPlayerObject = NULL;
393  bqPlayerPlay = NULL;
394  bqPlayerBufferQueue = NULL;
395  }
396 
397  if (audiodata->playsem) {
398  SDL_DestroySemaphore(audiodata->playsem);
399  audiodata->playsem = NULL;
400  }
401 
402  if (audiodata->mixbuff) {
403  SDL_free(audiodata->mixbuff);
404  }
405 }
406 
407 static int
408 openslES_CreatePCMPlayer(_THIS)
409 {
410  struct SDL_PrivateAudioData *audiodata = this->hidden;
411  SLDataFormat_PCM format_pcm;
412  SLresult result;
413  int i;
414 
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
418  */
419 #if 1
420  /* Just go with signed 16-bit audio as it's the most compatible */
421  this->spec.format = AUDIO_S16SYS;
422 #else
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)) {
426  break;
427  }
428  test_format = SDL_NextAudioFormat();
429  }
430 
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;
435  }
436  this->spec.format = test_format;
437 #endif
438 
439  /* Update the fragment size as size in bytes */
441 
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);
445 
446  /* configure audio source */
447  SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
448 
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);
454 
455  if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) {
456  format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
457  } else {
458  format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
459  }
460 
461  switch (this->spec.channels)
462  {
463  case 1:
464  format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT;
465  break;
466  case 2:
467  format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO;
468  break;
469  case 3:
470  format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_FRONT_CENTER;
471  break;
472  case 4:
473  format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD;
474  break;
475  case 5:
476  format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER;
477  break;
478  case 6:
479  format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1;
480  break;
481  case 7:
482  format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER;
483  break;
484  case 8:
485  format_pcm.channelMask = SL_ANDROID_SPEAKER_7DOT1;
486  break;
487  default:
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;
491  break;
492  }
493 
494  SLDataSource audioSrc = { &loc_bufq, &format_pcm };
495 
496  /* configure audio sink */
497  SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
498  SLDataSink audioSnk = { &loc_outmix, NULL };
499 
500  /* create audio player */
501  const SLInterfaceID ids[2] = {
502  SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
503  SL_IID_VOLUME
504  };
505 
506  const SLboolean req[2] = {
507  SL_BOOLEAN_TRUE,
508  SL_BOOLEAN_FALSE,
509  };
510 
511  result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
512  if (SL_RESULT_SUCCESS != result) {
513  LOGE("CreateAudioPlayer failed: %d", result);
514  goto failed;
515  }
516 
517  /* realize the player */
518  result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
519  if (SL_RESULT_SUCCESS != result) {
520  LOGE("RealizeAudioPlayer failed: %d", result);
521  goto failed;
522  }
523 
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);
528  goto failed;
529  }
530 
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);
535  goto failed;
536  }
537 
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);
543  goto failed;
544  }
545 
546 #if 0
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);
551  /* goto failed; */
552  }
553 #endif
554 
555  /* Create the audio buffer semaphore */
556  audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1);
557  if (!audiodata->playsem) {
558  LOGE("cannot create Semaphore!");
559  goto failed;
560  }
561 
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");
566  goto failed;
567  }
568 
569  for (i = 0; i < NUM_BUFFERS; i++) {
570  audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
571  }
572 
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);
577  goto failed;
578  }
579 
580  return 0;
581 
582 failed:
583 
584  openslES_DestroyPCMPlayer(this);
585 
586  return SDL_SetError("Open device failed!");
587 }
588 
589 static int
590 openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
591 {
592  this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
593  if (this->hidden == NULL) {
594  return SDL_OutOfMemory();
595  }
596 
597  if (iscapture) {
598  LOGI("openslES_OpenDevice() %s for capture", devname);
599  return openslES_CreatePCMRecorder(this);
600  } else {
601  LOGI("openslES_OpenDevice() %s for playing", devname);
602  return openslES_CreatePCMPlayer(this);
603  }
604 }
605 
606 static void
607 openslES_WaitDevice(_THIS)
608 {
609  struct SDL_PrivateAudioData *audiodata = this->hidden;
610 
611  LOGV("openslES_WaitDevice()");
612 
613  /* Wait for an audio chunk to finish */
614  SDL_SemWait(audiodata->playsem);
615 }
616 
617 static void
618 openslES_PlayDevice(_THIS)
619 {
620  struct SDL_PrivateAudioData *audiodata = this->hidden;
621  SLresult result;
622 
623  LOGV("======openslES_PlayDevice()======");
624 
625  /* Queue it up */
626  result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size);
627 
628  audiodata->next_buffer++;
629  if (audiodata->next_buffer >= NUM_BUFFERS) {
630  audiodata->next_buffer = 0;
631  }
632 
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);
637  }
638 }
639 
640 /*/ n playn sem */
641 /* getbuf 0 - 1 */
642 /* fill buff 0 - 1 */
643 /* play 0 - 0 1 */
644 /* wait 1 0 0 */
645 /* getbuf 1 0 0 */
646 /* fill buff 1 0 0 */
647 /* play 0 0 0 */
648 /* wait */
649 /* */
650 /* okay.. */
651 
652 static Uint8 *
653 openslES_GetDeviceBuf(_THIS)
654 {
655  struct SDL_PrivateAudioData *audiodata = this->hidden;
656 
657  LOGV("openslES_GetDeviceBuf()");
658  return audiodata->pmixbuff[audiodata->next_buffer];
659 }
660 
661 static int
662 openslES_CaptureFromDevice(_THIS, void *buffer, int buflen)
663 {
664  struct SDL_PrivateAudioData *audiodata = this->hidden;
665  SLresult result;
666 
667  /* Wait for new recorded data */
668  SDL_SemWait(audiodata->playsem);
669 
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);
673 
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);
678  return -1;
679  }
680 
681  audiodata->next_buffer++;
682  if (audiodata->next_buffer >= NUM_BUFFERS) {
683  audiodata->next_buffer = 0;
684  }
685 
686  return this->spec.size;
687 }
688 
689 static void
690 openslES_CloseDevice(_THIS)
691 {
692  /* struct SDL_PrivateAudioData *audiodata = this->hidden; */
693 
694  if (this->iscapture) {
695  LOGI("openslES_CloseDevice() for capture");
696  openslES_DestroyPCMRecorder(this);
697  } else {
698  LOGI("openslES_CloseDevice() for playing");
699  openslES_DestroyPCMPlayer(this);
700  }
701 
702  SDL_free(this->hidden);
703 }
704 
705 static int
706 openslES_Init(SDL_AudioDriverImpl * impl)
707 {
708  LOGI("openslES_Init() called");
709 
710  if (!openslES_CreateEngine()) {
711  return 0;
712  }
713 
714  LOGI("openslES_Init() - set pointers");
715 
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;
725 
726  /* and the capabilities */
727  impl->HasCaptureSupport = 1;
728  impl->OnlyHasDefaultOutputDevice = 1;
729  impl->OnlyHasDefaultCaptureDevice = 1;
730 
731  LOGI("openslES_Init() - success");
732 
733  /* this audio target is available. */
734  return 1;
735 }
736 
738  "openslES", "opensl ES audio driver", openslES_Init, 0
739 };
740 
741 void openslES_ResumeDevices(void)
742 {
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);
748  }
749  }
750 }
751 
752 void openslES_PauseDevices(void)
753 {
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);
759  }
760  }
761 }
762 
763 #endif /* SDL_AUDIO_DRIVER_OPENSLES */
764 
765 /* vi: set ts=4 sw=4 expandtab: */
#define _THIS
SDL_bool Android_JNI_RequestPermission(const char *permission)
#define SDL_assert(condition)
Definition: SDL_assert.h:171
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1689
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1650
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1662
#define SDL_AUDIO_ISINT(x)
Definition: SDL_audio.h:79
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
#define AUDIO_S16SYS
Definition: SDL_audio.h:123
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
#define SDL_AUDIO_ISSIGNED(x)
Definition: SDL_audio.h:78
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
#define SDL_SetError
#define SDL_SemPost
#define SDL_SemWait
#define SDL_malloc
#define SDL_DestroySemaphore
#define SDL_free
#define SDL_CreateSemaphore
#define SDL_memcpy
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
GLuint64EXT * result
GLuint buffer
GLuint * ids
void openslES_ResumeDevices(void)
#define NUM_BUFFERS
Definition: SDL_openslES.h:31
void openslES_PauseDevices(void)
uint8_t Uint8
Definition: SDL_stdinc.h:185
AudioBootStrap openslES_bootstrap
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
#define NULL
Definition: begin_code.h:163
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
SDL_AudioSpec spec
Definition: loopwave.c:31
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:82
int(* CaptureFromDevice)(_THIS, void *buffer, int buflen)
Definition: SDL_sysaudio.h:75
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
Uint32 size
Definition: SDL_audio.h:186
Uint8 channels
Definition: SDL_audio.h:182
SDL_AudioFormat format
Definition: SDL_audio.h:181
Uint8 * pmixbuff[NUM_BUFFERS]
Definition: SDL_openslES.h:37
static screen_context_t context
Definition: video.c:25