src/audio/openslES/SDL_openslES.c
author Sylvain Becker <sylvain.becker@gmail.com>
Mon, 14 Jan 2019 10:16:26 +0100
changeset 12539 e7282e21da92
parent 12538 fad97a498ffb
child 12540 2660c01ff7da
permissions -rw-r--r--
Android/openslES: register and use CloseDevice function.
     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(_THIS)
   239 {
   240     SLDataFormat_PCM format_pcm;
   241 
   242     SLresult result;
   243     int i;
   244 
   245     /*
   246       SDL_AudioFormat test_format;
   247       test_format = SDL_FirstAudioFormat( this->spec.format );
   248 
   249       while (test_format != 0) {
   250 
   251           if (SDL_AUDIO_ISSIGNED(test_format) && SDL_AUDIO_ISINT(test_format)) {
   252               break;
   253           }
   254           test_format = SDL_NextAudioFormat();
   255       }
   256 
   257       if ( test_format == 0 ) {
   258           // Didn't find a compatible format :
   259           LOGI( "No compatible audio format!" );
   260           return SDL_SetError("No compatible audio format!");
   261       }
   262 
   263       this->spec.format = test_format;
   264     */
   265 
   266     // Update the fragment size as size in bytes
   267     SDL_CalculateAudioSpec(&this->spec);
   268 
   269     LOGI("Try to open %u hz %u bit chan %u %s samples %u",
   270           this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format),
   271           this->spec.channels, (test_format & 0x1000) ? "BE" : "LE", this->spec.samples);
   272 
   273     // configure audio source
   274     SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
   275     // SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, OPENSLES_BUFFERS };
   276 
   277     format_pcm.formatType    = SL_DATAFORMAT_PCM;
   278     format_pcm.numChannels   = this->spec.channels;
   279     format_pcm.samplesPerSec = this->spec.freq * 1000;  // / kilo Hz to milli Hz
   280     format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
   281     format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format);
   282 
   283     if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) {
   284         format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
   285     } else {
   286         format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
   287     }
   288 
   289 /*
   290 #define SL_SPEAKER_FRONT_LEFT            ((SLuint32) 0x00000001)
   291 #define SL_SPEAKER_FRONT_RIGHT           ((SLuint32) 0x00000002)
   292 #define SL_SPEAKER_FRONT_CENTER          ((SLuint32) 0x00000004)
   293 #define SL_SPEAKER_LOW_FREQUENCY         ((SLuint32) 0x00000008)
   294 #define SL_SPEAKER_BACK_LEFT             ((SLuint32) 0x00000010)
   295 #define SL_SPEAKER_BACK_RIGHT            ((SLuint32) 0x00000020)
   296 #define SL_SPEAKER_FRONT_LEFT_OF_CENTER  ((SLuint32) 0x00000040)
   297 #define SL_SPEAKER_FRONT_RIGHT_OF_CENTER ((SLuint32) 0x00000080)
   298 #define SL_SPEAKER_BACK_CENTER           ((SLuint32) 0x00000100)
   299 #define SL_SPEAKER_SIDE_LEFT             ((SLuint32) 0x00000200)
   300 #define SL_SPEAKER_SIDE_RIGHT            ((SLuint32) 0x00000400)
   301 #define SL_SPEAKER_TOP_CENTER            ((SLuint32) 0x00000800)
   302 #define SL_SPEAKER_TOP_FRONT_LEFT        ((SLuint32) 0x00001000)
   303 #define SL_SPEAKER_TOP_FRONT_CENTER      ((SLuint32) 0x00002000)
   304 #define SL_SPEAKER_TOP_FRONT_RIGHT       ((SLuint32) 0x00004000)
   305 #define SL_SPEAKER_TOP_BACK_LEFT         ((SLuint32) 0x00008000)
   306 #define SL_SPEAKER_TOP_BACK_CENTER       ((SLuint32) 0x00010000)
   307 #define SL_SPEAKER_TOP_BACK_RIGHT        ((SLuint32) 0x00020000)
   308 */
   309 
   310     if (this->spec.channels == 1) {
   311         format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
   312     } else if (this->spec.channels == 2) {
   313         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
   314     } else if (this->spec.channels == 3) {
   315         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER;
   316     } else if (this->spec.channels == 4) {
   317         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   318               SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT;
   319     } else {
   320         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   321               SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_FRONT_CENTER;
   322     }
   323 
   324     SLDataSource audioSrc = { &loc_bufq, &format_pcm };
   325 
   326     // configure audio sink
   327     SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
   328     SLDataSink audioSnk = { &loc_outmix, NULL };
   329 
   330     // create audio player
   331     const SLInterfaceID ids[2] = {
   332         SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
   333         SL_IID_VOLUME
   334     };
   335 
   336     const SLboolean req[2] = {
   337         SL_BOOLEAN_TRUE,
   338         SL_BOOLEAN_FALSE,
   339     };
   340 
   341     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
   342     if (SL_RESULT_SUCCESS != result) {
   343         LOGE("CreateAudioPlayer failed");
   344         goto failed;
   345     }
   346 
   347     // realize the player
   348     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
   349     if (SL_RESULT_SUCCESS != result) {
   350         LOGE("RealizeAudioPlayer failed");
   351         goto failed;
   352     }
   353 
   354     // get the play interface
   355     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
   356     if (SL_RESULT_SUCCESS != result) {
   357         LOGE("SL_IID_PLAY interface get failed");
   358         goto failed;
   359     }
   360 
   361     // get the buffer queue interface
   362     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue);
   363     if (SL_RESULT_SUCCESS != result) {
   364         LOGE("SL_IID_BUFFERQUEUE interface get failed");
   365         goto failed;
   366     }
   367 
   368     // register callback on the buffer queue
   369     result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
   370     if (SL_RESULT_SUCCESS != result) {
   371         LOGE("RegisterCallback failed");
   372         goto failed;
   373     }
   374 
   375 #if 0
   376     // get the effect send interface
   377     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND, &bqPlayerEffectSend);
   378     if (SL_RESULT_SUCCESS != result)
   379     {
   380 
   381         LOGE("SL_IID_EFFECTSEND interface get failed");
   382         goto failed;
   383     }
   384 #endif
   385 
   386 #if 0   // mute/solo is not supported for sources that are known to be mono, as this is
   387     // get the mute/solo interface
   388     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo);
   389     assert(SL_RESULT_SUCCESS == result);
   390     (void) result;
   391 #endif
   392 
   393     // get the volume interface
   394     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
   395     if (SL_RESULT_SUCCESS != result) {
   396         LOGE("SL_IID_VOLUME interface get failed");
   397         // goto failed;
   398     }
   399 
   400     // set the player's state to playing
   401     result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
   402     if (SL_RESULT_SUCCESS != result) {
   403         LOGE("Play set state failed");
   404         goto failed;
   405     }
   406 
   407     /* Create the audio buffer semaphore */
   408     playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1);
   409     if (!playsem) {
   410         LOGE("cannot create Semaphore!");
   411         goto failed;
   412     }
   413 
   414     /* Create the sound buffers */
   415     mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
   416     if (mixbuff == NULL) {
   417         LOGE("mixbuffer allocate - out of memory");
   418         goto failed;
   419     }
   420 
   421     for (i = 0; i < NUM_BUFFERS; i++) {
   422         pmixbuff[i] = mixbuff + i * this->spec.size;
   423     }
   424 
   425     return 0;
   426 
   427 failed:
   428 
   429     openslES_DestroyPCMPlayer();
   430 
   431     return SDL_SetError("Open device failed!");
   432 }
   433 
   434 static void
   435 openslES_DestroyPCMPlayer(void)
   436 {
   437     // destroy buffer queue audio player object, and invalidate all associated interfaces
   438     if (bqPlayerObject != NULL) {
   439 
   440         (*bqPlayerObject)->Destroy(bqPlayerObject);
   441 
   442         bqPlayerObject = NULL;
   443         bqPlayerPlay = NULL;
   444         bqPlayerBufferQueue = NULL;
   445         // bqPlayerEffectSend = NULL;
   446         bqPlayerMuteSolo = NULL;
   447         bqPlayerVolume = NULL;
   448     }
   449 
   450     if (playsem) {
   451         SDL_DestroySemaphore(playsem);
   452         playsem = NULL;
   453     }
   454 
   455     if (mixbuff) {
   456         SDL_free(mixbuff);
   457     }
   458 
   459     return;
   460 }
   461 
   462 static int
   463 openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   464 {
   465     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
   466     if (this->hidden == NULL) {
   467         return SDL_OutOfMemory();
   468     }
   469 
   470     if (iscapture) {
   471         LOGI("openslES_OpenDevice( ) %s for capture", devname);
   472         return openslES_CreatePCMRecorder(this);
   473     } else {
   474         LOGI("openslES_OpenDevice( ) %s for playing", devname);
   475         return openslES_CreatePCMPlayer(this);
   476     }
   477 }
   478 
   479 static void
   480 openslES_CloseDevice(_THIS)
   481 {
   482     if (this->iscapture) {
   483         LOGI("openslES_CloseDevice( ) for capture");
   484         openslES_DestroyPCMRecorder();
   485     } else {
   486         LOGI("openslES_CloseDevice( ) for playing");
   487         SDL_Log("openslES_CloseDevice( ) for playing");
   488         openslES_DestroyPCMPlayer();
   489     }
   490 
   491     SDL_free(this->hidden);
   492 
   493     return;
   494 }
   495 
   496 static void
   497 openslES_WaitDevice(_THIS)
   498 {
   499     LOGI("openslES_WaitDevice( )");
   500 
   501     /* Wait for an audio chunk to finish */
   502     // WaitForSingleObject(this->hidden->audio_sem, INFINITE);
   503     SDL_SemWait(playsem);
   504 
   505     return;
   506 }
   507 
   508 ///           n   playn sem
   509 // getbuf     0   -     1
   510 // fill buff  0   -     1
   511 // play       0 - 0     1
   512 // wait       1   0     0
   513 // getbuf     1   0     0
   514 // fill buff  1   0     0
   515 // play       0   0     0
   516 // wait
   517 //
   518 // okay..
   519 
   520 static Uint8 *
   521 openslES_GetDeviceBuf(_THIS)
   522 {
   523     LOGI("openslES_GetDeviceBuf( )");
   524     return pmixbuff[next_buffer];
   525 }
   526 
   527 static void
   528 openslES_PlayDevice(_THIS)
   529 {
   530     SLresult result;
   531 
   532     LOGI("======openslES_PlayDevice( )======");
   533     /* Queue it up */
   534 
   535     result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, pmixbuff[next_buffer], this->spec.size);
   536     if (SL_RESULT_SUCCESS != result) {
   537         // just puk here
   538         // next !
   539     }
   540 
   541     next_buffer++;
   542     if (next_buffer >= NUM_BUFFERS) {
   543         next_buffer = 0;
   544     }
   545 
   546     return;
   547 }
   548 
   549 static int
   550 openslES_Init(SDL_AudioDriverImpl * impl)
   551 {
   552     LOGI("openslES_Init() called");
   553 
   554     if (!openslES_CreateEngine()) {
   555         return 0;
   556     }
   557 
   558     LOGI("openslES_Init() - set pointers");
   559 
   560     /* Set the function pointers */
   561     // impl->DetectDevices = openslES_DetectDevices;
   562     impl->OpenDevice    = openslES_OpenDevice;
   563     impl->CloseDevice   = openslES_CloseDevice;
   564     impl->PlayDevice    = openslES_PlayDevice;
   565     impl->GetDeviceBuf  = openslES_GetDeviceBuf;
   566     impl->Deinitialize  = openslES_DestroyEngine;
   567     impl->WaitDevice    = openslES_WaitDevice;
   568 
   569     /* and the capabilities */
   570     impl->HasCaptureSupport             = 0;        /* TODO */
   571     impl->OnlyHasDefaultOutputDevice    = 1;
   572     // impl->OnlyHasDefaultInputDevice  = 1;
   573 
   574     LOGI("openslES_Init() - succes");
   575 
   576     /* this audio target is available. */
   577     return 1;
   578 }
   579 
   580 AudioBootStrap openslES_bootstrap = {
   581     "openslES", "opensl ES audio driver", openslES_Init, 0
   582 };
   583 
   584 #endif /* SDL_AUDIO_DRIVER_OPENSLES */
   585 
   586 /* vi: set ts=4 sw=4 expandtab: */