LADI JACK2: Switch to 2.minor versioning scheme
[jackdbus.git] / android / opensl_io.c
blob38b6ec0ceea52dafbf8ad65c21c35e3697ffde67
1 /*
2 opensl_io.c:
3 Android OpenSL input/output module
4 Copyright (c) 2012, Victor Lazzarini
5 All rights reserved.
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.
30 #include "opensl_io.h"
31 //#define CONV16BIT 32768
32 //#define CONVMYFLT (1./32768.)
33 #define CONV16BIT 32640
34 #define CONVMYFLT (1./32640.)
36 static void* createThreadLock(void);
37 static int waitThreadLock(void *lock);
38 static void notifyThreadLock(void *lock);
39 static void destroyThreadLock(void *lock);
40 static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context);
41 static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context);
43 // creates the OpenSL ES audio engine
44 static SLresult openSLCreateEngine(OPENSL_STREAM *p)
46 SLresult result;
47 // create engine
48 result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
49 if(result != SL_RESULT_SUCCESS) goto engine_end;
51 // realize the engine
52 result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
53 if(result != SL_RESULT_SUCCESS) goto engine_end;
55 // get the engine interface, which is needed in order to create other objects
56 result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine));
57 if(result != SL_RESULT_SUCCESS) goto engine_end;
59 engine_end:
60 return result;
63 // opens the OpenSL ES device for output
64 static SLresult openSLPlayOpen(OPENSL_STREAM *p)
66 SLresult result;
67 SLuint32 sr = p->sr;
68 SLuint32 channels = p->outchannels;
70 if(channels){
71 // configure audio source
72 SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
74 switch(sr){
76 case 8000:
77 sr = SL_SAMPLINGRATE_8;
78 break;
79 case 11025:
80 sr = SL_SAMPLINGRATE_11_025;
81 break;
82 case 16000:
83 sr = SL_SAMPLINGRATE_16;
84 break;
85 case 22050:
86 sr = SL_SAMPLINGRATE_22_05;
87 break;
88 case 24000:
89 sr = SL_SAMPLINGRATE_24;
90 break;
91 case 32000:
92 sr = SL_SAMPLINGRATE_32;
93 break;
94 case 44100:
95 sr = SL_SAMPLINGRATE_44_1;
96 break;
97 case 48000:
98 sr = SL_SAMPLINGRATE_48;
99 break;
100 case 64000:
101 sr = SL_SAMPLINGRATE_64;
102 break;
103 case 88200:
104 sr = SL_SAMPLINGRATE_88_2;
105 break;
106 case 96000:
107 sr = SL_SAMPLINGRATE_96;
108 break;
109 case 192000:
110 sr = SL_SAMPLINGRATE_192;
111 break;
112 default:
113 return -1;
116 const SLInterfaceID ids[] = {SL_IID_VOLUME};
117 const SLboolean req[] = {SL_BOOLEAN_FALSE};
118 result = (*p->engineEngine)->CreateOutputMix(p->engineEngine, &(p->outputMixObject), 1, ids, req);
119 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
121 // realize the output mix
122 result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE);
124 int speakers;
125 if(channels > 1)
126 speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
127 else speakers = SL_SPEAKER_FRONT_CENTER;
128 SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,channels, sr,
129 SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
130 speakers, SL_BYTEORDER_LITTLEENDIAN};
132 SLDataSource audioSrc = {&loc_bufq, &format_pcm};
134 // configure audio sink
135 SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject};
136 SLDataSink audioSnk = {&loc_outmix, NULL};
138 // create audio player
139 const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
140 const SLboolean req1[] = {SL_BOOLEAN_TRUE};
141 result = (*p->engineEngine)->CreateAudioPlayer(p->engineEngine, &(p->bqPlayerObject), &audioSrc, &audioSnk,
142 1, ids1, req1);
143 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
145 // realize the player
146 result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE);
147 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
149 // get the play interface
150 result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY, &(p->bqPlayerPlay));
151 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
153 // get the buffer queue interface
154 result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
155 &(p->bqPlayerBufferQueue));
156 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
158 // register callback on the buffer queue
159 result = (*p->bqPlayerBufferQueue)->RegisterCallback(p->bqPlayerBufferQueue, bqPlayerCallback, p);
160 if(result != SL_RESULT_SUCCESS) goto end_openaudio;
162 // set the player's state to playing
163 result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay, SL_PLAYSTATE_PLAYING);
165 end_openaudio:
166 return result;
168 return SL_RESULT_SUCCESS;
171 // Open the OpenSL ES device for input
172 static SLresult openSLRecOpen(OPENSL_STREAM *p){
174 SLresult result;
175 SLuint32 sr = p->sr;
176 SLuint32 channels = p->inchannels;
178 if(channels){
180 switch(sr){
182 case 8000:
183 sr = SL_SAMPLINGRATE_8;
184 break;
185 case 11025:
186 sr = SL_SAMPLINGRATE_11_025;
187 break;
188 case 16000:
189 sr = SL_SAMPLINGRATE_16;
190 break;
191 case 22050:
192 sr = SL_SAMPLINGRATE_22_05;
193 break;
194 case 24000:
195 sr = SL_SAMPLINGRATE_24;
196 break;
197 case 32000:
198 sr = SL_SAMPLINGRATE_32;
199 break;
200 case 44100:
201 sr = SL_SAMPLINGRATE_44_1;
202 break;
203 case 48000:
204 sr = SL_SAMPLINGRATE_48;
205 break;
206 case 64000:
207 sr = SL_SAMPLINGRATE_64;
208 break;
209 case 88200:
210 sr = SL_SAMPLINGRATE_88_2;
211 break;
212 case 96000:
213 sr = SL_SAMPLINGRATE_96;
214 break;
215 case 192000:
216 sr = SL_SAMPLINGRATE_192;
217 break;
218 default:
219 return -1;
222 // configure audio source
223 SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
224 SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
225 SLDataSource audioSrc = {&loc_dev, NULL};
227 // configure audio sink
228 int speakers;
229 if(channels > 1)
230 speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
231 else speakers = SL_SPEAKER_FRONT_CENTER;
232 SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
233 SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, channels, sr,
234 SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
235 speakers, SL_BYTEORDER_LITTLEENDIAN};
236 SLDataSink audioSnk = {&loc_bq, &format_pcm};
238 // create audio recorder
239 // (requires the RECORD_AUDIO permission)
240 const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
241 const SLboolean req[1] = {SL_BOOLEAN_TRUE};
242 result = (*p->engineEngine)->CreateAudioRecorder(p->engineEngine, &(p->recorderObject), &audioSrc,
243 &audioSnk, 1, id, req);
244 if (SL_RESULT_SUCCESS != result) goto end_recopen;
246 // realize the audio recorder
247 result = (*p->recorderObject)->Realize(p->recorderObject, SL_BOOLEAN_FALSE);
248 if (SL_RESULT_SUCCESS != result) goto end_recopen;
250 // get the record interface
251 result = (*p->recorderObject)->GetInterface(p->recorderObject, SL_IID_RECORD, &(p->recorderRecord));
252 if (SL_RESULT_SUCCESS != result) goto end_recopen;
254 // get the buffer queue interface
255 result = (*p->recorderObject)->GetInterface(p->recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
256 &(p->recorderBufferQueue));
257 if (SL_RESULT_SUCCESS != result) goto end_recopen;
259 // register callback on the buffer queue
260 result = (*p->recorderBufferQueue)->RegisterCallback(p->recorderBufferQueue, bqRecorderCallback,
262 if (SL_RESULT_SUCCESS != result) goto end_recopen;
263 result = (*p->recorderRecord)->SetRecordState(p->recorderRecord, SL_RECORDSTATE_RECORDING);
265 end_recopen:
266 return result;
268 else return SL_RESULT_SUCCESS;
273 // close the OpenSL IO and destroy the audio engine
274 static void openSLDestroyEngine(OPENSL_STREAM *p){
276 // destroy buffer queue audio player object, and invalidate all associated interfaces
277 if (p->bqPlayerObject != NULL) {
278 (*p->bqPlayerObject)->Destroy(p->bqPlayerObject);
279 p->bqPlayerObject = NULL;
280 p->bqPlayerPlay = NULL;
281 p->bqPlayerBufferQueue = NULL;
282 p->bqPlayerEffectSend = NULL;
285 // destroy audio recorder object, and invalidate all associated interfaces
286 if (p->recorderObject != NULL) {
287 (*p->recorderObject)->Destroy(p->recorderObject);
288 p->recorderObject = NULL;
289 p->recorderRecord = NULL;
290 p->recorderBufferQueue = NULL;
293 // destroy output mix object, and invalidate all associated interfaces
294 if (p->outputMixObject != NULL) {
295 (*p->outputMixObject)->Destroy(p->outputMixObject);
296 p->outputMixObject = NULL;
299 // destroy engine object, and invalidate all associated interfaces
300 if (p->engineObject != NULL) {
301 (*p->engineObject)->Destroy(p->engineObject);
302 p->engineObject = NULL;
303 p->engineEngine = NULL;
309 // open the android audio device for input and/or output
310 OPENSL_STREAM *android_OpenAudioDevice(int sr, int inchannels, int outchannels, int bufferframes){
312 OPENSL_STREAM *p;
313 p = (OPENSL_STREAM *) calloc(sizeof(OPENSL_STREAM),1);
315 p->inchannels = inchannels;
316 p->outchannels = outchannels;
317 p->sr = sr;
318 p->inlock = createThreadLock();
319 p->outlock = createThreadLock();
321 if((p->outBufSamples = bufferframes*outchannels) != 0) {
322 if((p->outputBuffer[0] = (short *) calloc(p->outBufSamples, sizeof(short))) == NULL ||
323 (p->outputBuffer[1] = (short *) calloc(p->outBufSamples, sizeof(short))) == NULL) {
324 android_CloseAudioDevice(p);
325 return NULL;
329 if((p->inBufSamples = bufferframes*inchannels) != 0){
330 if((p->inputBuffer[0] = (short *) calloc(p->inBufSamples, sizeof(short))) == NULL ||
331 (p->inputBuffer[1] = (short *) calloc(p->inBufSamples, sizeof(short))) == NULL){
332 android_CloseAudioDevice(p);
333 return NULL;
337 p->currentInputIndex = 0;
338 p->currentOutputBuffer = 0;
339 p->currentInputIndex = p->inBufSamples;
340 p->currentInputBuffer = 0;
342 if(openSLCreateEngine(p) != SL_RESULT_SUCCESS) {
343 android_CloseAudioDevice(p);
344 return NULL;
347 if(openSLRecOpen(p) != SL_RESULT_SUCCESS) {
348 android_CloseAudioDevice(p);
349 return NULL;
352 if(openSLPlayOpen(p) != SL_RESULT_SUCCESS) {
353 android_CloseAudioDevice(p);
354 return NULL;
357 notifyThreadLock(p->outlock);
358 notifyThreadLock(p->inlock);
360 p->time = 0.;
361 return p;
364 // close the android audio device
365 void android_CloseAudioDevice(OPENSL_STREAM *p){
367 if (p == NULL)
368 return;
370 openSLDestroyEngine(p);
372 if (p->inlock != NULL) {
373 notifyThreadLock(p->inlock);
374 destroyThreadLock(p->inlock);
375 p->inlock = NULL;
378 if (p->outlock != NULL) {
379 notifyThreadLock(p->outlock);
380 destroyThreadLock(p->outlock);
381 p->inlock = NULL;
384 if (p->outputBuffer[0] != NULL) {
385 free(p->outputBuffer[0]);
386 p->outputBuffer[0] = NULL;
389 if (p->outputBuffer[1] != NULL) {
390 free(p->outputBuffer[1]);
391 p->outputBuffer[1] = NULL;
394 if (p->inputBuffer[0] != NULL) {
395 free(p->inputBuffer[0]);
396 p->inputBuffer[0] = NULL;
399 if (p->inputBuffer[1] != NULL) {
400 free(p->inputBuffer[1]);
401 p->inputBuffer[1] = NULL;
404 free(p);
407 // returns timestamp of the processed stream
408 double android_GetTimestamp(OPENSL_STREAM *p){
409 return p->time;
413 // this callback handler is called every time a buffer finishes recording
414 void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
416 OPENSL_STREAM *p = (OPENSL_STREAM *) context;
417 notifyThreadLock(p->inlock);
420 // gets a buffer of size samples from the device
421 int android_AudioIn(OPENSL_STREAM *p,float *buffer,int size){
422 short *inBuffer;
423 int i, bufsamps, index;
424 if(p == NULL) return 0;
425 bufsamps = p->inBufSamples;
426 if(bufsamps == 0) return 0;
427 index = p->currentInputIndex;
429 inBuffer = p->inputBuffer[p->currentInputBuffer];
430 for(i=0; i < size; i++){
431 if (index >= bufsamps) {
432 waitThreadLock(p->inlock);
433 (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue,
434 inBuffer,bufsamps*sizeof(short));
435 p->currentInputBuffer = (p->currentInputBuffer ? 0 : 1);
436 index = 0;
437 inBuffer = p->inputBuffer[p->currentInputBuffer];
439 buffer[i] = (float) inBuffer[index++]*CONVMYFLT;
441 p->currentInputIndex = index;
442 if(p->outchannels == 0) p->time += (double) size/(p->sr*p->inchannels);
443 return i;
446 // this callback handler is called every time a buffer finishes playing
447 void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
449 OPENSL_STREAM *p = (OPENSL_STREAM *) context;
450 notifyThreadLock(p->outlock);
453 // puts a buffer of size samples to the device
454 int android_AudioOut(OPENSL_STREAM *p, float *buffer,int size){
456 short *outBuffer;
457 int i, bufsamps, index;
458 if(p == NULL) return 0;
459 bufsamps = p->outBufSamples;
460 if(bufsamps == 0) return 0;
461 index = p->currentOutputIndex;
462 outBuffer = p->outputBuffer[p->currentOutputBuffer];
464 for(i=0; i < size; i++){
465 outBuffer[index++] = (short) (buffer[i]*CONV16BIT);
466 if (index >= p->outBufSamples) {
467 waitThreadLock(p->outlock);
468 (*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue,
469 outBuffer,bufsamps*sizeof(short));
470 p->currentOutputBuffer = (p->currentOutputBuffer ? 0 : 1);
471 index = 0;
472 outBuffer = p->outputBuffer[p->currentOutputBuffer];
475 p->currentOutputIndex = index;
476 p->time += (double) size/(p->sr*p->outchannels);
477 return i;
480 //----------------------------------------------------------------------
481 // thread Locks
482 // to ensure synchronisation between callbacks and processing code
483 void* createThreadLock(void)
485 threadLock *p;
486 p = (threadLock*) malloc(sizeof(threadLock));
487 if (p == NULL)
488 return NULL;
489 memset(p, 0, sizeof(threadLock));
490 if (pthread_mutex_init(&(p->m), (pthread_mutexattr_t*) NULL) != 0) {
491 free((void*) p);
492 return NULL;
494 if (pthread_cond_init(&(p->c), (pthread_condattr_t*) NULL) != 0) {
495 pthread_mutex_destroy(&(p->m));
496 free((void*) p);
497 return NULL;
499 p->s = (unsigned char) 1;
501 return p;
504 int waitThreadLock(void *lock)
506 threadLock *p;
507 int retval = 0;
508 p = (threadLock*) lock;
509 pthread_mutex_lock(&(p->m));
510 while (!p->s) {
511 pthread_cond_wait(&(p->c), &(p->m));
513 p->s = (unsigned char) 0;
514 pthread_mutex_unlock(&(p->m));
515 return NULL;
518 void notifyThreadLock(void *lock)
520 threadLock *p;
521 p = (threadLock*) lock;
522 pthread_mutex_lock(&(p->m));
523 p->s = (unsigned char) 1;
524 pthread_cond_signal(&(p->c));
525 pthread_mutex_unlock(&(p->m));
526 return;
529 void destroyThreadLock(void *lock)
531 threadLock *p;
532 p = (threadLock*) lock;
533 if (p == NULL)
534 return;
535 notifyThreadLock(p);
536 pthread_cond_destroy(&(p->c));
537 pthread_mutex_destroy(&(p->m));
538 free(p);