FreeRDP
audin/client/opensles/opensl_io.c
1 /*
2 opensl_io.c:
3 Android OpenSL input/output module
4 Copyright (c) 2012, Victor Lazzarini
5 All rights reserved.
6 
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.
17 
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.
28 */
29 
30 #include <winpr/assert.h>
31 
32 #include "audin_main.h"
33 #include "opensl_io.h"
34 #define CONV16BIT 32768
35 #define CONVMYFLT (1. / 32768.)
36 
37 typedef struct
38 {
39  size_t size;
40  void* data;
41 } queue_element;
42 
43 struct opensl_stream
44 {
45  // engine interfaces
46  SLObjectItf engineObject;
47  SLEngineItf engineEngine;
48 
49  // device interfaces
50  SLDeviceVolumeItf deviceVolume;
51 
52  // recorder interfaces
53  SLObjectItf recorderObject;
54  SLRecordItf recorderRecord;
55  SLAndroidSimpleBufferQueueItf recorderBufferQueue;
56 
57  unsigned int inchannels;
58  unsigned int sr;
59  unsigned int buffersize;
60  unsigned int bits_per_sample;
61 
62  queue_element* prep;
63  queue_element* next;
64 
65  void* context;
66  opensl_receive_t receive;
67 };
68 
69 static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
70 
71 // creates the OpenSL ES audio engine
72 static SLresult openSLCreateEngine(OPENSL_STREAM* p)
73 {
74  SLresult result;
75  // create engine
76  result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
77 
78  if (result != SL_RESULT_SUCCESS)
79  goto engine_end;
80 
81  // realize the engine
82  result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
83 
84  if (result != SL_RESULT_SUCCESS)
85  goto engine_end;
86 
87  // get the engine interface, which is needed in order to create other objects
88  result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine));
89 
90  if (result != SL_RESULT_SUCCESS)
91  goto engine_end;
92 
93  // get the volume interface - important, this is optional!
94  result =
95  (*p->engineObject)->GetInterface(p->engineObject, SL_IID_DEVICEVOLUME, &(p->deviceVolume));
96 
97  if (result != SL_RESULT_SUCCESS)
98  {
99  p->deviceVolume = NULL;
100  result = SL_RESULT_SUCCESS;
101  }
102 
103 engine_end:
104  WINPR_ASSERT(SL_RESULT_SUCCESS == result);
105  return result;
106 }
107 
108 // Open the OpenSL ES device for input
109 static SLresult openSLRecOpen(OPENSL_STREAM* p)
110 {
111  SLresult result;
112  SLuint32 sr = p->sr;
113  SLuint32 channels = p->inchannels;
114  WINPR_ASSERT(!p->recorderObject);
115 
116  if (channels)
117  {
118  switch (sr)
119  {
120  case 8000:
121  sr = SL_SAMPLINGRATE_8;
122  break;
123 
124  case 11025:
125  sr = SL_SAMPLINGRATE_11_025;
126  break;
127 
128  case 16000:
129  sr = SL_SAMPLINGRATE_16;
130  break;
131 
132  case 22050:
133  sr = SL_SAMPLINGRATE_22_05;
134  break;
135 
136  case 24000:
137  sr = SL_SAMPLINGRATE_24;
138  break;
139 
140  case 32000:
141  sr = SL_SAMPLINGRATE_32;
142  break;
143 
144  case 44100:
145  sr = SL_SAMPLINGRATE_44_1;
146  break;
147 
148  case 48000:
149  sr = SL_SAMPLINGRATE_48;
150  break;
151 
152  case 64000:
153  sr = SL_SAMPLINGRATE_64;
154  break;
155 
156  case 88200:
157  sr = SL_SAMPLINGRATE_88_2;
158  break;
159 
160  case 96000:
161  sr = SL_SAMPLINGRATE_96;
162  break;
163 
164  case 192000:
165  sr = SL_SAMPLINGRATE_192;
166  break;
167 
168  default:
169  return -1;
170  }
171 
172  // configure audio source
173  SLDataLocator_IODevice loc_dev = { SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
174  SL_DEFAULTDEVICEID_AUDIOINPUT, NULL };
175  SLDataSource audioSrc = { &loc_dev, NULL };
176  // configure audio sink
177  int speakers;
178 
179  if (channels > 1)
180  speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
181  else
182  speakers = SL_SPEAKER_FRONT_CENTER;
183 
184  SLDataLocator_AndroidSimpleBufferQueue loc_bq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
185  2 };
186  SLDataFormat_PCM format_pcm;
187  format_pcm.formatType = SL_DATAFORMAT_PCM;
188  format_pcm.numChannels = channels;
189  format_pcm.samplesPerSec = sr;
190  format_pcm.channelMask = speakers;
191  format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
192 
193  if (16 == p->bits_per_sample)
194  {
195  format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
196  format_pcm.containerSize = 16;
197  }
198  else if (8 == p->bits_per_sample)
199  {
200  format_pcm.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_8;
201  format_pcm.containerSize = 8;
202  }
203  else
204  WINPR_ASSERT(0);
205 
206  SLDataSink audioSnk = { &loc_bq, &format_pcm };
207  // create audio recorder
208  // (requires the RECORD_AUDIO permission)
209  const SLInterfaceID id[] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE };
210  const SLboolean req[] = { SL_BOOLEAN_TRUE };
211  result = (*p->engineEngine)
212  ->CreateAudioRecorder(p->engineEngine, &(p->recorderObject), &audioSrc,
213  &audioSnk, 1, id, req);
214  WINPR_ASSERT(!result);
215 
216  if (SL_RESULT_SUCCESS != result)
217  goto end_recopen;
218 
219  // realize the audio recorder
220  result = (*p->recorderObject)->Realize(p->recorderObject, SL_BOOLEAN_FALSE);
221  WINPR_ASSERT(!result);
222 
223  if (SL_RESULT_SUCCESS != result)
224  goto end_recopen;
225 
226  // get the record interface
227  result = (*p->recorderObject)
228  ->GetInterface(p->recorderObject, SL_IID_RECORD, &(p->recorderRecord));
229  WINPR_ASSERT(!result);
230 
231  if (SL_RESULT_SUCCESS != result)
232  goto end_recopen;
233 
234  // get the buffer queue interface
235  result = (*p->recorderObject)
236  ->GetInterface(p->recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
237  &(p->recorderBufferQueue));
238  WINPR_ASSERT(!result);
239 
240  if (SL_RESULT_SUCCESS != result)
241  goto end_recopen;
242 
243  // register callback on the buffer queue
244  result = (*p->recorderBufferQueue)
245  ->RegisterCallback(p->recorderBufferQueue, bqRecorderCallback, p);
246  WINPR_ASSERT(!result);
247 
248  if (SL_RESULT_SUCCESS != result)
249  goto end_recopen;
250 
251  end_recopen:
252  return result;
253  }
254  else
255  return SL_RESULT_SUCCESS;
256 }
257 
258 // close the OpenSL IO and destroy the audio engine
259 static void openSLDestroyEngine(OPENSL_STREAM* p)
260 {
261  // destroy audio recorder object, and invalidate all associated interfaces
262  if (p->recorderObject != NULL)
263  {
264  (*p->recorderObject)->Destroy(p->recorderObject);
265  p->recorderObject = NULL;
266  p->recorderRecord = NULL;
267  p->recorderBufferQueue = NULL;
268  }
269 
270  // destroy engine object, and invalidate all associated interfaces
271  if (p->engineObject != NULL)
272  {
273  (*p->engineObject)->Destroy(p->engineObject);
274  p->engineObject = NULL;
275  p->engineEngine = NULL;
276  }
277 }
278 
279 static queue_element* opensles_queue_element_new(size_t size)
280 {
281  queue_element* q = calloc(1, sizeof(queue_element));
282 
283  if (!q)
284  goto fail;
285 
286  q->size = size;
287  q->data = malloc(size);
288 
289  if (!q->data)
290  goto fail;
291 
292  return q;
293 fail:
294  free(q);
295  return NULL;
296 }
297 
298 static void opensles_queue_element_free(void* obj)
299 {
300  queue_element* e = (queue_element*)obj;
301 
302  if (e)
303  free(e->data);
304 
305  free(e);
306 }
307 
308 // open the android audio device for input
309 OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, int sr,
310  int inchannels, int bufferframes, int bits_per_sample)
311 {
312  OPENSL_STREAM* p;
313 
314  if (!context || !receive)
315  return NULL;
316 
317  p = (OPENSL_STREAM*)calloc(1, sizeof(OPENSL_STREAM));
318 
319  if (!p)
320  return NULL;
321 
322  p->context = context;
323  p->receive = receive;
324  p->inchannels = inchannels;
325  p->sr = sr;
326  p->buffersize = bufferframes;
327  p->bits_per_sample = bits_per_sample;
328 
329  if ((p->bits_per_sample != 8) && (p->bits_per_sample != 16))
330  goto fail;
331 
332  if (openSLCreateEngine(p) != SL_RESULT_SUCCESS)
333  goto fail;
334 
335  if (openSLRecOpen(p) != SL_RESULT_SUCCESS)
336  goto fail;
337 
338  /* Create receive buffers, prepare them and start recording */
339  p->prep = opensles_queue_element_new(p->buffersize * p->bits_per_sample / 8);
340  p->next = opensles_queue_element_new(p->buffersize * p->bits_per_sample / 8);
341 
342  if (!p->prep || !p->next)
343  goto fail;
344 
345  (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, p->next->data, p->next->size);
346  (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, p->prep->data, p->prep->size);
347  (*p->recorderRecord)->SetRecordState(p->recorderRecord, SL_RECORDSTATE_RECORDING);
348  return p;
349 fail:
350  android_CloseRecDevice(p);
351  return NULL;
352 }
353 
354 // close the android audio device
355 void android_CloseRecDevice(OPENSL_STREAM* p)
356 {
357  if (p == NULL)
358  return;
359 
360  opensles_queue_element_free(p->next);
361  opensles_queue_element_free(p->prep);
362  openSLDestroyEngine(p);
363  free(p);
364 }
365 
366 // this callback handler is called every time a buffer finishes recording
367 static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
368 {
369  OPENSL_STREAM* p = (OPENSL_STREAM*)context;
370  queue_element* e;
371 
372  if (!p)
373  return;
374 
375  e = p->next;
376 
377  if (!e)
378  return;
379 
380  if (!p->context || !p->receive)
381  WLog_WARN(TAG, "Missing receive callback=%p, context=%p", p->receive, p->context);
382  else
383  p->receive(p->context, e->data, e->size);
384 
385  p->next = p->prep;
386  p->prep = e;
387  (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, e->data, e->size);
388 }