3 Android OpenSL input/output module
4 Copyright (c) 2012, Victor Lazzarini
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 * Neither the name of the <organization> nor the
15 names of its contributors may be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "rdpsnd_main.h"
33 #include "opensl_io.h"
34 #define CONV16BIT 32768
35 #define CONVMYFLT (1./32768.)
37 static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context);
39 // creates the OpenSL ES audio engine
40 static SLresult openSLCreateEngine(OPENSL_STREAM *p)
44 result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
45 DEBUG_SND("engineObject=%p", p->engineObject);
46 if(result != SL_RESULT_SUCCESS) goto engine_end;
49 result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
50 DEBUG_SND("Realize=%d", result);
51 if(result != SL_RESULT_SUCCESS) goto engine_end;
53 // get the engine interface, which is needed in order to create other objects
54 result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine));
55 DEBUG_SND("engineEngine=%p", p->engineEngine);
56 if(result != SL_RESULT_SUCCESS) goto engine_end;
62 // opens the OpenSL ES device for output
63 static SLresult openSLPlayOpen(OPENSL_STREAM *p)
67 SLuint32 channels = p->outchannels;
69 assert(p->engineObject);
70 assert(p->engineEngine);
73 // configure audio source
74 SLDataLocator_AndroidSimpleBufferQueue loc_bufq =
76 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
83 sr = SL_SAMPLINGRATE_8;
86 sr = SL_SAMPLINGRATE_11_025;
89 sr = SL_SAMPLINGRATE_16;
92 sr = SL_SAMPLINGRATE_22_05;
95 sr = SL_SAMPLINGRATE_24;
98 sr = SL_SAMPLINGRATE_32;
101 sr = SL_SAMPLINGRATE_44_1;
104 sr = SL_SAMPLINGRATE_48;
107 sr = SL_SAMPLINGRATE_64;
110 sr = SL_SAMPLINGRATE_88_2;
113 sr = SL_SAMPLINGRATE_96;
116 sr = SL_SAMPLINGRATE_192;
122 const SLInterfaceID ids[] = {SL_IID_VOLUME};
123 const SLboolean req[] = {SL_BOOLEAN_FALSE};
124 result = (*p->engineEngine)->CreateOutputMix(p->engineEngine, &(p->outputMixObject), 1, ids, req);
125 DEBUG_SND("engineEngine=%p", p->engineEngine);
127 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
129 // realize the output mix
130 result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE);
131 DEBUG_SND("Realize=%d", result);
133 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
137 speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
138 else speakers = SL_SPEAKER_FRONT_CENTER;
139 SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,channels, sr,
140 SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
141 speakers, SL_BYTEORDER_LITTLEENDIAN};
143 SLDataSource audioSrc = {&loc_bufq, &format_pcm};
145 // configure audio sink
146 SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject};
147 SLDataSink audioSnk = {&loc_outmix, NULL};
149 // create audio player
150 const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME};
151 const SLboolean req1[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
152 result = (*p->engineEngine)->CreateAudioPlayer(p->engineEngine,
153 &(p->bqPlayerObject), &audioSrc, &audioSnk, 2, ids1, req1);
154 DEBUG_SND("bqPlayerObject=%p", p->bqPlayerObject);
156 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
158 // realize the player
159 result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE);
160 DEBUG_SND("Realize=%d", result);
162 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
164 // get the play interface
165 result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY, &(p->bqPlayerPlay));
166 DEBUG_SND("bqPlayerPlay=%p", p->bqPlayerPlay);
168 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
170 // get the volume interface
171 result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_VOLUME, &(p->bqPlayerVolume));
172 DEBUG_SND("bqPlayerVolume=%p", p->bqPlayerVolume);
174 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
176 // get the buffer queue interface
177 result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
178 &(p->bqPlayerBufferQueue));
179 DEBUG_SND("bqPlayerBufferQueue=%p", p->bqPlayerBufferQueue);
181 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
183 // register callback on the buffer queue
184 result = (*p->bqPlayerBufferQueue)->RegisterCallback(p->bqPlayerBufferQueue, bqPlayerCallback, p);
185 DEBUG_SND("bqPlayerCallback=%p", p->bqPlayerCallback);
187 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
189 // set the player's state to playing
190 result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay, SL_PLAYSTATE_PLAYING);
191 DEBUG_SND("SetPlayState=%d", result);
198 return SL_RESULT_SUCCESS;
201 // close the OpenSL IO and destroy the audio engine
202 static void openSLDestroyEngine(OPENSL_STREAM *p){
204 // destroy buffer queue audio player object, and invalidate all associated interfaces
205 if (p->bqPlayerObject != NULL) {
206 (*p->bqPlayerObject)->Destroy(p->bqPlayerObject);
207 p->bqPlayerObject = NULL;
208 p->bqPlayerVolume = NULL;
209 p->bqPlayerPlay = NULL;
210 p->bqPlayerBufferQueue = NULL;
211 p->bqPlayerEffectSend = NULL;
214 // destroy output mix object, and invalidate all associated interfaces
215 if (p->outputMixObject != NULL) {
216 (*p->outputMixObject)->Destroy(p->outputMixObject);
217 p->outputMixObject = NULL;
220 // destroy engine object, and invalidate all associated interfaces
221 if (p->engineObject != NULL) {
222 (*p->engineObject)->Destroy(p->engineObject);
223 p->engineObject = NULL;
224 p->engineEngine = NULL;
230 // open the android audio device for and/or output
231 OPENSL_STREAM *android_OpenAudioDevice(int sr, int outchannels, int bufferframes){
233 p = (OPENSL_STREAM *) calloc(sizeof(OPENSL_STREAM), 1);
237 p->queuesize = bufferframes;
238 p->outchannels = outchannels;
241 if(openSLCreateEngine(p) != SL_RESULT_SUCCESS)
243 android_CloseAudioDevice(p);
247 if(openSLPlayOpen(p) != SL_RESULT_SUCCESS)
249 android_CloseAudioDevice(p);
253 p->queue = Queue_New(TRUE, -1, -1);
256 android_CloseAudioDevice(p);
263 // close the android audio device
264 void android_CloseAudioDevice(OPENSL_STREAM *p){
269 openSLDestroyEngine(p);
271 Queue_Free(p->queue);
276 // this callback handler is called every time a buffer finishes playing
277 void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
279 OPENSL_STREAM *p = (OPENSL_STREAM *) context;
284 void *data = Queue_Dequeue(p->queue);
288 // puts a buffer of size samples to the device
289 int android_AudioOut(OPENSL_STREAM *p, const short *buffer,int size)
295 /* Assure, that the queue is not full. */
296 if (p->queuesize <= Queue_Count(p->queue) && WaitForSingleObject(p->queue->event, INFINITE) == WAIT_FAILED)
298 DEBUG_SND("WaitForSingleObject failed!");
302 void *data = calloc(size, sizeof(short));
305 DEBUG_SND("unable to allocate a buffer");
308 memcpy(data, buffer, size * sizeof(short));
309 Queue_Enqueue(p->queue, data);
310 (*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue,
311 data, sizeof(short) * size);
316 int android_GetOutputMute(OPENSL_STREAM *p) {
320 assert(p->bqPlayerVolume);
322 SLresult rc = (*p->bqPlayerVolume)->GetMute(p->bqPlayerVolume, &mute);
323 assert(SL_RESULT_SUCCESS == rc);
328 void android_SetOutputMute(OPENSL_STREAM *p, BOOL _mute) {
329 SLboolean mute = _mute;
332 assert(p->bqPlayerVolume);
334 SLresult rc = (*p->bqPlayerVolume)->SetMute(p->bqPlayerVolume, mute);
335 assert(SL_RESULT_SUCCESS == rc);
338 int android_GetOutputVolume(OPENSL_STREAM *p){
342 assert(p->bqPlayerVolume);
344 SLresult rc = (*p->bqPlayerVolume)->GetVolumeLevel(p->bqPlayerVolume, &level);
345 assert(SL_RESULT_SUCCESS == rc);
350 int android_GetOutputVolumeMax(OPENSL_STREAM *p){
354 assert(p->bqPlayerVolume);
356 SLresult rc = (*p->bqPlayerVolume)->GetMaxVolumeLevel(p->bqPlayerVolume, &level);
357 assert(SL_RESULT_SUCCESS == rc);
363 void android_SetOutputVolume(OPENSL_STREAM *p, int level){
364 SLresult rc = (*p->bqPlayerVolume)->SetVolumeLevel(p->bqPlayerVolume, level);
365 assert(SL_RESULT_SUCCESS == rc);