Mercurial > audio-send
view Alc/backends/opensl.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
line wrap: on
line source
1 /*2 * Copyright (C) 2011 The Android Open Source Project3 *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 at7 *8 * http://www.apache.org/licenses/LICENSE-2.09 *10 * Unless required by applicable law or agreed to in writing, software11 * 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 and14 * limitations under the License.15 */17 /* This is an OpenAL backend for Android using the native audio APIs based on18 * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app19 * bundled with NDK.20 */22 #include "config.h"24 #include <stdlib.h>25 #include "alMain.h"26 #include "AL/al.h"27 #include "AL/alc.h"30 #include <SLES/OpenSLES.h>31 #if 132 #include <SLES/OpenSLES_Android.h>33 #else34 extern SLAPIENTRY const SLInterfaceID SL_IID_ANDROIDSIMPLEBUFFERQUEUE;36 struct SLAndroidSimpleBufferQueueItf_;37 typedef const struct SLAndroidSimpleBufferQueueItf_ * const * SLAndroidSimpleBufferQueueItf;39 typedef void (*slAndroidSimpleBufferQueueCallback)(SLAndroidSimpleBufferQueueItf caller, void *pContext);41 typedef struct SLAndroidSimpleBufferQueueState_ {42 SLuint32 count;43 SLuint32 index;44 } SLAndroidSimpleBufferQueueState;47 struct SLAndroidSimpleBufferQueueItf_ {48 SLresult (*Enqueue) (49 SLAndroidSimpleBufferQueueItf self,50 const void *pBuffer,51 SLuint32 size52 );53 SLresult (*Clear) (54 SLAndroidSimpleBufferQueueItf self55 );56 SLresult (*GetState) (57 SLAndroidSimpleBufferQueueItf self,58 SLAndroidSimpleBufferQueueState *pState59 );60 SLresult (*RegisterCallback) (61 SLAndroidSimpleBufferQueueItf self,62 slAndroidSimpleBufferQueueCallback callback,63 void* pContext64 );65 };67 #define SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE ((SLuint32) 0x800007BD)69 typedef struct SLDataLocator_AndroidSimpleBufferQueue {70 SLuint32 locatorType;71 SLuint32 numBuffers;72 } SLDataLocator_AndroidSimpleBufferQueue;74 #endif76 /* Helper macros */77 #define SLObjectItf_Realize(a,b) ((*(a))->Realize((a),(b)))78 #define SLObjectItf_GetInterface(a,b,c) ((*(a))->GetInterface((a),(b),(c)))79 #define SLObjectItf_Destroy(a) ((*(a))->Destroy((a)))81 #define SLEngineItf_CreateOutputMix(a,b,c,d,e) ((*(a))->CreateOutputMix((a),(b),(c),(d),(e)))82 #define SLEngineItf_CreateAudioPlayer(a,b,c,d,e,f,g) ((*(a))->CreateAudioPlayer((a),(b),(c),(d),(e),(f),(g)))84 #define SLPlayItf_SetPlayState(a,b) ((*(a))->SetPlayState((a),(b)))87 typedef struct {88 /* engine interfaces */89 SLObjectItf engineObject;90 SLEngineItf engine;92 /* output mix interfaces */93 SLObjectItf outputMix;95 /* buffer queue player interfaces */96 SLObjectItf bufferQueueObject;98 void *buffer;99 ALuint bufferSize;101 ALuint frameSize;102 } osl_data;105 static const ALCchar opensl_device[] = "OpenSL";108 static SLuint32 GetChannelMask(enum DevFmtChannels chans)109 {110 switch(chans)111 {112 case DevFmtMono: return SL_SPEAKER_FRONT_CENTER;113 case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT;114 case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|115 SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;116 case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|117 SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|118 SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;119 case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|120 SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|121 SL_SPEAKER_BACK_CENTER|122 SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;123 case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|124 SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|125 SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|126 SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;127 case DevFmtX51Side: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|128 SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|129 SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;130 }131 return 0;132 }134 static const char *res_str(SLresult result)135 {136 switch(result)137 {138 case SL_RESULT_SUCCESS: return "Success";139 case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";140 case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid";141 case SL_RESULT_MEMORY_FAILURE: return "Memory failure";142 case SL_RESULT_RESOURCE_ERROR: return "Resource error";143 case SL_RESULT_RESOURCE_LOST: return "Resource lost";144 case SL_RESULT_IO_ERROR: return "I/O error";145 case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient";146 case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted";147 case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported";148 case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found";149 case SL_RESULT_PERMISSION_DENIED: return "Permission denied";150 case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported";151 case SL_RESULT_INTERNAL_ERROR: return "Internal error";152 case SL_RESULT_UNKNOWN_ERROR: return "Unknown error";153 case SL_RESULT_OPERATION_ABORTED: return "Operation aborted";154 case SL_RESULT_CONTROL_LOST: return "Control lost";155 case SL_RESULT_READONLY: return "ReadOnly";156 case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported";157 case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible";158 }159 return "Unknown error code";160 }162 #define PRINTERR(x, s) do { \163 if((x) != SL_RESULT_SUCCESS) \164 ERR("%s: %s\n", (s), res_str((x))); \165 } while(0)167 /* this callback handler is called every time a buffer finishes playing */168 static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *context)169 {170 ALCdevice *Device = context;171 osl_data *data = Device->ExtraData;172 SLresult result;174 aluMixData(Device, data->buffer, data->bufferSize/data->frameSize);176 result = (*bq)->Enqueue(bq, data->buffer, data->bufferSize);177 PRINTERR(result, "bq->Enqueue");178 }181 static ALCboolean opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName)182 {183 osl_data *data = NULL;184 SLresult result;186 if(!deviceName)187 deviceName = opensl_device;188 else if(strcmp(deviceName, opensl_device) != 0)189 return ALC_FALSE;191 data = calloc(1, sizeof(*data));192 if(!data)193 {194 alcSetError(Device, ALC_OUT_OF_MEMORY);195 return ALC_FALSE;196 }198 // create engine199 result = slCreateEngine(&data->engineObject, 0, NULL, 0, NULL, NULL);200 PRINTERR(result, "slCreateEngine");201 if(SL_RESULT_SUCCESS == result)202 {203 result = SLObjectItf_Realize(data->engineObject, SL_BOOLEAN_FALSE);204 PRINTERR(result, "engine->Realize");205 }206 if(SL_RESULT_SUCCESS == result)207 {208 result = SLObjectItf_GetInterface(data->engineObject, SL_IID_ENGINE, &data->engine);209 PRINTERR(result, "engine->GetInterface");210 }211 if(SL_RESULT_SUCCESS == result)212 {213 result = SLEngineItf_CreateOutputMix(data->engine, &data->outputMix, 0, NULL, NULL);214 PRINTERR(result, "engine->CreateOutputMix");215 }216 if(SL_RESULT_SUCCESS == result)217 {218 result = SLObjectItf_Realize(data->outputMix, SL_BOOLEAN_FALSE);219 PRINTERR(result, "outputMix->Realize");220 }222 if(SL_RESULT_SUCCESS != result)223 {224 if(data->outputMix != NULL)225 SLObjectItf_Destroy(data->outputMix);226 data->outputMix = NULL;228 if(data->engineObject != NULL)229 SLObjectItf_Destroy(data->engineObject);230 data->engineObject = NULL;231 data->engine = NULL;233 free(data);234 return ALC_FALSE;235 }237 Device->szDeviceName = strdup(deviceName);238 Device->ExtraData = data;240 return ALC_TRUE;241 }244 static void opensl_close_playback(ALCdevice *Device)245 {246 osl_data *data = Device->ExtraData;248 SLObjectItf_Destroy(data->outputMix);249 data->outputMix = NULL;251 SLObjectItf_Destroy(data->engineObject);252 data->engineObject = NULL;253 data->engine = NULL;255 free(data);256 Device->ExtraData = NULL;257 }259 static ALCboolean opensl_reset_playback(ALCdevice *Device)260 {261 osl_data *data = Device->ExtraData;262 SLDataLocator_AndroidSimpleBufferQueue loc_bufq;263 SLAndroidSimpleBufferQueueItf bufferQueue;264 SLDataLocator_OutputMix loc_outmix;265 SLDataFormat_PCM format_pcm;266 SLDataSource audioSrc;267 SLDataSink audioSnk;268 SLPlayItf player;269 SLInterfaceID id;270 SLboolean req;271 SLresult result;272 ALuint i;275 Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency;276 Device->UpdateSize = Device->UpdateSize * Device->NumUpdates / 2;277 Device->NumUpdates = 2;279 Device->Frequency = 44100;280 Device->FmtChans = DevFmtStereo;281 Device->FmtType = DevFmtShort;283 SetDefaultWFXChannelOrder(Device);286 id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;287 req = SL_BOOLEAN_TRUE;289 loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;290 loc_bufq.numBuffers = Device->NumUpdates;292 format_pcm.formatType = SL_DATAFORMAT_PCM;293 format_pcm.numChannels = ChannelsFromDevFmt(Device->FmtChans);294 format_pcm.samplesPerSec = Device->Frequency * 1000;295 format_pcm.bitsPerSample = BytesFromDevFmt(Device->FmtType) * 8;296 format_pcm.containerSize = format_pcm.bitsPerSample;297 format_pcm.channelMask = GetChannelMask(Device->FmtChans);298 format_pcm.endianness = SL_BYTEORDER_NATIVE;300 audioSrc.pLocator = &loc_bufq;301 audioSrc.pFormat = &format_pcm;303 loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;304 loc_outmix.outputMix = data->outputMix;305 audioSnk.pLocator = &loc_outmix;306 audioSnk.pFormat = NULL;309 result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req);310 PRINTERR(result, "engine->CreateAudioPlayer");311 if(SL_RESULT_SUCCESS == result)312 {313 result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE);314 PRINTERR(result, "bufferQueue->Realize");315 }316 if(SL_RESULT_SUCCESS == result)317 {318 result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue);319 PRINTERR(result, "bufferQueue->GetInterface");320 }321 if(SL_RESULT_SUCCESS == result)322 {323 result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device);324 PRINTERR(result, "bufferQueue->RegisterCallback");325 }326 if(SL_RESULT_SUCCESS == result)327 {328 data->frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);329 data->bufferSize = Device->UpdateSize * data->frameSize;330 data->buffer = calloc(1, data->bufferSize);331 if(!data->buffer)332 {333 result = SL_RESULT_MEMORY_FAILURE;334 PRINTERR(result, "calloc");335 }336 }337 /* enqueue the first buffer to kick off the callbacks */338 for(i = 0;i < Device->NumUpdates;i++)339 {340 if(SL_RESULT_SUCCESS == result)341 {342 result = (*bufferQueue)->Enqueue(bufferQueue, data->buffer, data->bufferSize);343 PRINTERR(result, "bufferQueue->Enqueue");344 }345 }346 if(SL_RESULT_SUCCESS == result)347 {348 result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player);349 PRINTERR(result, "bufferQueue->GetInterface");350 }351 if(SL_RESULT_SUCCESS == result)352 {353 result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING);354 PRINTERR(result, "player->SetPlayState");355 }357 if(SL_RESULT_SUCCESS != result)358 {359 if(data->bufferQueueObject != NULL)360 SLObjectItf_Destroy(data->bufferQueueObject);361 data->bufferQueueObject = NULL;363 free(data->buffer);364 data->buffer = NULL;365 data->bufferSize = 0;367 return ALC_FALSE;368 }370 return ALC_TRUE;371 }374 static void opensl_stop_playback(ALCdevice *Device)375 {376 osl_data *data = Device->ExtraData;378 if(data->bufferQueueObject != NULL)379 SLObjectItf_Destroy(data->bufferQueueObject);380 data->bufferQueueObject = NULL;382 free(data->buffer);383 data->buffer = NULL;384 data->bufferSize = 0;385 }388 static const BackendFuncs opensl_funcs = {389 opensl_open_playback,390 opensl_close_playback,391 opensl_reset_playback,392 opensl_stop_playback,393 NULL,394 NULL,395 NULL,396 NULL,397 NULL,398 NULL399 };402 ALCboolean alc_opensl_init(BackendFuncs *func_list)403 {404 *func_list = opensl_funcs;405 return ALC_TRUE;406 }408 void alc_opensl_deinit(void)409 {410 }412 void alc_opensl_probe(enum DevProbe type)413 {414 switch(type)415 {416 case DEVICE_PROBE:417 AppendDeviceList(opensl_device);418 break;419 case ALL_DEVICE_PROBE:420 AppendAllDeviceList(opensl_device);421 break;422 case CAPTURE_DEVICE_PROBE:423 break;424 }425 }