android_Effect.cpp revision f5fce95f98037ea4ab341b416c82444af595313d
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//----------------------------------------------------------------------------- 226bool android_fx_initEffectDescriptor(const SLInterfaceID effectId, 227 effect_descriptor_t* fxDescrLoc) { 228 uint32_t numEffects = 0; 229 effect_descriptor_t descriptor; 230 bool foundEffect = false; 231 232 // any effects? 233 android::status_t res = android::AudioEffect::queryNumberEffects(&numEffects); 234 if (android::NO_ERROR != res) { 235 SL_LOGE("unable to find any effects."); 236 goto effectError; 237 } 238 239 // request effect in the effects? 240 for (uint32_t i=0 ; i < numEffects ; i++) { 241 res = android::AudioEffect::queryEffect(i, &descriptor); 242 if ((android::NO_ERROR == res) && 243 (0 == memcmp(effectId, &descriptor.type, sizeof(effect_uuid_t)))) { 244 SL_LOGV("found effect %d %s", i, descriptor.name); 245 foundEffect = true; 246 break; 247 } 248 } 249 if (foundEffect) { 250 memcpy(fxDescrLoc, &descriptor, sizeof(effect_descriptor_t)); 251 } else { 252 SL_LOGE("unable to find an implementation for the requested effect."); 253 goto effectError; 254 } 255 256 return true; 257 258effectError: 259 // the requested effect wasn't found 260 memset(fxDescrLoc, 0, sizeof(effect_descriptor_t)); 261 262 return false; 263} 264 265//----------------------------------------------------------------------------- 266SLresult android_genericFx_queryNumEffects(SLuint32 *pNumSupportedAudioEffects) { 267 268 if (NULL == pNumSupportedAudioEffects) { 269 return SL_RESULT_PARAMETER_INVALID; 270 } 271 272 android::status_t status = 273 android::AudioEffect::queryNumberEffects((uint32_t*)pNumSupportedAudioEffects); 274 275 SLresult result = SL_RESULT_SUCCESS; 276 switch(status) { 277 case android::NO_ERROR: 278 result = SL_RESULT_SUCCESS; 279 break; 280 case android::PERMISSION_DENIED: 281 result = SL_RESULT_PERMISSION_DENIED; 282 break; 283 case android::NO_INIT: 284 result = SL_RESULT_RESOURCE_ERROR; 285 break; 286 case android::BAD_VALUE: 287 result = SL_RESULT_PARAMETER_INVALID; 288 break; 289 default: 290 result = SL_RESULT_INTERNAL_ERROR; 291 SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status); 292 break; 293 } 294 return result; 295} 296 297 298//----------------------------------------------------------------------------- 299SLresult android_genericFx_queryEffect(SLuint32 index, SLInterfaceID *pAudioEffectId) { 300 301 if (NULL == pAudioEffectId) { 302 return SL_RESULT_PARAMETER_INVALID; 303 } 304 305 effect_descriptor_t descriptor; 306 android::status_t status = 307 android::AudioEffect::queryEffect(index, &descriptor); 308 309 SLresult result = SL_RESULT_SUCCESS; 310 switch(status) { 311 case android::NO_ERROR: 312 // FIXME this function will move to an engine interface where we will store the 313 // audio effect IDs and we only return references to those, as SLInterfaceID 314 // is a pointer to the struct where a uuid is stored. 315 //*pAudioEffectId = some global reference to where we keep a copy of the effect uuid 316 result = SL_RESULT_SUCCESS; 317 break; 318 case android::PERMISSION_DENIED: 319 result = SL_RESULT_PERMISSION_DENIED; 320 break; 321 case android::NO_INIT: 322 case android::INVALID_OPERATION: 323 result = SL_RESULT_RESOURCE_ERROR; 324 break; 325 case android::BAD_VALUE: 326 result = SL_RESULT_PARAMETER_INVALID; 327 break; 328 default: 329 result = SL_RESULT_INTERNAL_ERROR; 330 SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status); 331 break; 332 } 333 return result; 334} 335 336 337//----------------------------------------------------------------------------- 338SLresult android_genericFx_createEffect(int sessionId, SLInterfaceID pUuid, void **ppAudioEffect) { 339 340 android::AudioEffect* af = NULL; 341 SLresult result = SL_RESULT_SUCCESS; 342 343 af = new android::AudioEffect( 344 NULL, // not using type to create effect 345 (const effect_uuid_t*)pUuid, 346 0,// priority 347 0,// effect callback 348 0,// callback data 349 sessionId, 350 0 );// output 351 android::status_t status = af->initCheck(); 352 353 if (android::NO_ERROR != status) { 354 SL_LOGE("AudioEffect initCheck() returned %d", status); 355 result = SL_RESULT_RESOURCE_ERROR; 356 } 357 358 *ppAudioEffect = af; 359 return result; 360} 361 362 363//----------------------------------------------------------------------------- 364SLresult android_genericFx_releaseEffect(void *pAudioEffect) { 365 366 if (NULL != pAudioEffect) { 367 delete ((android::AudioEffect*)pAudioEffect); 368 return SL_RESULT_SUCCESS; 369 } else { 370 return SL_RESULT_PARAMETER_INVALID; 371 } 372} 373 374 375//----------------------------------------------------------------------------- 376SLresult android_genericFx_setEnabled(void *pAudioEffect, SLboolean enabled) { 377 378 if (NULL == pAudioEffect) { 379 return SL_RESULT_PARAMETER_INVALID; 380 } 381 382 android::status_t status = 383 ((android::AudioEffect*)pAudioEffect)->setEnabled(SL_BOOLEAN_TRUE == enabled); 384 385 return android_fx_statusToResult(status); 386} 387 388 389//----------------------------------------------------------------------------- 390SLresult android_genericFx_isEnabled(void *pAudioEffect, SLboolean *pEnabled) { 391 392 if (NULL == pAudioEffect) { 393 *pEnabled = SL_BOOLEAN_FALSE; 394 return SL_RESULT_PARAMETER_INVALID; 395 } 396 397 *pEnabled = 398 ((android::AudioEffect*)pAudioEffect)->getEnabled() ? SL_BOOLEAN_TRUE : SL_BOOLEAN_FALSE; 399 400 return SL_RESULT_SUCCESS; 401} 402 403 404//----------------------------------------------------------------------------- 405SLresult android_genericFx_sendCommand(void *pAudioEffect, SLuint32 command, SLuint32 commandSize, 406 void* pCommand, SLuint32 *replySize, void *pReply) { 407 408 if (NULL == pAudioEffect) { 409 return SL_RESULT_PARAMETER_INVALID; 410 } 411 412 android::status_t status = ((android::AudioEffect*)pAudioEffect)->command( 413 (uint32_t) command, 414 (uint32_t) commandSize, 415 pCommand, 416 (uint32_t*)replySize, 417 pReply); 418 419 if (android::BAD_VALUE == status) { 420 return SL_RESULT_PARAMETER_INVALID; 421 } 422 return SL_RESULT_SUCCESS; 423} 424 425 426