2 * Copyright (C) 2011 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 /* This is an OpenAL backend for Android using the native audio APIs based on
18 * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app
30 #include <SLES/OpenSLES.h>
31 #include <SLES/OpenSLES_Android.h>
34 #define VCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
35 #define VCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
39 /* engine interfaces */
40 SLObjectItf engineObject
;
43 /* output mix interfaces */
44 SLObjectItf outputMix
;
46 /* buffer queue player interfaces */
47 SLObjectItf bufferQueueObject
;
57 static const ALCchar opensl_device
[] = "OpenSL";
60 static SLuint32
GetChannelMask(enum DevFmtChannels chans
)
64 case DevFmtMono
: return SL_SPEAKER_FRONT_CENTER
;
65 case DevFmtStereo
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
;
66 case DevFmtQuad
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
|
67 SL_SPEAKER_BACK_LEFT
|SL_SPEAKER_BACK_RIGHT
;
68 case DevFmtX51
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
|
69 SL_SPEAKER_FRONT_CENTER
|SL_SPEAKER_LOW_FREQUENCY
|
70 SL_SPEAKER_SIDE_LEFT
|SL_SPEAKER_SIDE_RIGHT
;
71 case DevFmtX51Rear
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
|
72 SL_SPEAKER_FRONT_CENTER
|SL_SPEAKER_LOW_FREQUENCY
|
73 SL_SPEAKER_BACK_LEFT
|SL_SPEAKER_BACK_RIGHT
;
74 case DevFmtX61
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
|
75 SL_SPEAKER_FRONT_CENTER
|SL_SPEAKER_LOW_FREQUENCY
|
76 SL_SPEAKER_BACK_CENTER
|
77 SL_SPEAKER_SIDE_LEFT
|SL_SPEAKER_SIDE_RIGHT
;
78 case DevFmtX71
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
|
79 SL_SPEAKER_FRONT_CENTER
|SL_SPEAKER_LOW_FREQUENCY
|
80 SL_SPEAKER_BACK_LEFT
|SL_SPEAKER_BACK_RIGHT
|
81 SL_SPEAKER_SIDE_LEFT
|SL_SPEAKER_SIDE_RIGHT
;
82 case DevFmtBFormat3D
: break;
87 static const char *res_str(SLresult result
)
91 case SL_RESULT_SUCCESS
: return "Success";
92 case SL_RESULT_PRECONDITIONS_VIOLATED
: return "Preconditions violated";
93 case SL_RESULT_PARAMETER_INVALID
: return "Parameter invalid";
94 case SL_RESULT_MEMORY_FAILURE
: return "Memory failure";
95 case SL_RESULT_RESOURCE_ERROR
: return "Resource error";
96 case SL_RESULT_RESOURCE_LOST
: return "Resource lost";
97 case SL_RESULT_IO_ERROR
: return "I/O error";
98 case SL_RESULT_BUFFER_INSUFFICIENT
: return "Buffer insufficient";
99 case SL_RESULT_CONTENT_CORRUPTED
: return "Content corrupted";
100 case SL_RESULT_CONTENT_UNSUPPORTED
: return "Content unsupported";
101 case SL_RESULT_CONTENT_NOT_FOUND
: return "Content not found";
102 case SL_RESULT_PERMISSION_DENIED
: return "Permission denied";
103 case SL_RESULT_FEATURE_UNSUPPORTED
: return "Feature unsupported";
104 case SL_RESULT_INTERNAL_ERROR
: return "Internal error";
105 case SL_RESULT_UNKNOWN_ERROR
: return "Unknown error";
106 case SL_RESULT_OPERATION_ABORTED
: return "Operation aborted";
107 case SL_RESULT_CONTROL_LOST
: return "Control lost";
108 #ifdef SL_RESULT_READONLY
109 case SL_RESULT_READONLY
: return "ReadOnly";
111 #ifdef SL_RESULT_ENGINEOPTION_UNSUPPORTED
112 case SL_RESULT_ENGINEOPTION_UNSUPPORTED
: return "Engine option unsupported";
114 #ifdef SL_RESULT_SOURCE_SINK_INCOMPATIBLE
115 case SL_RESULT_SOURCE_SINK_INCOMPATIBLE
: return "Source/Sink incompatible";
118 return "Unknown error code";
121 #define PRINTERR(x, s) do { \
122 if((x) != SL_RESULT_SUCCESS) \
123 ERR("%s: %s\n", (s), res_str((x))); \
126 /* this callback handler is called every time a buffer finishes playing */
127 static void opensl_callback(SLAndroidSimpleBufferQueueItf bq
, void *context
)
129 ALCdevice
*Device
= context
;
130 osl_data
*data
= Device
->ExtraData
;
134 buf
= (ALbyte
*)data
->buffer
+ data
->curBuffer
*data
->bufferSize
;
135 aluMixData(Device
, buf
, data
->bufferSize
/data
->frameSize
);
137 result
= VCALL(bq
,Enqueue
)(buf
, data
->bufferSize
);
138 PRINTERR(result
, "bq->Enqueue");
140 data
->curBuffer
= (data
->curBuffer
+1) % Device
->NumUpdates
;
144 static ALCenum
opensl_open_playback(ALCdevice
*Device
, const ALCchar
*deviceName
)
146 osl_data
*data
= NULL
;
150 deviceName
= opensl_device
;
151 else if(strcmp(deviceName
, opensl_device
) != 0)
152 return ALC_INVALID_VALUE
;
154 data
= calloc(1, sizeof(*data
));
156 return ALC_OUT_OF_MEMORY
;
159 result
= slCreateEngine(&data
->engineObject
, 0, NULL
, 0, NULL
, NULL
);
160 PRINTERR(result
, "slCreateEngine");
161 if(SL_RESULT_SUCCESS
== result
)
163 result
= VCALL(data
->engineObject
,Realize
)(SL_BOOLEAN_FALSE
);
164 PRINTERR(result
, "engine->Realize");
166 if(SL_RESULT_SUCCESS
== result
)
168 result
= VCALL(data
->engineObject
,GetInterface
)(SL_IID_ENGINE
, &data
->engine
);
169 PRINTERR(result
, "engine->GetInterface");
171 if(SL_RESULT_SUCCESS
== result
)
173 result
= VCALL(data
->engine
,CreateOutputMix
)(&data
->outputMix
, 0, NULL
, NULL
);
174 PRINTERR(result
, "engine->CreateOutputMix");
176 if(SL_RESULT_SUCCESS
== result
)
178 result
= VCALL(data
->outputMix
,Realize
)(SL_BOOLEAN_FALSE
);
179 PRINTERR(result
, "outputMix->Realize");
182 if(SL_RESULT_SUCCESS
!= result
)
184 if(data
->outputMix
!= NULL
)
185 VCALL0(data
->outputMix
,Destroy
)();
186 data
->outputMix
= NULL
;
188 if(data
->engineObject
!= NULL
)
189 VCALL0(data
->engineObject
,Destroy
)();
190 data
->engineObject
= NULL
;
194 return ALC_INVALID_VALUE
;
197 al_string_copy_cstr(&Device
->DeviceName
, deviceName
);
198 Device
->ExtraData
= data
;
204 static void opensl_close_playback(ALCdevice
*Device
)
206 osl_data
*data
= Device
->ExtraData
;
208 if(data
->bufferQueueObject
!= NULL
)
209 VCALL0(data
->bufferQueueObject
,Destroy
)();
210 data
->bufferQueueObject
= NULL
;
212 VCALL0(data
->outputMix
,Destroy
)();
213 data
->outputMix
= NULL
;
215 VCALL0(data
->engineObject
,Destroy
)();
216 data
->engineObject
= NULL
;
220 Device
->ExtraData
= NULL
;
223 static ALCboolean
opensl_reset_playback(ALCdevice
*Device
)
225 osl_data
*data
= Device
->ExtraData
;
226 SLDataLocator_AndroidSimpleBufferQueue loc_bufq
;
227 SLDataLocator_OutputMix loc_outmix
;
228 SLDataFormat_PCM format_pcm
;
229 SLDataSource audioSrc
;
236 Device
->UpdateSize
= (ALuint64
)Device
->UpdateSize
* 44100 / Device
->Frequency
;
237 Device
->UpdateSize
= Device
->UpdateSize
* Device
->NumUpdates
/ 2;
238 Device
->NumUpdates
= 2;
240 Device
->Frequency
= 44100;
241 Device
->FmtChans
= DevFmtStereo
;
242 Device
->FmtType
= DevFmtShort
;
244 SetDefaultWFXChannelOrder(Device
);
247 id
= SL_IID_ANDROIDSIMPLEBUFFERQUEUE
;
248 req
= SL_BOOLEAN_TRUE
;
250 loc_bufq
.locatorType
= SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
;
251 loc_bufq
.numBuffers
= Device
->NumUpdates
;
253 format_pcm
.formatType
= SL_DATAFORMAT_PCM
;
254 format_pcm
.numChannels
= ChannelsFromDevFmt(Device
->FmtChans
);
255 format_pcm
.samplesPerSec
= Device
->Frequency
* 1000;
256 format_pcm
.bitsPerSample
= BytesFromDevFmt(Device
->FmtType
) * 8;
257 format_pcm
.containerSize
= format_pcm
.bitsPerSample
;
258 format_pcm
.channelMask
= GetChannelMask(Device
->FmtChans
);
259 format_pcm
.endianness
= IS_LITTLE_ENDIAN
? SL_BYTEORDER_LITTLEENDIAN
:
260 SL_BYTEORDER_BIGENDIAN
;
262 audioSrc
.pLocator
= &loc_bufq
;
263 audioSrc
.pFormat
= &format_pcm
;
265 loc_outmix
.locatorType
= SL_DATALOCATOR_OUTPUTMIX
;
266 loc_outmix
.outputMix
= data
->outputMix
;
267 audioSnk
.pLocator
= &loc_outmix
;
268 audioSnk
.pFormat
= NULL
;
271 if(data
->bufferQueueObject
!= NULL
)
272 VCALL0(data
->bufferQueueObject
,Destroy
)();
273 data
->bufferQueueObject
= NULL
;
275 result
= VCALL(data
->engine
,CreateAudioPlayer
)(&data
->bufferQueueObject
, &audioSrc
, &audioSnk
, 1, &id
, &req
);
276 PRINTERR(result
, "engine->CreateAudioPlayer");
277 if(SL_RESULT_SUCCESS
== result
)
279 result
= VCALL(data
->bufferQueueObject
,Realize
)(SL_BOOLEAN_FALSE
);
280 PRINTERR(result
, "bufferQueue->Realize");
283 if(SL_RESULT_SUCCESS
!= result
)
285 if(data
->bufferQueueObject
!= NULL
)
286 VCALL0(data
->bufferQueueObject
,Destroy
)();
287 data
->bufferQueueObject
= NULL
;
295 static ALCboolean
opensl_start_playback(ALCdevice
*Device
)
297 osl_data
*data
= Device
->ExtraData
;
298 SLAndroidSimpleBufferQueueItf bufferQueue
;
303 result
= VCALL(data
->bufferQueueObject
,GetInterface
)(SL_IID_BUFFERQUEUE
, &bufferQueue
);
304 PRINTERR(result
, "bufferQueue->GetInterface");
305 if(SL_RESULT_SUCCESS
== result
)
307 result
= VCALL(bufferQueue
,RegisterCallback
)(opensl_callback
, Device
);
308 PRINTERR(result
, "bufferQueue->RegisterCallback");
310 if(SL_RESULT_SUCCESS
== result
)
312 data
->frameSize
= FrameSizeFromDevFmt(Device
->FmtChans
, Device
->FmtType
);
313 data
->bufferSize
= Device
->UpdateSize
* data
->frameSize
;
314 data
->buffer
= calloc(Device
->NumUpdates
, data
->bufferSize
);
317 result
= SL_RESULT_MEMORY_FAILURE
;
318 PRINTERR(result
, "calloc");
321 /* enqueue the first buffer to kick off the callbacks */
322 for(i
= 0;i
< Device
->NumUpdates
;i
++)
324 if(SL_RESULT_SUCCESS
== result
)
326 ALvoid
*buf
= (ALbyte
*)data
->buffer
+ i
*data
->bufferSize
;
327 result
= VCALL(bufferQueue
,Enqueue
)(buf
, data
->bufferSize
);
328 PRINTERR(result
, "bufferQueue->Enqueue");
332 if(SL_RESULT_SUCCESS
== result
)
334 result
= VCALL(data
->bufferQueueObject
,GetInterface
)(SL_IID_PLAY
, &player
);
335 PRINTERR(result
, "bufferQueue->GetInterface");
337 if(SL_RESULT_SUCCESS
== result
)
339 result
= VCALL(player
,SetPlayState
)(SL_PLAYSTATE_PLAYING
);
340 PRINTERR(result
, "player->SetPlayState");
343 if(SL_RESULT_SUCCESS
!= result
)
345 if(data
->bufferQueueObject
!= NULL
)
346 VCALL0(data
->bufferQueueObject
,Destroy
)();
347 data
->bufferQueueObject
= NULL
;
351 data
->bufferSize
= 0;
360 static void opensl_stop_playback(ALCdevice
*Device
)
362 osl_data
*data
= Device
->ExtraData
;
364 SLAndroidSimpleBufferQueueItf bufferQueue
;
367 result
= VCALL(data
->bufferQueueObject
,GetInterface
)(SL_IID_PLAY
, &player
);
368 PRINTERR(result
, "bufferQueue->GetInterface");
369 if(SL_RESULT_SUCCESS
== result
)
371 result
= VCALL(player
,SetPlayState
)(SL_PLAYSTATE_STOPPED
);
372 PRINTERR(result
, "player->SetPlayState");
375 result
= VCALL(data
->bufferQueueObject
,GetInterface
)(SL_IID_BUFFERQUEUE
, &bufferQueue
);
376 PRINTERR(result
, "bufferQueue->GetInterface");
377 if(SL_RESULT_SUCCESS
== result
)
379 result
= VCALL0(bufferQueue
,Clear
)();
380 PRINTERR(result
, "bufferQueue->Clear");
382 if(SL_RESULT_SUCCESS
== result
)
384 SLAndroidSimpleBufferQueueState state
;
387 result
= VCALL(bufferQueue
,GetState
)(&state
);
388 } while(SL_RESULT_SUCCESS
== result
&& state
.count
> 0);
389 PRINTERR(result
, "bufferQueue->GetState");
394 data
->bufferSize
= 0;
398 static const BackendFuncs opensl_funcs
= {
399 opensl_open_playback
,
400 opensl_close_playback
,
401 opensl_reset_playback
,
402 opensl_start_playback
,
403 opensl_stop_playback
,
413 ALCboolean
alc_opensl_init(BackendFuncs
*func_list
)
415 *func_list
= opensl_funcs
;
419 void alc_opensl_deinit(void)
423 void alc_opensl_probe(enum DevProbe type
)
427 case ALL_DEVICE_PROBE
:
428 AppendAllDevicesList(opensl_device
);
430 case CAPTURE_DEVICE_PROBE
: