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_BACK_LEFT
|SL_SPEAKER_BACK_RIGHT
;
71 case DevFmtX61
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
|
72 SL_SPEAKER_FRONT_CENTER
|SL_SPEAKER_LOW_FREQUENCY
|
73 SL_SPEAKER_BACK_CENTER
|
74 SL_SPEAKER_SIDE_LEFT
|SL_SPEAKER_SIDE_RIGHT
;
75 case DevFmtX71
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
|
76 SL_SPEAKER_FRONT_CENTER
|SL_SPEAKER_LOW_FREQUENCY
|
77 SL_SPEAKER_BACK_LEFT
|SL_SPEAKER_BACK_RIGHT
|
78 SL_SPEAKER_SIDE_LEFT
|SL_SPEAKER_SIDE_RIGHT
;
79 case DevFmtX51Side
: return SL_SPEAKER_FRONT_LEFT
|SL_SPEAKER_FRONT_RIGHT
|
80 SL_SPEAKER_FRONT_CENTER
|SL_SPEAKER_LOW_FREQUENCY
|
81 SL_SPEAKER_SIDE_LEFT
|SL_SPEAKER_SIDE_RIGHT
;
86 static const char *res_str(SLresult result
)
90 case SL_RESULT_SUCCESS
: return "Success";
91 case SL_RESULT_PRECONDITIONS_VIOLATED
: return "Preconditions violated";
92 case SL_RESULT_PARAMETER_INVALID
: return "Parameter invalid";
93 case SL_RESULT_MEMORY_FAILURE
: return "Memory failure";
94 case SL_RESULT_RESOURCE_ERROR
: return "Resource error";
95 case SL_RESULT_RESOURCE_LOST
: return "Resource lost";
96 case SL_RESULT_IO_ERROR
: return "I/O error";
97 case SL_RESULT_BUFFER_INSUFFICIENT
: return "Buffer insufficient";
98 case SL_RESULT_CONTENT_CORRUPTED
: return "Content corrupted";
99 case SL_RESULT_CONTENT_UNSUPPORTED
: return "Content unsupported";
100 case SL_RESULT_CONTENT_NOT_FOUND
: return "Content not found";
101 case SL_RESULT_PERMISSION_DENIED
: return "Permission denied";
102 case SL_RESULT_FEATURE_UNSUPPORTED
: return "Feature unsupported";
103 case SL_RESULT_INTERNAL_ERROR
: return "Internal error";
104 case SL_RESULT_UNKNOWN_ERROR
: return "Unknown error";
105 case SL_RESULT_OPERATION_ABORTED
: return "Operation aborted";
106 case SL_RESULT_CONTROL_LOST
: return "Control lost";
107 #ifdef SL_RESULT_READONLY
108 case SL_RESULT_READONLY
: return "ReadOnly";
110 #ifdef SL_RESULT_ENGINEOPTION_UNSUPPORTED
111 case SL_RESULT_ENGINEOPTION_UNSUPPORTED
: return "Engine option unsupported";
113 #ifdef SL_RESULT_SOURCE_SINK_INCOMPATIBLE
114 case SL_RESULT_SOURCE_SINK_INCOMPATIBLE
: return "Source/Sink incompatible";
117 return "Unknown error code";
120 #define PRINTERR(x, s) do { \
121 if((x) != SL_RESULT_SUCCESS) \
122 ERR("%s: %s\n", (s), res_str((x))); \
125 /* this callback handler is called every time a buffer finishes playing */
126 static void opensl_callback(SLAndroidSimpleBufferQueueItf bq
, void *context
)
128 ALCdevice
*Device
= context
;
129 osl_data
*data
= Device
->ExtraData
;
133 buf
= (ALbyte
*)data
->buffer
+ data
->curBuffer
*data
->bufferSize
;
134 aluMixData(Device
, buf
, data
->bufferSize
/data
->frameSize
);
136 result
= VCALL(bq
,Enqueue
)(buf
, data
->bufferSize
);
137 PRINTERR(result
, "bq->Enqueue");
139 data
->curBuffer
= (data
->curBuffer
+1) % Device
->NumUpdates
;
143 static ALCenum
opensl_open_playback(ALCdevice
*Device
, const ALCchar
*deviceName
)
145 osl_data
*data
= NULL
;
149 deviceName
= opensl_device
;
150 else if(strcmp(deviceName
, opensl_device
) != 0)
151 return ALC_INVALID_VALUE
;
153 data
= calloc(1, sizeof(*data
));
155 return ALC_OUT_OF_MEMORY
;
158 result
= slCreateEngine(&data
->engineObject
, 0, NULL
, 0, NULL
, NULL
);
159 PRINTERR(result
, "slCreateEngine");
160 if(SL_RESULT_SUCCESS
== result
)
162 result
= VCALL(data
->engineObject
,Realize
)(SL_BOOLEAN_FALSE
);
163 PRINTERR(result
, "engine->Realize");
165 if(SL_RESULT_SUCCESS
== result
)
167 result
= VCALL(data
->engineObject
,GetInterface
)(SL_IID_ENGINE
, &data
->engine
);
168 PRINTERR(result
, "engine->GetInterface");
170 if(SL_RESULT_SUCCESS
== result
)
172 result
= VCALL(data
->engine
,CreateOutputMix
)(&data
->outputMix
, 0, NULL
, NULL
);
173 PRINTERR(result
, "engine->CreateOutputMix");
175 if(SL_RESULT_SUCCESS
== result
)
177 result
= VCALL(data
->outputMix
,Realize
)(SL_BOOLEAN_FALSE
);
178 PRINTERR(result
, "outputMix->Realize");
181 if(SL_RESULT_SUCCESS
!= result
)
183 if(data
->outputMix
!= NULL
)
184 VCALL0(data
->outputMix
,Destroy
)();
185 data
->outputMix
= NULL
;
187 if(data
->engineObject
!= NULL
)
188 VCALL0(data
->engineObject
,Destroy
)();
189 data
->engineObject
= NULL
;
193 return ALC_INVALID_VALUE
;
196 al_string_copy_cstr(&Device
->DeviceName
, deviceName
);
197 Device
->ExtraData
= data
;
203 static void opensl_close_playback(ALCdevice
*Device
)
205 osl_data
*data
= Device
->ExtraData
;
207 if(data
->bufferQueueObject
!= NULL
)
208 VCALL0(data
->bufferQueueObject
,Destroy
)();
209 data
->bufferQueueObject
= NULL
;
211 VCALL0(data
->outputMix
,Destroy
)();
212 data
->outputMix
= NULL
;
214 VCALL0(data
->engineObject
,Destroy
)();
215 data
->engineObject
= NULL
;
219 Device
->ExtraData
= NULL
;
222 static ALCboolean
opensl_reset_playback(ALCdevice
*Device
)
224 osl_data
*data
= Device
->ExtraData
;
225 SLDataLocator_AndroidSimpleBufferQueue loc_bufq
;
226 SLDataLocator_OutputMix loc_outmix
;
227 SLDataFormat_PCM format_pcm
;
228 SLDataSource audioSrc
;
235 Device
->UpdateSize
= (ALuint64
)Device
->UpdateSize
* 44100 / Device
->Frequency
;
236 Device
->UpdateSize
= Device
->UpdateSize
* Device
->NumUpdates
/ 2;
237 Device
->NumUpdates
= 2;
239 Device
->Frequency
= 44100;
240 Device
->FmtChans
= DevFmtStereo
;
241 Device
->FmtType
= DevFmtShort
;
243 SetDefaultWFXChannelOrder(Device
);
246 id
= SL_IID_ANDROIDSIMPLEBUFFERQUEUE
;
247 req
= SL_BOOLEAN_TRUE
;
249 loc_bufq
.locatorType
= SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
;
250 loc_bufq
.numBuffers
= Device
->NumUpdates
;
252 format_pcm
.formatType
= SL_DATAFORMAT_PCM
;
253 format_pcm
.numChannels
= ChannelsFromDevFmt(Device
->FmtChans
);
254 format_pcm
.samplesPerSec
= Device
->Frequency
* 1000;
255 format_pcm
.bitsPerSample
= BytesFromDevFmt(Device
->FmtType
) * 8;
256 format_pcm
.containerSize
= format_pcm
.bitsPerSample
;
257 format_pcm
.channelMask
= GetChannelMask(Device
->FmtChans
);
258 format_pcm
.endianness
= IS_LITTLE_ENDIAN
? SL_BYTEORDER_LITTLEENDIAN
:
259 SL_BYTEORDER_BIGENDIAN
;
261 audioSrc
.pLocator
= &loc_bufq
;
262 audioSrc
.pFormat
= &format_pcm
;
264 loc_outmix
.locatorType
= SL_DATALOCATOR_OUTPUTMIX
;
265 loc_outmix
.outputMix
= data
->outputMix
;
266 audioSnk
.pLocator
= &loc_outmix
;
267 audioSnk
.pFormat
= NULL
;
270 if(data
->bufferQueueObject
!= NULL
)
271 VCALL0(data
->bufferQueueObject
,Destroy
)();
272 data
->bufferQueueObject
= NULL
;
274 result
= VCALL(data
->engine
,CreateAudioPlayer
)(&data
->bufferQueueObject
, &audioSrc
, &audioSnk
, 1, &id
, &req
);
275 PRINTERR(result
, "engine->CreateAudioPlayer");
276 if(SL_RESULT_SUCCESS
== result
)
278 result
= VCALL(data
->bufferQueueObject
,Realize
)(SL_BOOLEAN_FALSE
);
279 PRINTERR(result
, "bufferQueue->Realize");
282 if(SL_RESULT_SUCCESS
!= result
)
284 if(data
->bufferQueueObject
!= NULL
)
285 VCALL0(data
->bufferQueueObject
,Destroy
)();
286 data
->bufferQueueObject
= NULL
;
294 static ALCboolean
opensl_start_playback(ALCdevice
*Device
)
296 osl_data
*data
= Device
->ExtraData
;
297 SLAndroidSimpleBufferQueueItf bufferQueue
;
302 result
= VCALL(data
->bufferQueueObject
,GetInterface
)(SL_IID_BUFFERQUEUE
, &bufferQueue
);
303 PRINTERR(result
, "bufferQueue->GetInterface");
304 if(SL_RESULT_SUCCESS
== result
)
306 result
= VCALL(bufferQueue
,RegisterCallback
)(opensl_callback
, Device
);
307 PRINTERR(result
, "bufferQueue->RegisterCallback");
309 if(SL_RESULT_SUCCESS
== result
)
311 data
->frameSize
= FrameSizeFromDevFmt(Device
->FmtChans
, Device
->FmtType
);
312 data
->bufferSize
= Device
->UpdateSize
* data
->frameSize
;
313 data
->buffer
= calloc(Device
->NumUpdates
, data
->bufferSize
);
316 result
= SL_RESULT_MEMORY_FAILURE
;
317 PRINTERR(result
, "calloc");
320 /* enqueue the first buffer to kick off the callbacks */
321 for(i
= 0;i
< Device
->NumUpdates
;i
++)
323 if(SL_RESULT_SUCCESS
== result
)
325 ALvoid
*buf
= (ALbyte
*)data
->buffer
+ i
*data
->bufferSize
;
326 result
= VCALL(bufferQueue
,Enqueue
)(buf
, data
->bufferSize
);
327 PRINTERR(result
, "bufferQueue->Enqueue");
331 if(SL_RESULT_SUCCESS
== result
)
333 result
= VCALL(data
->bufferQueueObject
,GetInterface
)(SL_IID_PLAY
, &player
);
334 PRINTERR(result
, "bufferQueue->GetInterface");
336 if(SL_RESULT_SUCCESS
== result
)
338 result
= VCALL(player
,SetPlayState
)(SL_PLAYSTATE_PLAYING
);
339 PRINTERR(result
, "player->SetPlayState");
342 if(SL_RESULT_SUCCESS
!= result
)
344 if(data
->bufferQueueObject
!= NULL
)
345 VCALL0(data
->bufferQueueObject
,Destroy
)();
346 data
->bufferQueueObject
= NULL
;
350 data
->bufferSize
= 0;
359 static void opensl_stop_playback(ALCdevice
*Device
)
361 osl_data
*data
= Device
->ExtraData
;
363 SLAndroidSimpleBufferQueueItf bufferQueue
;
366 result
= VCALL(data
->bufferQueueObject
,GetInterface
)(SL_IID_PLAY
, &player
);
367 PRINTERR(result
, "bufferQueue->GetInterface");
368 if(SL_RESULT_SUCCESS
== result
)
370 result
= VCALL(player
,SetPlayState
)(SL_PLAYSTATE_STOPPED
);
371 PRINTERR(result
, "player->SetPlayState");
374 result
= VCALL(data
->bufferQueueObject
,GetInterface
)(SL_IID_BUFFERQUEUE
, &bufferQueue
);
375 PRINTERR(result
, "bufferQueue->GetInterface");
376 if(SL_RESULT_SUCCESS
== result
)
378 result
= VCALL0(bufferQueue
,Clear
)();
379 PRINTERR(result
, "bufferQueue->Clear");
384 data
->bufferSize
= 0;
388 static const BackendFuncs opensl_funcs
= {
389 opensl_open_playback
,
390 opensl_close_playback
,
391 opensl_reset_playback
,
392 opensl_start_playback
,
393 opensl_stop_playback
,
400 ALCdevice_GetLatencyDefault
404 ALCboolean
alc_opensl_init(BackendFuncs
*func_list
)
406 *func_list
= opensl_funcs
;
410 void alc_opensl_deinit(void)
414 void alc_opensl_probe(enum DevProbe type
)
418 case ALL_DEVICE_PROBE
:
419 AppendAllDevicesList(opensl_device
);
421 case CAPTURE_DEVICE_PROBE
: