src/audio/openslES/SDL_openslES.c
author Sylvain Becker <sylvain.becker@gmail.com>
Mon, 14 Jan 2019 10:04:54 +0100
changeset 12538 fad97a498ffb
parent 12534 682d9b5ecbed
child 12539 e7282e21da92
permissions -rw-r--r--
Android/openslES: some space and indentation to match SDL conventions
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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 #include "SDL_audio.h"
    26 #include "../SDL_audio_c.h"
    27 #include "SDL_openslES.h"
    28 
    29 // for native audio
    30 #include <SLES/OpenSLES.h>
    31 #include <SLES/OpenSLES_Android.h>
    32 
    33 #include <android/log.h>
    34 
    35 #define LOG_TAG "SDL_openslES"
    36 
    37 //#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
    38 //#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
    39 //#define LOGI(...) do {} while (0)
    40 //#define LOGE(...) do {} while (0)
    41 #define LOGI(...)
    42 #define LOGE(...)
    43 
    44 // engine interfaces
    45 static SLObjectItf engineObject = NULL;
    46 static SLEngineItf engineEngine;
    47 
    48 // output mix interfaces
    49 static SLObjectItf outputMixObject = NULL;
    50 //static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
    51 
    52 // aux effect on the output mix, used by the buffer queue player
    53 // static const SLEnvironmentalReverbSettings reverbSettings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
    54 
    55 // buffer queue player interfaces
    56 static SLObjectItf                   bqPlayerObject = NULL;
    57 static SLPlayItf                     bqPlayerPlay;
    58 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
    59 //static SLEffectSendItf          bqPlayerEffectSend;
    60 static SLMuteSoloItf                 bqPlayerMuteSolo;
    61 static SLVolumeItf                   bqPlayerVolume;
    62 
    63 #if 0
    64 // recorder interfaces TODO
    65 static SLObjectItf                   recorderObject = NULL;
    66 static SLRecordItf                   recorderRecord;
    67 static SLAndroidSimpleBufferQueueItf recorderBufferQueue;
    68 #endif
    69 
    70 // pointer and size of the next player buffer to enqueue, and number of remaining buffers
    71 #if 0
    72 static short      *nextBuffer;
    73 static unsigned    nextSize;
    74 static int         nextCount;
    75 #endif
    76 
    77 #define NUM_BUFFERS 2           /* -- Don't lower this! */
    78 
    79 static Uint8   *mixbuff               = NULL;
    80 static int      next_buffer           = 0;
    81 static Uint8   *pmixbuff[NUM_BUFFERS];
    82 
    83 static SDL_sem *playsem               = NULL;
    84 #if 0
    85 static SDL_sem *recsem                = NULL;
    86 #endif
    87 
    88 //static SDL_AudioDevice* audioDevice = NULL;
    89 
    90 #if 0
    91 static const char *sldevaudiorecorderstr = "SLES Audio Recorder";
    92 static const char *sldevaudioplayerstr   = "SLES Audio Player";
    93 
    94 #define  SLES_DEV_AUDIO_RECORDER  sldevaudiorecorderstr
    95 #define  SLES_DEV_AUDIO_PLAYER  sldevaudioplayerstr
    96 static void openslES_DetectDevices( int iscapture )
    97 {
    98   LOGI( "openSLES_DetectDevices()" );
    99     if ( iscapture )
   100             addfn( SLES_DEV_AUDIO_RECORDER );
   101   else
   102             addfn( SLES_DEV_AUDIO_PLAYER );
   103   return;
   104 }
   105 #endif
   106 
   107 static void openslES_DestroyEngine(void);
   108 
   109 static int
   110 openslES_CreateEngine(void)
   111 {
   112     SLresult result;
   113 
   114     LOGI("openSLES_CreateEngine()");
   115 
   116     // create engine
   117     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
   118     if (SL_RESULT_SUCCESS != result) {
   119         LOGE("slCreateEngine failed");
   120         goto error;
   121     }
   122 
   123     LOGI("slCreateEngine OK");
   124 
   125     // realize the engine
   126     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
   127     if (SL_RESULT_SUCCESS != result) {
   128         LOGE("RealizeEngine failed");
   129         goto error;
   130     }
   131 
   132     LOGI("RealizeEngine OK");
   133 
   134     // get the engine interface, which is needed in order to create other objects
   135     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
   136     if (SL_RESULT_SUCCESS != result) {
   137         LOGE("EngineGetInterface failed");
   138         goto error;
   139     }
   140 
   141     LOGI("EngineGetInterface OK");
   142 
   143     // create output mix, with environmental reverb specified as a non-required interface
   144     // const SLInterfaceID ids[1] = { SL_IID_ENVIRONMENTALREVERB };
   145     // const SLboolean req[1] = { SL_BOOLEAN_FALSE };
   146 
   147     const SLInterfaceID ids[1] = { SL_IID_VOLUME };
   148     const SLboolean req[1] = { SL_BOOLEAN_FALSE };
   149     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
   150 
   151     if (SL_RESULT_SUCCESS != result) {
   152         LOGE("CreateOutputMix failed");
   153         goto error;
   154     }
   155     LOGI("CreateOutputMix OK");
   156 
   157     // realize the output mix
   158     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
   159     if (SL_RESULT_SUCCESS != result) {
   160         LOGE("RealizeOutputMix failed");
   161         goto error;
   162     }
   163     return 1;
   164 
   165 error:
   166     openslES_DestroyEngine();
   167     return 0;
   168 }
   169 
   170 static void openslES_DestroyPCMPlayer(void);
   171 static void openslES_DestroyPCMRecorder(void);
   172 
   173 static void openslES_DestroyEngine(void)
   174 {
   175     LOGI("openslES_DestroyEngine()");
   176     openslES_DestroyPCMPlayer();
   177     openslES_DestroyPCMRecorder();
   178 
   179     // destroy output mix object, and invalidate all associated interfaces
   180     if (outputMixObject != NULL) {
   181         (*outputMixObject)->Destroy(outputMixObject);
   182         outputMixObject = NULL;
   183         // outputMixEnvironmentalReverb = NULL;
   184     }
   185 
   186     // destroy engine object, and invalidate all associated interfaces
   187     if (engineObject != NULL) {
   188         (*engineObject)->Destroy(engineObject);
   189         engineObject = NULL;
   190         engineEngine = NULL;
   191     }
   192 
   193     return;
   194 }
   195 
   196 // this callback handler is called every time a buffer finishes playing
   197 static void
   198 bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
   199 {
   200     static int t = 0;
   201 
   202     // assert(bq == bqPlayerBufferQueue);
   203     // assert(NULL == context);
   204 
   205     // for streaming playback, replace this test by logic to find and fill the next buffer
   206 #if 0
   207     if (--nextCount > 0 && NULL != nextBuffer && 0 != nextSize)
   208     {
   209         SLresult result;
   210 
   211         // enqueue another buffer
   212         result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
   213         // the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
   214         // which for this code example would indicate a programming error
   215         assert(SL_RESULT_SUCCESS == result);
   216         (void) result;
   217     }
   218 #endif
   219     LOGI("SLES: Playback Callmeback %u", t++);
   220     SDL_SemPost(playsem);
   221     return;
   222 }
   223 
   224 static int
   225 openslES_CreatePCMRecorder(_THIS)
   226 {
   227     LOGE("openslES_CreatePCMRecorder not implimented yet!");
   228     return SDL_SetError("openslES_CreatePCMRecorder not implimented yet!");
   229 }
   230 
   231 static void
   232 openslES_DestroyPCMRecorder(void)
   233 {
   234     return;
   235 }
   236 
   237 static int
   238 openslES_CreatePCMPlayer(
   239       _THIS)
   240 {
   241     SLDataFormat_PCM format_pcm;
   242 
   243     SLresult result;
   244     int i;
   245 
   246     /*
   247       SDL_AudioFormat test_format;
   248       test_format = SDL_FirstAudioFormat( this->spec.format );
   249 
   250       while (test_format != 0) {
   251 
   252           if (SDL_AUDIO_ISSIGNED(test_format) && SDL_AUDIO_ISINT(test_format)) {
   253               break;
   254           }
   255           test_format = SDL_NextAudioFormat();
   256       }
   257 
   258       if ( test_format == 0 ) {
   259           // Didn't find a compatible format :
   260           LOGI( "No compatible audio format!" );
   261           return SDL_SetError("No compatible audio format!");
   262       }
   263 
   264       this->spec.format = test_format;
   265     */
   266 
   267     // Update the fragment size as size in bytes
   268     SDL_CalculateAudioSpec(&this->spec);
   269 
   270     LOGI("Try to open %u hz %u bit chan %u %s samples %u",
   271           this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format),
   272           this->spec.channels, (test_format & 0x1000) ? "BE" : "LE", this->spec.samples);
   273 
   274     // configure audio source
   275     SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
   276     // SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, OPENSLES_BUFFERS };
   277 
   278     format_pcm.formatType    = SL_DATAFORMAT_PCM;
   279     format_pcm.numChannels   = this->spec.channels;
   280     format_pcm.samplesPerSec = this->spec.freq * 1000;  // / kilo Hz to milli Hz
   281     format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
   282     format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format);
   283 
   284     if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) {
   285         format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
   286     } else {
   287         format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
   288     }
   289 
   290 /*
   291 #define SL_SPEAKER_FRONT_LEFT            ((SLuint32) 0x00000001)
   292 #define SL_SPEAKER_FRONT_RIGHT           ((SLuint32) 0x00000002)
   293 #define SL_SPEAKER_FRONT_CENTER          ((SLuint32) 0x00000004)
   294 #define SL_SPEAKER_LOW_FREQUENCY         ((SLuint32) 0x00000008)
   295 #define SL_SPEAKER_BACK_LEFT             ((SLuint32) 0x00000010)
   296 #define SL_SPEAKER_BACK_RIGHT            ((SLuint32) 0x00000020)
   297 #define SL_SPEAKER_FRONT_LEFT_OF_CENTER  ((SLuint32) 0x00000040)
   298 #define SL_SPEAKER_FRONT_RIGHT_OF_CENTER ((SLuint32) 0x00000080)
   299 #define SL_SPEAKER_BACK_CENTER           ((SLuint32) 0x00000100)
   300 #define SL_SPEAKER_SIDE_LEFT             ((SLuint32) 0x00000200)
   301 #define SL_SPEAKER_SIDE_RIGHT            ((SLuint32) 0x00000400)
   302 #define SL_SPEAKER_TOP_CENTER            ((SLuint32) 0x00000800)
   303 #define SL_SPEAKER_TOP_FRONT_LEFT        ((SLuint32) 0x00001000)
   304 #define SL_SPEAKER_TOP_FRONT_CENTER      ((SLuint32) 0x00002000)
   305 #define SL_SPEAKER_TOP_FRONT_RIGHT       ((SLuint32) 0x00004000)
   306 #define SL_SPEAKER_TOP_BACK_LEFT         ((SLuint32) 0x00008000)
   307 #define SL_SPEAKER_TOP_BACK_CENTER       ((SLuint32) 0x00010000)
   308 #define SL_SPEAKER_TOP_BACK_RIGHT        ((SLuint32) 0x00020000)
   309 */
   310 
   311     if (this->spec.channels == 1) {
   312         format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
   313     } else if (this->spec.channels == 2) {
   314         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
   315     } else if (this->spec.channels == 3) {
   316         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER;
   317     } else if (this->spec.channels == 4) {
   318         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   319               SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT;
   320     } else {
   321         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   322               SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_FRONT_CENTER;
   323     }
   324 
   325     SLDataSource audioSrc = { &loc_bufq, &format_pcm };
   326 
   327     // configure audio sink
   328     SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
   329     SLDataSink audioSnk = { &loc_outmix, NULL };
   330 
   331     // create audio player
   332     const SLInterfaceID ids[2] = {
   333         SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
   334         SL_IID_VOLUME
   335     };
   336 
   337     const SLboolean req[2] = {
   338         SL_BOOLEAN_TRUE,
   339         SL_BOOLEAN_FALSE,
   340     };
   341 
   342     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
   343     if (SL_RESULT_SUCCESS != result) {
   344         LOGE("CreateAudioPlayer failed");
   345         goto failed;
   346     }
   347 
   348     // realize the player
   349     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
   350     if (SL_RESULT_SUCCESS != result) {
   351         LOGE("RealizeAudioPlayer failed");
   352         goto failed;
   353     }
   354 
   355     // get the play interface
   356     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
   357     if (SL_RESULT_SUCCESS != result) {
   358         LOGE("SL_IID_PLAY interface get failed");
   359         goto failed;
   360     }
   361 
   362     // get the buffer queue interface
   363     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue);
   364     if (SL_RESULT_SUCCESS != result) {
   365         LOGE("SL_IID_BUFFERQUEUE interface get failed");
   366         goto failed;
   367     }
   368 
   369     // register callback on the buffer queue
   370     result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
   371     if (SL_RESULT_SUCCESS != result) {
   372         LOGE("RegisterCallback failed");
   373         goto failed;
   374     }
   375 
   376 #if 0
   377     // get the effect send interface
   378     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND, &bqPlayerEffectSend);
   379     if (SL_RESULT_SUCCESS != result)
   380     {
   381 
   382         LOGE("SL_IID_EFFECTSEND interface get failed");
   383         goto failed;
   384     }
   385 #endif
   386 
   387 #if 0   // mute/solo is not supported for sources that are known to be mono, as this is
   388     // get the mute/solo interface
   389     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo);
   390     assert(SL_RESULT_SUCCESS == result);
   391     (void) result;
   392 #endif
   393 
   394     // get the volume interface
   395     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
   396     if (SL_RESULT_SUCCESS != result) {
   397         LOGE("SL_IID_VOLUME interface get failed");
   398         // goto failed;
   399     }
   400 
   401     // set the player's state to playing
   402     result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
   403     if (SL_RESULT_SUCCESS != result) {
   404         LOGE("Play set state failed");
   405         goto failed;
   406     }
   407 
   408     /* Create the audio buffer semaphore */
   409     playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1);
   410     if (!playsem) {
   411         LOGE("cannot create Semaphore!");
   412         goto failed;
   413     }
   414 
   415     /* Create the sound buffers */
   416     mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
   417     if (mixbuff == NULL) {
   418         LOGE("mixbuffer allocate - out of memory");
   419         goto failed;
   420     }
   421 
   422     for (i = 0; i < NUM_BUFFERS; i++) {
   423         pmixbuff[i] = mixbuff + i * this->spec.size;
   424     }
   425 
   426     return 0;
   427 
   428 failed:
   429 
   430     openslES_DestroyPCMPlayer();
   431 
   432     return SDL_SetError("Open device failed!");
   433 }
   434 
   435 static void
   436 openslES_DestroyPCMPlayer(void)
   437 {
   438     // destroy buffer queue audio player object, and invalidate all associated interfaces
   439     if (bqPlayerObject != NULL) {
   440 
   441         (*bqPlayerObject)->Destroy(bqPlayerObject);
   442 
   443         bqPlayerObject = NULL;
   444         bqPlayerPlay = NULL;
   445         bqPlayerBufferQueue = NULL;
   446         // bqPlayerEffectSend = NULL;
   447         bqPlayerMuteSolo = NULL;
   448         bqPlayerVolume = NULL;
   449     }
   450 
   451     if (playsem) {
   452         SDL_DestroySemaphore(playsem);
   453         playsem = NULL;
   454     }
   455 
   456     if (mixbuff) {
   457         SDL_free(mixbuff);
   458     }
   459 
   460     return;
   461 }
   462 
   463 static int
   464 openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   465 {
   466     if (iscapture) {
   467         LOGI("openslES_OpenDevice( ) %s for capture", devname);
   468         return openslES_CreatePCMRecorder(this);
   469     } else {
   470         LOGI("openslES_OpenDevice( ) %s for playing", devname);
   471         return openslES_CreatePCMPlayer(this);
   472     }
   473 }
   474 
   475 static void
   476 openslES_CloseDevice(_THIS)
   477 {
   478     if (this->iscapture) {
   479         LOGI("openslES_CloseDevice( ) for capture");
   480         openslES_DestroyPCMRecorder();
   481     } else {
   482         LOGI("openslES_CloseDevice( ) for playing");
   483         openslES_DestroyPCMPlayer();
   484     }
   485 
   486     return;
   487 }
   488 
   489 static void
   490 openslES_WaitDevice(_THIS)
   491 {
   492     LOGI("openslES_WaitDevice( )");
   493 
   494     /* Wait for an audio chunk to finish */
   495     // WaitForSingleObject(this->hidden->audio_sem, INFINITE);
   496     SDL_SemWait(playsem);
   497 
   498     return;
   499 }
   500 
   501 ///           n   playn sem
   502 // getbuf     0   -     1
   503 // fill buff  0   -     1
   504 // play       0 - 0     1
   505 // wait       1   0     0
   506 // getbuf     1   0     0
   507 // fill buff  1   0     0
   508 // play       0   0     0
   509 // wait
   510 //
   511 // okay..
   512 
   513 static Uint8 *
   514 openslES_GetDeviceBuf(_THIS)
   515 {
   516     LOGI("openslES_GetDeviceBuf( )");
   517     return pmixbuff[next_buffer];
   518 }
   519 
   520 static void
   521 openslES_PlayDevice(_THIS)
   522 {
   523     SLresult result;
   524 
   525     LOGI("======openslES_PlayDevice( )======");
   526     /* Queue it up */
   527 
   528     result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, pmixbuff[next_buffer], this->spec.size);
   529     if (SL_RESULT_SUCCESS != result) {
   530         // just puk here
   531         // next !
   532     }
   533 
   534     next_buffer++;
   535     if (next_buffer >= NUM_BUFFERS) {
   536         next_buffer = 0;
   537     }
   538 
   539     return;
   540 }
   541 
   542 static int
   543 openslES_Init(SDL_AudioDriverImpl * impl)
   544 {
   545     LOGI("openslES_Init() called");
   546 
   547     if (!openslES_CreateEngine()) {
   548         return 0;
   549     }
   550 
   551     LOGI("openslES_Init() - set pointers");
   552 
   553     /* Set the function pointers */
   554     // impl->DetectDevices = openslES_DetectDevices;
   555     impl->OpenDevice    = openslES_OpenDevice;
   556     impl->PlayDevice    = openslES_PlayDevice;
   557     impl->GetDeviceBuf  = openslES_GetDeviceBuf;
   558     impl->Deinitialize  = openslES_DestroyEngine;
   559     impl->WaitDevice    = openslES_WaitDevice;
   560 
   561     /* and the capabilities */
   562     impl->HasCaptureSupport             = 0;        /* TODO */
   563     impl->OnlyHasDefaultOutputDevice    = 1;
   564     // impl->OnlyHasDefaultInputDevice  = 1;
   565 
   566     LOGI("openslES_Init() - succes");
   567 
   568     /* this audio target is available. */
   569     return 1;
   570 }
   571 
   572 AudioBootStrap openslES_bootstrap = {
   573     "openslES", "opensl ES audio driver", openslES_Init, 0
   574 };
   575 
   576 #endif /* SDL_AUDIO_DRIVER_OPENSLES */
   577 
   578 /* vi: set ts=4 sw=4 expandtab: */