android_Effect.cpp revision b3b757daa7d162b6f66590d917c1f84f3ba73c70
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 18#include "sles_allinclusive.h" 19#include "math.h" 20#include "utils/RefBase.h" 21 22 23static const int EQUALIZER_PARAM_SIZE_MAX = sizeof(effect_param_t) + 2 * sizeof(int32_t) 24 + EFFECT_STRING_LEN_MAX; 25 26 27//----------------------------------------------------------------------------- 28uint32_t eq_paramSize(int32_t param) 29{ 30 uint32_t size; 31 32 switch (param) { 33 case EQ_PARAM_NUM_BANDS: 34 case EQ_PARAM_LEVEL_RANGE: 35 case EQ_PARAM_CUR_PRESET: 36 case EQ_PARAM_GET_NUM_OF_PRESETS: 37 size = sizeof(int32_t); 38 break; 39 case EQ_PARAM_BAND_LEVEL: 40 case EQ_PARAM_CENTER_FREQ: 41 case EQ_PARAM_BAND_FREQ_RANGE: 42 case EQ_PARAM_GET_BAND: 43 case EQ_PARAM_GET_PRESET_NAME: 44 size = 2 * sizeof(int32_t); 45 break; 46 default: 47 size = 2 * sizeof(int32_t); 48 SL_LOGE("Trying to use an unknown EQ parameter %d", param); 49 break; 50 } 51 return size; 52} 53 54uint32_t eq_valueSize(int32_t param) 55{ 56 uint32_t size; 57 58 switch (param) { 59 case EQ_PARAM_NUM_BANDS: 60 case EQ_PARAM_CUR_PRESET: 61 case EQ_PARAM_GET_NUM_OF_PRESETS: 62 case EQ_PARAM_BAND_LEVEL: 63 case EQ_PARAM_GET_BAND: 64 size = sizeof(int16_t); 65 break; 66 case EQ_PARAM_LEVEL_RANGE: 67 size = 2 * sizeof(int16_t); 68 break; 69 case EQ_PARAM_CENTER_FREQ: 70 size = sizeof(int32_t); 71 break; 72 case EQ_PARAM_BAND_FREQ_RANGE: 73 size = 2 * sizeof(int32_t); 74 break; 75 case EQ_PARAM_GET_PRESET_NAME: 76 size = EFFECT_STRING_LEN_MAX; 77 break; 78 default: 79 size = sizeof(int32_t); 80 SL_LOGE("Trying to access an unknown EQ parameter %d", param); 81 break; 82 } 83 return size; 84} 85 86 87//----------------------------------------------------------------------------- 88android::status_t android_eq_getParam(android::sp<android::AudioEffect> pFx, 89 int32_t param, int32_t param2, void *pValue) 90{ 91 android::status_t status; 92 uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1]; 93 effect_param_t *p = (effect_param_t *)buf32; 94 95 p->psize = eq_paramSize(param); 96 *(int32_t *)p->data = param; 97 if (p->psize == 2 * sizeof(int32_t)) { 98 *((int32_t *)p->data + 1) = param2; 99 } 100 p->vsize = eq_valueSize(param); 101 status = pFx->getParameter(p); 102 if (android::NO_ERROR == status) { 103 status = p->status; 104 if (android::NO_ERROR == status) { 105 memcpy(pValue, p->data + p->psize, p->vsize); 106 } 107 } 108 109 return status; 110 } 111 112 113//----------------------------------------------------------------------------- 114android::status_t android_eq_setParam(android::sp<android::AudioEffect> pFx, 115 int32_t param, int32_t param2, void *pValue) 116{ 117 android::status_t status; 118 uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1]; 119 effect_param_t *p = (effect_param_t *)buf32; 120 121 p->psize = eq_paramSize(param); 122 *(int32_t *)p->data = param; 123 if (p->psize == 2 * sizeof(int32_t)) { 124 *((int32_t *)p->data + 1) = param2; 125 } 126 p->vsize = eq_valueSize(param); 127 memcpy(p->data + p->psize, pValue, p->vsize); 128 status = pFx->setParameter(p); 129 if (android::NO_ERROR == status) { 130 status = p->status; 131 } 132 133 return status; 134} 135 136 137//----------------------------------------------------------------------------- 138void android_eq_init(int sessionId, CAudioPlayer* ap) { 139 SL_LOGV("android_initEq on session %d", sessionId); 140 141 ap->mEqualizer.mEqEffect = new android::AudioEffect( 142 &ap->mEqualizer.mEqDescriptor.type,//(const effect_uuid_t*)SL_IID_EQUALIZER,// 143 &ap->mEqualizer.mEqDescriptor.uuid, 144 0,// priority 145 0,// effect callback 146 0,// callback data 147 sessionId,// session ID 148 0 );// output 149 android::status_t status = ap->mEqualizer.mEqEffect->initCheck(); 150 if (android::NO_ERROR != status) { 151 SL_LOGE("EQ initCheck() returned %d", status); 152 return; 153 } 154 155 // initialize number of bands, band level range 156 uint16_t num = 0; 157 if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect, 158 EQ_PARAM_NUM_BANDS, 0, &num)) { 159 ap->mEqualizer.mNumBands = num; 160 } 161 int16_t range[2] = {0, 0}; 162 if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect, 163 EQ_PARAM_LEVEL_RANGE, 0, range)) { 164 ap->mEqualizer.mBandLevelRangeMin = range[0]; 165 ap->mEqualizer.mBandLevelRangeMax = range[1]; 166 } 167 168 SL_LOGV(" EQ init: num presets = %u, band range=[%d %d]mB", num, range[0], range[1]); 169 170 // initialize preset number and names, store in IEngine 171 uint16_t numPresets = 0; 172 if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect, 173 EQ_PARAM_GET_NUM_OF_PRESETS, 0, &numPresets)) { 174 ap->mObject.mEngine->mEqNumPresets = numPresets; 175 } 176 char name[EFFECT_STRING_LEN_MAX]; 177 if ((0 < numPresets) && (NULL == ap->mObject.mEngine->mEqPresetNames)) { 178 ap->mObject.mEngine->mEqPresetNames = (char **)new char *[numPresets]; 179 for(uint32_t i = 0 ; i < numPresets ; i++) { 180 if (android::NO_ERROR == android_eq_getParam(ap->mEqualizer.mEqEffect, 181 EQ_PARAM_GET_PRESET_NAME, i, name)) { 182 ap->mObject.mEngine->mEqPresetNames[i] = new char[strlen(name) + 1]; 183 strcpy(ap->mObject.mEngine->mEqPresetNames[i], name); 184 SL_LOGV(" EQ init: presets = %u is %s", i, ap->mObject.mEngine->mEqPresetNames[i]); 185 } 186 187 } 188 } 189#if 0 190 // configure the EQ so it can easily be heard, for test only 191 uint32_t freq = 1977; 192 uint32_t frange[2]; 193 int16_t value = ap->mEqualizer.mBandLevelRangeMin; 194 for(int32_t i=0 ; i< ap->mEqualizer.mNumBands ; i++) { 195 android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, i, &value); 196 // display EQ characteristics 197 android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_CENTER_FREQ, i, &freq); 198 android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_FREQ_RANGE, i, frange); 199 SL_LOGV(" EQ init: band %d = %d - %d - %dHz", i, frange[0]/1000, freq/1000, 200 frange[1]/1000); 201 } 202 value = ap->mEqualizer.mBandLevelRangeMax; 203 if (ap->mEqualizer.mNumBands > 2) { 204 android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 2, &value); 205 } 206 if (ap->mEqualizer.mNumBands > 3) { 207 android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 3, &value); 208 } 209 210 ap->mEqualizer.mEqEffect->setEnabled(true); 211#endif 212} 213 214//----------------------------------------------------------------------------- 215SLresult android_fx_statusToResult(android::status_t status) { 216 217 if ((android::INVALID_OPERATION == status) || (android::DEAD_OBJECT == status)) { 218 return SL_RESULT_CONTROL_LOST; 219 } else { 220 return SL_RESULT_SUCCESS; 221 } 222} 223 224 225//----------------------------------------------------------------------------- 226SLresult android_genericFx_queryNumEffects(SLuint32 *pNumSupportedAudioEffects) { 227 228 if (NULL == pNumSupportedAudioEffects) { 229 return SL_RESULT_PARAMETER_INVALID; 230 } 231 232 android::status_t status = 233 android::AudioEffect::queryNumberEffects((uint32_t*)pNumSupportedAudioEffects); 234 235 SLresult result = SL_RESULT_SUCCESS; 236 switch(status) { 237 case android::NO_ERROR: 238 result = SL_RESULT_SUCCESS; 239 break; 240 case android::PERMISSION_DENIED: 241 result = SL_RESULT_PERMISSION_DENIED; 242 break; 243 case android::NO_INIT: 244 result = SL_RESULT_RESOURCE_ERROR; 245 break; 246 case android::BAD_VALUE: 247 result = SL_RESULT_PARAMETER_INVALID; 248 break; 249 default: 250 result = SL_RESULT_INTERNAL_ERROR; 251 SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status); 252 break; 253 } 254 return result; 255} 256 257 258//----------------------------------------------------------------------------- 259SLresult android_genericFx_queryEffect(SLuint32 index, SLInterfaceID *pAudioEffectId) { 260 261 if (NULL == pAudioEffectId) { 262 return SL_RESULT_PARAMETER_INVALID; 263 } 264 265 effect_descriptor_t descriptor; 266 android::status_t status = 267 android::AudioEffect::queryEffect(index, &descriptor); 268 269 SLresult result = SL_RESULT_SUCCESS; 270 switch(status) { 271 case android::NO_ERROR: 272 // FIXME this function will move to an engine interface where we will store the 273 // audio effect IDs and we only return references to those, as SLInterfaceID 274 // is a pointer to the struct where a uuid is stored. 275 //*pAudioEffectId = some global reference to where we keep a copy of the effect uuid 276 result = SL_RESULT_SUCCESS; 277 break; 278 case android::PERMISSION_DENIED: 279 result = SL_RESULT_PERMISSION_DENIED; 280 break; 281 case android::NO_INIT: 282 case android::INVALID_OPERATION: 283 result = SL_RESULT_RESOURCE_ERROR; 284 break; 285 case android::BAD_VALUE: 286 result = SL_RESULT_PARAMETER_INVALID; 287 break; 288 default: 289 result = SL_RESULT_INTERNAL_ERROR; 290 SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status); 291 break; 292 } 293 return result; 294} 295 296 297//----------------------------------------------------------------------------- 298SLresult android_genericFx_createEffect(int sessionId, SLInterfaceID pUuid, void **ppAudioEffect) { 299 300 android::AudioEffect* af = NULL; 301 SLresult result = SL_RESULT_SUCCESS; 302 303 af = new android::AudioEffect( 304 NULL, // not using type to create effect 305 (const effect_uuid_t*)pUuid, 306 0,// priority 307 0,// effect callback 308 0,// callback data 309 sessionId, 310 0 );// output 311 android::status_t status = af->initCheck(); 312 313 if (android::NO_ERROR != status) { 314 SL_LOGE("AudioEffect initCheck() returned %d", status); 315 result = SL_RESULT_RESOURCE_ERROR; 316 } 317 318 *ppAudioEffect = af; 319 return result; 320} 321 322 323//----------------------------------------------------------------------------- 324SLresult android_genericFx_releaseEffect(void *pAudioEffect) { 325 326 if (NULL != pAudioEffect) { 327 delete ((android::AudioEffect*)pAudioEffect); 328 return SL_RESULT_SUCCESS; 329 } else { 330 return SL_RESULT_PARAMETER_INVALID; 331 } 332} 333 334 335//----------------------------------------------------------------------------- 336SLresult android_genericFx_setEnabled(void *pAudioEffect, SLboolean enabled) { 337 338 if (NULL == pAudioEffect) { 339 return SL_RESULT_PARAMETER_INVALID; 340 } 341 342 android::status_t status = 343 ((android::AudioEffect*)pAudioEffect)->setEnabled(SL_BOOLEAN_TRUE == enabled); 344 345 // the effect framework will return an error if the requested state is the same as the previous, 346 // this prevents us from returning an error when the effect cannot be controlled. We're 347 // therefore returning success regardless of the status code. 348 return SL_RESULT_SUCCESS; 349} 350 351 352//----------------------------------------------------------------------------- 353SLresult android_genericFx_isEnabled(void *pAudioEffect, SLboolean *pEnabled) { 354 355 if (NULL == pAudioEffect) { 356 *pEnabled = SL_BOOLEAN_FALSE; 357 return SL_RESULT_PARAMETER_INVALID; 358 } 359 360 *pEnabled = 361 ((android::AudioEffect*)pAudioEffect)->getEnabled() ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE; 362 363 return SL_RESULT_SUCCESS; 364} 365 366 367//----------------------------------------------------------------------------- 368SLresult android_genericFx_sendCommand(void *pAudioEffect, SLuint32 command, SLuint32 commandSize, 369 void* pCommand, SLuint32 *replySize, void *pReply) { 370 371 if (NULL == pAudioEffect) { 372 return SL_RESULT_PARAMETER_INVALID; 373 } 374 375 // FIXME update size casts when framework moves from int32_t to uint32_t 376 android::status_t status = ((android::AudioEffect*)pAudioEffect)->command( 377 (int32_t) command, 378 (int32_t) commandSize, 379 pCommand, 380 (uint32_t*)replySize, 381 pReply); 382 383 if (android::BAD_VALUE == status) { 384 return SL_RESULT_PARAMETER_INVALID; 385 } 386 return SL_RESULT_SUCCESS; 387} 388 389 390