Initial Android OpenSL ES implementation, contributed by ANTA
authorSam Lantinga <slouken@libsdl.org>
Sat, 12 Jan 2019 12:18:44 -0800
changeset 12534682d9b5ecbed
parent 12533 eb22f5f6d5a5
child 12538 fad97a498ffb
Initial Android OpenSL ES implementation, contributed by ANTA
Android.mk
include/SDL_config_android.h
src/audio/SDL_audio.c
src/audio/SDL_sysaudio.h
src/audio/openslES/SDL_openslES.c
src/audio/openslES/SDL_openslES.h
     1.1 --- a/Android.mk	Sat Jan 12 12:12:43 2019 -0800
     1.2 +++ b/Android.mk	Sat Jan 12 12:18:44 2019 -0800
     1.3 @@ -20,6 +20,7 @@
     1.4  	$(wildcard $(LOCAL_PATH)/src/audio/*.c) \
     1.5  	$(wildcard $(LOCAL_PATH)/src/audio/android/*.c) \
     1.6  	$(wildcard $(LOCAL_PATH)/src/audio/dummy/*.c) \
     1.7 +	$(wildcard $(LOCAL_PATH)/src/audio/openslES/*.c) \
     1.8  	$(LOCAL_PATH)/src/atomic/SDL_atomic.c.arm \
     1.9  	$(LOCAL_PATH)/src/atomic/SDL_spinlock.c.arm \
    1.10  	$(wildcard $(LOCAL_PATH)/src/core/android/*.c) \
    1.11 @@ -69,7 +70,7 @@
    1.12  LOCAL_CFLAGS += -Wno-unused-parameter -Wno-sign-compare
    1.13   
    1.14  
    1.15 -LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
    1.16 +LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid
    1.17  
    1.18  ifeq ($(NDK_DEBUG),1)
    1.19      cmd-strip :=
     2.1 --- a/include/SDL_config_android.h	Sat Jan 12 12:12:43 2019 -0800
     2.2 +++ b/include/SDL_config_android.h	Sat Jan 12 12:18:44 2019 -0800
     2.3 @@ -130,6 +130,7 @@
     2.4  
     2.5  /* Enable various audio drivers */
     2.6  #define SDL_AUDIO_DRIVER_ANDROID    1
     2.7 +#define SDL_AUDIO_DRIVER_OPENSLES   1
     2.8  #define SDL_AUDIO_DRIVER_DUMMY  1
     2.9  
    2.10  /* Enable various input drivers */
     3.1 --- a/src/audio/SDL_audio.c	Sat Jan 12 12:12:43 2019 -0800
     3.2 +++ b/src/audio/SDL_audio.c	Sat Jan 12 12:18:44 2019 -0800
     3.3 @@ -92,6 +92,9 @@
     3.4  #if SDL_AUDIO_DRIVER_ANDROID
     3.5      &ANDROIDAUDIO_bootstrap,
     3.6  #endif
     3.7 +#if SDL_AUDIO_DRIVER_OPENSLES
     3.8 +    &openslES_bootstrap,
     3.9 +#endif
    3.10  #if SDL_AUDIO_DRIVER_PSP
    3.11      &PSPAUDIO_bootstrap,
    3.12  #endif
     4.1 --- a/src/audio/SDL_sysaudio.h	Sat Jan 12 12:12:43 2019 -0800
     4.2 +++ b/src/audio/SDL_sysaudio.h	Sat Jan 12 12:18:44 2019 -0800
     4.3 @@ -205,6 +205,7 @@
     4.4  extern AudioBootStrap DUMMYAUDIO_bootstrap;
     4.5  extern AudioBootStrap FUSIONSOUND_bootstrap;
     4.6  extern AudioBootStrap ANDROIDAUDIO_bootstrap;
     4.7 +extern AudioBootStrap openslES_bootstrap;
     4.8  extern AudioBootStrap PSPAUDIO_bootstrap;
     4.9  extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
    4.10  
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/audio/openslES/SDL_openslES.c	Sat Jan 12 12:18:44 2019 -0800
     5.3 @@ -0,0 +1,573 @@
     5.4 +/*
     5.5 +  Simple DirectMedia Layer
     5.6 +  Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
     5.7 +
     5.8 +  This software is provided 'as-is', without any express or implied
     5.9 +  warranty.  In no event will the authors be held liable for any damages
    5.10 +  arising from the use of this software.
    5.11 +
    5.12 +  Permission is granted to anyone to use this software for any purpose,
    5.13 +  including commercial applications, and to alter it and redistribute it
    5.14 +  freely, subject to the following restrictions:
    5.15 +
    5.16 +  1. The origin of this software must not be misrepresented; you must not
    5.17 +     claim that you wrote the original software. If you use this software
    5.18 +     in a product, an acknowledgment in the product documentation would be
    5.19 +     appreciated but is not required.
    5.20 +  2. Altered source versions must be plainly marked as such, and must not be
    5.21 +     misrepresented as being the original software.
    5.22 +  3. This notice may not be removed or altered from any source distribution.
    5.23 +*/
    5.24 +#include "../../SDL_internal.h"
    5.25 +
    5.26 +#if SDL_AUDIO_DRIVER_OPENSLES
    5.27 +
    5.28 +#include "SDL_audio.h"
    5.29 +#include "../SDL_audio_c.h"
    5.30 +#include "SDL_openslES.h"
    5.31 +
    5.32 +// for native audio
    5.33 +#include <SLES/OpenSLES.h>
    5.34 +#include <SLES/OpenSLES_Android.h>
    5.35 +
    5.36 +#include <android/log.h>
    5.37 +
    5.38 +#define LOG_TAG "SDL_openslES"
    5.39 +
    5.40 +//#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
    5.41 +//#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
    5.42 +//#define LOGI(...) do {} while (0)
    5.43 +//#define LOGE(...) do {} while (0)
    5.44 +#define LOGI(...)
    5.45 +#define LOGE(...)
    5.46 +
    5.47 +// engine interfaces
    5.48 +static SLObjectItf engineObject = NULL;
    5.49 +static SLEngineItf engineEngine;
    5.50 +
    5.51 +// output mix interfaces
    5.52 +static SLObjectItf outputMixObject = NULL;
    5.53 +//static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
    5.54 +
    5.55 +// aux effect on the output mix, used by the buffer queue player
    5.56 +static const SLEnvironmentalReverbSettings reverbSettings =
    5.57 +    SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR;
    5.58 +
    5.59 +// buffer queue player interfaces
    5.60 +static SLObjectItf						bqPlayerObject = NULL;
    5.61 +static SLPlayItf 						bqPlayerPlay;
    5.62 +static SLAndroidSimpleBufferQueueItf	bqPlayerBufferQueue;
    5.63 +//static SLEffectSendItf					bqPlayerEffectSend;
    5.64 +static SLMuteSoloItf					bqPlayerMuteSolo;
    5.65 +static SLVolumeItf						bqPlayerVolume;
    5.66 +
    5.67 +// recorder interfaces TODO
    5.68 +static SLObjectItf						recorderObject = NULL;
    5.69 +static SLRecordItf						recorderRecord;
    5.70 +static SLAndroidSimpleBufferQueueItf	recorderBufferQueue;
    5.71 +
    5.72 +// pointer and size of the next player buffer to enqueue, and number of remaining buffers
    5.73 +static short 	*nextBuffer;
    5.74 +static unsigned	nextSize;
    5.75 +static int 		nextCount;
    5.76 +
    5.77 +static const char	*sldevaudiorecorderstr	= "SLES Audio Recorder";
    5.78 +static const char	*sldevaudioplayerstr 	= "SLES Audio Player";
    5.79 +
    5.80 +#define	SLES_DEV_AUDIO_RECORDER	sldevaudiorecorderstr
    5.81 +#define	SLES_DEV_AUDIO_PLAYER	sldevaudioplayerstr
    5.82 +
    5.83 +#define NUM_BUFFERS 2           /* -- Don't lower this! */
    5.84 +
    5.85 +static	Uint8	*mixbuff = NULL;
    5.86 +static	int		next_buffer = 0;
    5.87 +static	Uint8	*pmixbuff[NUM_BUFFERS];
    5.88 +
    5.89 +static SDL_sem *playsem = NULL, *recsem = NULL;
    5.90 +
    5.91 +//static SDL_AudioDevice* audioDevice = NULL;
    5.92 +
    5.93 +#if 0
    5.94 +static void openslES_DetectDevices( int iscapture )
    5.95 +{
    5.96 +	LOGI( "openSLES_DetectDevices()" );
    5.97 +    if ( iscapture )
    5.98 +            addfn( SLES_DEV_AUDIO_RECORDER );
    5.99 +	else
   5.100 +            addfn( SLES_DEV_AUDIO_PLAYER );
   5.101 +	return;
   5.102 +}
   5.103 +#endif
   5.104 +
   5.105 +static void openslES_DestroyEngine( void );
   5.106 +
   5.107 +static int	openslES_CreateEngine( void )
   5.108 +{
   5.109 +	SLresult result;
   5.110 +
   5.111 +	LOGI( "openSLES_CreateEngine()" );
   5.112 +
   5.113 +	// create engine
   5.114 +	result = slCreateEngine( &engineObject, 0, NULL, 0, NULL, NULL );
   5.115 +	if ( SL_RESULT_SUCCESS != result ) {
   5.116 +
   5.117 +		LOGE( "slCreateEngine failed" );
   5.118 +		goto error;
   5.119 +	}
   5.120 +
   5.121 +	LOGI( "slCreateEngine OK" );
   5.122 +
   5.123 +    // realize the engine
   5.124 +    result = (*engineObject)->Realize( engineObject, SL_BOOLEAN_FALSE );
   5.125 +	if ( SL_RESULT_SUCCESS != result ) {
   5.126 +
   5.127 +		LOGE( "RealizeEngine failed" );
   5.128 +		goto error;
   5.129 +	}
   5.130 +
   5.131 +	LOGI( "RealizeEngine OK" );
   5.132 +
   5.133 +    // get the engine interface, which is needed in order to create other objects
   5.134 +    result = (*engineObject)->GetInterface( engineObject, SL_IID_ENGINE, &engineEngine );
   5.135 +	if ( SL_RESULT_SUCCESS != result ) {
   5.136 +
   5.137 +		LOGE( "EngineGetInterface failed" );
   5.138 +		goto error;
   5.139 +	}
   5.140 +
   5.141 +	LOGI( "EngineGetInterface OK" );
   5.142 +
   5.143 +    // create output mix, with environmental reverb specified as a non-required interface
   5.144 +//  const SLInterfaceID ids[1] = { SL_IID_ENVIRONMENTALREVERB };
   5.145 +//  const SLboolean req[1] = { SL_BOOLEAN_FALSE };
   5.146 +
   5.147 +  const SLInterfaceID ids[1] = { SL_IID_VOLUME };
   5.148 +  const SLboolean req[1] = { SL_BOOLEAN_FALSE };
   5.149 +  result = (*engineEngine)->CreateOutputMix( engineEngine, &outputMixObject, 1, ids, req );
   5.150 +
   5.151 +	if ( SL_RESULT_SUCCESS != result ) {
   5.152 +
   5.153 +		LOGE( "CreateOutputMix failed" );
   5.154 +		goto error;
   5.155 +	}
   5.156 +	LOGI( "CreateOutputMix OK" );
   5.157 +
   5.158 +  // realize the output mix
   5.159 +  result = (*outputMixObject)->Realize( outputMixObject, SL_BOOLEAN_FALSE );
   5.160 +	if ( SL_RESULT_SUCCESS != result ) {
   5.161 +
   5.162 +		LOGE( "RealizeOutputMix failed" );
   5.163 +		goto error;
   5.164 +	}
   5.165 +
   5.166 +	return 1;
   5.167 +
   5.168 +error:;
   5.169 +	openslES_DestroyEngine( );
   5.170 +	return 0;
   5.171 +}
   5.172 +
   5.173 +static	void	openslES_DestroyPCMPlayer( void );
   5.174 +static	void	openslES_DestroyPCMRecorder( void );
   5.175 +
   5.176 +static void openslES_DestroyEngine( void )
   5.177 +{
   5.178 +	LOGI( "openslES_DestroyEngine()" );
   5.179 +
   5.180 +	openslES_DestroyPCMPlayer( );
   5.181 +	openslES_DestroyPCMRecorder( );
   5.182 +
   5.183 +	// destroy output mix object, and invalidate all associated interfaces
   5.184 +	if ( outputMixObject != NULL ) {
   5.185 +
   5.186 +	    (*outputMixObject)->Destroy( outputMixObject );
   5.187 +	    outputMixObject = NULL;
   5.188 +//	    outputMixEnvironmentalReverb = NULL;
   5.189 +	}
   5.190 +
   5.191 +	// destroy engine object, and invalidate all associated interfaces
   5.192 +	if (engineObject != NULL) {
   5.193 +
   5.194 +	    (*engineObject)->Destroy( engineObject );
   5.195 +	    engineObject = NULL;
   5.196 +	    engineEngine = NULL;
   5.197 +	}
   5.198 +
   5.199 +	return;
   5.200 +}
   5.201 +
   5.202 +// this callback handler is called every time a buffer finishes playing
   5.203 +static void bqPlayerCallback( SLAndroidSimpleBufferQueueItf bq, void *context )
   5.204 +{
   5.205 +	static int	t = 0;
   5.206 +//    assert(bq == bqPlayerBufferQueue);
   5.207 +//    assert(NULL == context);
   5.208 +
   5.209 +    // for streaming playback, replace this test by logic to find and fill the next buffer
   5.210 +#if 0
   5.211 +	if (--nextCount > 0 && NULL != nextBuffer && 0 != nextSize) {
   5.212 +		SLresult result;
   5.213 +		// enqueue another buffer
   5.214 +		result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
   5.215 +		// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
   5.216 +		// which for this code example would indicate a programming error
   5.217 +		assert(SL_RESULT_SUCCESS == result);
   5.218 +		(void)result;
   5.219 +	}
   5.220 +#endif
   5.221 +
   5.222 +	LOGI( "SLES: Playback Callmeback %u", t++ );
   5.223 +
   5.224 +	SDL_SemPost( playsem );
   5.225 +
   5.226 +	return;
   5.227 +}
   5.228 +
   5.229 +static int openslES_CreatePCMRecorder( _THIS )
   5.230 +{
   5.231 +	LOGE( "openslES_CreatePCMRecorder not implimented yet!" );
   5.232 +	return SDL_SetError( "openslES_CreatePCMRecorder not implimented yet!" );
   5.233 +}
   5.234 +
   5.235 +static void openslES_DestroyPCMRecorder( void )
   5.236 +{
   5.237 +	return;
   5.238 +}
   5.239 +
   5.240 +static int openslES_CreatePCMPlayer( _THIS )
   5.241 +{
   5.242 +	SLDataFormat_PCM format_pcm;
   5.243 +  SDL_AudioFormat	test_format;
   5.244 +	SLresult result;
   5.245 +	int	i;
   5.246 +
   5.247 +/*
   5.248 +	test_format = SDL_FirstAudioFormat( this->spec.format );
   5.249 +
   5.250 +	while ( test_format != 0 ) {
   5.251 +
   5.252 +		if ( SDL_AUDIO_ISSIGNED(test_format) && SDL_AUDIO_ISINT(test_format ) ) break;
   5.253 +		test_format = SDL_NextAudioFormat( );
   5.254 +	}
   5.255 +
   5.256 +	if ( test_format == 0 ) {
   5.257 +
   5.258 +		// Didn't find a compatible format :( 
   5.259 +		LOGI( "No compatible audio format!" );
   5.260 +		return SDL_SetError("No compatible audio format!");
   5.261 +	}
   5.262 +
   5.263 +	this->spec.format = test_format;
   5.264 +*/
   5.265 +
   5.266 + // Update the fragment size as size in bytes 
   5.267 + SDL_CalculateAudioSpec( &this->spec );
   5.268 +
   5.269 +	LOGI( "Try to open %u hz %u bit chan %u %s samples %u", 
   5.270 +			this->spec.freq, SDL_AUDIO_BITSIZE( this->spec.format ), 
   5.271 +			this->spec.channels, (test_format&0x1000) ? "BE" : "LE", this->spec.samples 
   5.272 +		);
   5.273 +
   5.274 +	// configure audio source
   5.275 +	SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
   5.276 +//	SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, OPENSLES_BUFFERS };
   5.277 +
   5.278 +	format_pcm.formatType    = SL_DATAFORMAT_PCM;
   5.279 +	format_pcm.numChannels   = this->spec.channels;
   5.280 +	format_pcm.samplesPerSec = this->spec.freq * 1000;	/// kilo Hz to milli Hz
   5.281 +	format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE( this->spec.format );
   5.282 +	format_pcm.containerSize = SDL_AUDIO_BITSIZE( this->spec.format );
   5.283 +
   5.284 +	if ( SDL_AUDIO_ISBIGENDIAN( this->spec.format ) )
   5.285 +		format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
   5.286 +	else
   5.287 +		format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
   5.288 +
   5.289 +/*
   5.290 +#define SL_SPEAKER_FRONT_LEFT			((SLuint32) 0x00000001)
   5.291 +#define SL_SPEAKER_FRONT_RIGHT			((SLuint32) 0x00000002)
   5.292 +#define SL_SPEAKER_FRONT_CENTER			((SLuint32) 0x00000004)
   5.293 +#define SL_SPEAKER_LOW_FREQUENCY			((SLuint32) 0x00000008)
   5.294 +#define SL_SPEAKER_BACK_LEFT			((SLuint32) 0x00000010)
   5.295 +#define SL_SPEAKER_BACK_RIGHT			((SLuint32) 0x00000020)
   5.296 +#define SL_SPEAKER_FRONT_LEFT_OF_CENTER	((SLuint32) 0x00000040)
   5.297 +#define SL_SPEAKER_FRONT_RIGHT_OF_CENTER	((SLuint32) 0x00000080)
   5.298 +#define SL_SPEAKER_BACK_CENTER			((SLuint32) 0x00000100)
   5.299 +#define SL_SPEAKER_SIDE_LEFT			((SLuint32) 0x00000200)
   5.300 +#define SL_SPEAKER_SIDE_RIGHT			((SLuint32) 0x00000400)
   5.301 +#define SL_SPEAKER_TOP_CENTER			((SLuint32) 0x00000800)
   5.302 +#define SL_SPEAKER_TOP_FRONT_LEFT		((SLuint32) 0x00001000)
   5.303 +#define SL_SPEAKER_TOP_FRONT_CENTER		((SLuint32) 0x00002000)
   5.304 +#define SL_SPEAKER_TOP_FRONT_RIGHT		((SLuint32) 0x00004000)
   5.305 +#define SL_SPEAKER_TOP_BACK_LEFT			((SLuint32) 0x00008000)
   5.306 +#define SL_SPEAKER_TOP_BACK_CENTER		((SLuint32) 0x00010000)
   5.307 +#define SL_SPEAKER_TOP_BACK_RIGHT		((SLuint32) 0x00020000)
   5.308 +*/
   5.309 +
   5.310 +	if ( this->spec.channels == 1 )
   5.311 +		format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
   5.312 +	else if ( this->spec.channels == 2 )
   5.313 +		format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
   5.314 +	else if ( this->spec.channels == 3 )
   5.315 +		format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER;
   5.316 +	else if ( this->spec.channels == 4 )
   5.317 +		format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   5.318 +								 SL_SPEAKER_BACK_LEFT  | SL_SPEAKER_BACK_RIGHT;
   5.319 +	else
   5.320 +		format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   5.321 +								 SL_SPEAKER_BACK_LEFT  | SL_SPEAKER_BACK_RIGHT |
   5.322 +								 SL_SPEAKER_FRONT_CENTER;
   5.323 +
   5.324 +	SLDataSource audioSrc = { &loc_bufq, &format_pcm };
   5.325 +
   5.326 +	// configure audio sink
   5.327 +	SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
   5.328 +	SLDataSink audioSnk = { &loc_outmix, NULL };
   5.329 +
   5.330 +    // create audio player
   5.331 +    const SLInterfaceID ids[2] = { 
   5.332 +			SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
   5.333 +			SL_IID_VOLUME 
   5.334 +			};
   5.335 +
   5.336 +    const SLboolean req[2] = { 
   5.337 +			SL_BOOLEAN_TRUE, 
   5.338 +			SL_BOOLEAN_FALSE,
   5.339 +			};
   5.340 +
   5.341 +	result = (*engineEngine)->CreateAudioPlayer( engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
   5.342 +				2, ids, req );
   5.343 +	if ( SL_RESULT_SUCCESS != result ) {
   5.344 +
   5.345 +		LOGE( "CreateAudioPlayer failed" );
   5.346 +		goto failed;
   5.347 +	}
   5.348 +
   5.349 +    // realize the player
   5.350 +	result = (*bqPlayerObject)->Realize( bqPlayerObject, SL_BOOLEAN_FALSE );
   5.351 +	if ( SL_RESULT_SUCCESS != result ) {
   5.352 +
   5.353 +		LOGE( "RealizeAudioPlayer failed" );
   5.354 +		goto failed;
   5.355 +	}
   5.356 +
   5.357 +	// get the play interface
   5.358 +	result = (*bqPlayerObject)->GetInterface( bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay );
   5.359 +	if ( SL_RESULT_SUCCESS != result ) {
   5.360 +
   5.361 +		LOGE( "SL_IID_PLAY interface get failed" );
   5.362 +		goto failed;
   5.363 +	}
   5.364 +
   5.365 +    // get the buffer queue interface
   5.366 +	result = (*bqPlayerObject)->GetInterface( bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue );
   5.367 +	if ( SL_RESULT_SUCCESS != result ) {
   5.368 +
   5.369 +		LOGE( "SL_IID_BUFFERQUEUE interface get failed" );
   5.370 +		goto failed;
   5.371 +	}
   5.372 +
   5.373 +	// register callback on the buffer queue
   5.374 +	result = (*bqPlayerBufferQueue)->RegisterCallback( bqPlayerBufferQueue, bqPlayerCallback, NULL );
   5.375 +	if ( SL_RESULT_SUCCESS != result ) {
   5.376 +
   5.377 +		LOGE( "RegisterCallback failed" );
   5.378 +		goto failed;
   5.379 +	}
   5.380 +
   5.381 +#if 0
   5.382 +    // get the effect send interface
   5.383 +	result = (*bqPlayerObject)->GetInterface( bqPlayerObject, SL_IID_EFFECTSEND, &bqPlayerEffectSend );
   5.384 +	if ( SL_RESULT_SUCCESS != result ) {
   5.385 +
   5.386 +		LOGE( "SL_IID_EFFECTSEND interface get failed" );
   5.387 +		goto failed;
   5.388 +	}
   5.389 +#endif
   5.390 +
   5.391 +#if 0   // mute/solo is not supported for sources that are known to be mono, as this is
   5.392 +    // get the mute/solo interface
   5.393 +    result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo);
   5.394 +    assert(SL_RESULT_SUCCESS == result);
   5.395 +    (void)result;
   5.396 +#endif
   5.397 +
   5.398 +    // get the volume interface
   5.399 +	result = (*bqPlayerObject)->GetInterface( bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume );
   5.400 +	if ( SL_RESULT_SUCCESS != result ) {
   5.401 +
   5.402 +		LOGE( "SL_IID_VOLUME interface get failed" );
   5.403 +//		goto failed;
   5.404 +	}
   5.405 +
   5.406 +	// set the player's state to playing
   5.407 +	result = (*bqPlayerPlay)->SetPlayState( bqPlayerPlay, SL_PLAYSTATE_PLAYING );
   5.408 +	if ( SL_RESULT_SUCCESS != result ) {
   5.409 +
   5.410 +		LOGE( "Play set state failed" );
   5.411 +		goto failed;
   5.412 +	}
   5.413 +
   5.414 +    /* Create the audio buffer semaphore */
   5.415 +	playsem = SDL_CreateSemaphore( NUM_BUFFERS - 1 );
   5.416 +	if ( !playsem ) {
   5.417 +
   5.418 +		LOGE( "cannot create Semaphore!" );
   5.419 +		goto failed;
   5.420 +	}
   5.421 +
   5.422 +	/* Create the sound buffers */
   5.423 +	mixbuff = (Uint8 *) SDL_malloc( NUM_BUFFERS * this->spec.size );
   5.424 +	if ( mixbuff == NULL) {
   5.425 +
   5.426 +		LOGE( "mixbuffer allocate - out of memory" );
   5.427 +		goto failed;
   5.428 +	}
   5.429 +
   5.430 +	for ( i = 0; i < NUM_BUFFERS; i ++ )
   5.431 +		pmixbuff[i] = mixbuff + i * this->spec.size;
   5.432 +
   5.433 +    return 0;
   5.434 +
   5.435 +failed:;
   5.436 +
   5.437 +	openslES_DestroyPCMPlayer( );
   5.438 +
   5.439 +	return SDL_SetError( "Open device failed!" );
   5.440 +}
   5.441 +
   5.442 +static void openslES_DestroyPCMPlayer( void )
   5.443 +{
   5.444 +	// destroy buffer queue audio player object, and invalidate all associated interfaces
   5.445 +	if ( bqPlayerObject != NULL ) {
   5.446 +
   5.447 +        (*bqPlayerObject)->Destroy( bqPlayerObject );
   5.448 +
   5.449 +        bqPlayerObject		= NULL;
   5.450 +        bqPlayerPlay		= NULL;
   5.451 +        bqPlayerBufferQueue = NULL;
   5.452 +//        bqPlayerEffectSend	= NULL;
   5.453 +        bqPlayerMuteSolo	= NULL;
   5.454 +        bqPlayerVolume		= NULL;
   5.455 +    }
   5.456 +
   5.457 +	if ( playsem ) {
   5.458 +
   5.459 +		SDL_DestroySemaphore( playsem );
   5.460 +		playsem = NULL;
   5.461 +	}
   5.462 +
   5.463 +	if ( mixbuff )
   5.464 +		SDL_free( mixbuff );
   5.465 +
   5.466 +	return;
   5.467 +}
   5.468 +
   5.469 +static int openslES_OpenDevice( _THIS, void *handle, const char *devname, int iscapture )
   5.470 +{
   5.471 +	if ( iscapture ) {
   5.472 +		LOGI( "openslES_OpenDevice( ) %s for capture", devname );
   5.473 +		return openslES_CreatePCMRecorder( this );
   5.474 +	}
   5.475 +
   5.476 +	LOGI( "openslES_OpenDevice( ) %s for playing", devname );
   5.477 +
   5.478 +	return openslES_CreatePCMPlayer( this );
   5.479 +}
   5.480 +
   5.481 +static void openslES_CloseDevice( _THIS )
   5.482 +{
   5.483 +	if ( this->iscapture ) {
   5.484 +		LOGI( "openslES_CloseDevice( ) for capture" );
   5.485 +		return openslES_DestroyPCMRecorder( );
   5.486 +	}
   5.487 +
   5.488 +	LOGI( "openslES_CloseDevice( ) for playing" );
   5.489 +	openslES_DestroyPCMPlayer( );
   5.490 +
   5.491 +	return;
   5.492 +}
   5.493 +
   5.494 +static void openslES_WaitDevice( _THIS )
   5.495 +{
   5.496 +	LOGI( "openslES_WaitDevice( )" );
   5.497 +
   5.498 +    /* Wait for an audio chunk to finish */
   5.499 +//    WaitForSingleObject(this->hidden->audio_sem, INFINITE);
   5.500 +	SDL_SemWait( playsem );
   5.501 +
   5.502 +	return;
   5.503 +}
   5.504 +
   5.505 +///           n   playn sem
   5.506 +// getbuf     0   -     1
   5.507 +// fill buff  0   -     1
   5.508 +// play       0 - 0     1
   5.509 +// wait       1   0     0
   5.510 +// getbuf     1   0     0
   5.511 +// fill buff  1   0     0
   5.512 +// play       0   0     0
   5.513 +// wait       
   5.514 +//
   5.515 +// okay..
   5.516 +
   5.517 +
   5.518 +static Uint8 *openslES_GetDeviceBuf( _THIS )
   5.519 +{
   5.520 +	LOGI( "openslES_GetDeviceBuf( )" );
   5.521 +
   5.522 +    return pmixbuff[next_buffer];
   5.523 +}
   5.524 +
   5.525 +static void openslES_PlayDevice( _THIS )
   5.526 +{
   5.527 +	SLresult result;
   5.528 +
   5.529 +	LOGI( "======openslES_PlayDevice( )======" );
   5.530 +    /* Queue it up */
   5.531 +
   5.532 +	result = (*bqPlayerBufferQueue)->Enqueue( bqPlayerBufferQueue, pmixbuff[next_buffer], this->spec.size );
   5.533 +	if ( SL_RESULT_SUCCESS != result ) { 
   5.534 +		// just puk here
   5.535 +		// next !
   5.536 +	}
   5.537 +
   5.538 +	next_buffer ++;
   5.539 +	if ( next_buffer >= NUM_BUFFERS ) next_buffer = 0;
   5.540 +
   5.541 +	return;
   5.542 +}
   5.543 +
   5.544 +static int openslES_Init( SDL_AudioDriverImpl * impl )
   5.545 +{
   5.546 +	LOGI( "openslES_Init() called" );
   5.547 +
   5.548 +	if ( !openslES_CreateEngine() ) return 0;
   5.549 +
   5.550 +	LOGI( "openslES_Init() - set pointers" );
   5.551 +
   5.552 +	/* Set the function pointers */
   5.553 +//	impl->DetectDevices = openslES_DetectDevices;
   5.554 +	impl->OpenDevice    = openslES_OpenDevice;
   5.555 +   impl->PlayDevice	= openslES_PlayDevice;
   5.556 +   impl->GetDeviceBuf	= openslES_GetDeviceBuf;
   5.557 +	impl->Deinitialize  = openslES_DestroyEngine;
   5.558 +   impl->WaitDevice	= openslES_WaitDevice;
   5.559 +
   5.560 +	/* and the capabilities */
   5.561 +	impl->HasCaptureSupport = 0; /* TODO */
   5.562 +	impl->OnlyHasDefaultOutputDevice = 1;
   5.563 +//	impl->OnlyHasDefaultInputDevice  = 1;
   5.564 +
   5.565 +	LOGI( "openslES_Init() - succes" );
   5.566 +
   5.567 +	return 1;   /* this audio target is available. */
   5.568 +}
   5.569 +
   5.570 +AudioBootStrap openslES_bootstrap = {
   5.571 +	"openslES", "opensl ES audio driver", openslES_Init, 0
   5.572 +};
   5.573 +
   5.574 +#endif /* SDL_AUDIO_DRIVER_OPENSLES */
   5.575 +
   5.576 +/* vi: set ts=4 sw=4 expandtab: */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/audio/openslES/SDL_openslES.h	Sat Jan 12 12:18:44 2019 -0800
     6.3 @@ -0,0 +1,42 @@
     6.4 +/*
     6.5 +  Simple DirectMedia Layer
     6.6 +  Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
     6.7 +
     6.8 +  This software is provided 'as-is', without any express or implied
     6.9 +  warranty.  In no event will the authors be held liable for any damages
    6.10 +  arising from the use of this software.
    6.11 +
    6.12 +  Permission is granted to anyone to use this software for any purpose,
    6.13 +  including commercial applications, and to alter it and redistribute it
    6.14 +  freely, subject to the following restrictions:
    6.15 +
    6.16 +  1. The origin of this software must not be misrepresented; you must not
    6.17 +     claim that you wrote the original software. If you use this software
    6.18 +     in a product, an acknowledgment in the product documentation would be
    6.19 +     appreciated but is not required.
    6.20 +  2. Altered source versions must be plainly marked as such, and must not be
    6.21 +     misrepresented as being the original software.
    6.22 +  3. This notice may not be removed or altered from any source distribution.
    6.23 +*/
    6.24 +#include "../../SDL_internal.h"
    6.25 +
    6.26 +#ifndef _SDL_openslesaudio_h
    6.27 +#define _SDL_openslesaudio_h
    6.28 +
    6.29 +#include "../SDL_sysaudio.h"
    6.30 +
    6.31 +/* Hidden "this" pointer for the audio functions */
    6.32 +#define _THIS   SDL_AudioDevice *this
    6.33 +
    6.34 +struct SDL_PrivateAudioData
    6.35 +{
    6.36 +    /* The file descriptor for the audio device */
    6.37 +    Uint8 *mixbuf;
    6.38 +    Uint32 mixlen;
    6.39 +    Uint32 write_delay;
    6.40 +    Uint32 initial_calls;
    6.41 +};
    6.42 +
    6.43 +#endif /* _SDL_openslesaudio_h */
    6.44 +
    6.45 +/* vi: set ts=4 sw=4 expandtab: */