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 /* Equalizer implementation */ 18 19 #include "sles_allinclusive.h" 20 #ifdef ANDROID 21 #include <audio_effects/effect_equalizer.h> 22 #endif 23 24 #define MAX_EQ_PRESETS 3 25 26 #if !defined(ANDROID) 27 static const struct EqualizerBand EqualizerBands[MAX_EQ_BANDS] = { 28 {1000, 1500, 2000}, 29 {2000, 3000, 4000}, 30 {4000, 5500, 7000}, 31 {7000, 8000, 9000} 32 }; 33 34 static const struct EqualizerPreset { 35 const char *mName; 36 SLmillibel mLevels[MAX_EQ_BANDS]; 37 } EqualizerPresets[MAX_EQ_PRESETS] = { 38 {"Default", {0, 0, 0, 0}}, 39 {"Bass", {500, 200, 100, 0}}, 40 {"Treble", {0, 100, 200, 500}} 41 }; 42 #endif 43 44 45 #if defined(ANDROID) 46 /** 47 * returns true if this interface is not associated with an initialized Equalizer effect 48 */ 49 static inline bool NO_EQ(IEqualizer* v) { 50 return (v->mEqEffect == 0); 51 } 52 #endif 53 54 55 static SLresult IEqualizer_SetEnabled(SLEqualizerItf self, SLboolean enabled) 56 { 57 SL_ENTER_INTERFACE 58 59 IEqualizer *thiz = (IEqualizer *) self; 60 interface_lock_exclusive(thiz); 61 thiz->mEnabled = (SLboolean) enabled; 62 #if !defined(ANDROID) 63 result = SL_RESULT_SUCCESS; 64 #else 65 if (NO_EQ(thiz)) { 66 result = SL_RESULT_CONTROL_LOST; 67 } else { 68 android::status_t status = 69 thiz->mEqEffect->setEnabled((bool) thiz->mEnabled); 70 result = android_fx_statusToResult(status); 71 } 72 #endif 73 interface_unlock_exclusive(thiz); 74 75 SL_LEAVE_INTERFACE 76 } 77 78 79 static SLresult IEqualizer_IsEnabled(SLEqualizerItf self, SLboolean *pEnabled) 80 { 81 SL_ENTER_INTERFACE 82 83 if (NULL == pEnabled) { 84 result = SL_RESULT_PARAMETER_INVALID; 85 } else { 86 IEqualizer *thiz = (IEqualizer *) self; 87 interface_lock_exclusive(thiz); 88 SLboolean enabled = thiz->mEnabled; 89 #if !defined(ANDROID) 90 *pEnabled = enabled; 91 result = SL_RESULT_SUCCESS; 92 #else 93 if (NO_EQ(thiz)) { 94 result = SL_RESULT_CONTROL_LOST; 95 } else { 96 *pEnabled = (SLboolean) thiz->mEqEffect->getEnabled(); 97 result = SL_RESULT_SUCCESS; 98 } 99 #endif 100 interface_unlock_exclusive(thiz); 101 } 102 103 SL_LEAVE_INTERFACE 104 } 105 106 107 static SLresult IEqualizer_GetNumberOfBands(SLEqualizerItf self, SLuint16 *pNumBands) 108 { 109 SL_ENTER_INTERFACE 110 111 if (NULL == pNumBands) { 112 result = SL_RESULT_PARAMETER_INVALID; 113 } else { 114 IEqualizer *thiz = (IEqualizer *) self; 115 // Note: no lock, but OK because it is const 116 *pNumBands = thiz->mNumBands; 117 result = SL_RESULT_SUCCESS; 118 } 119 120 SL_LEAVE_INTERFACE 121 } 122 123 124 static SLresult IEqualizer_GetBandLevelRange(SLEqualizerItf self, SLmillibel *pMin, 125 SLmillibel *pMax) 126 { 127 SL_ENTER_INTERFACE 128 129 if (NULL == pMin && NULL == pMax) { 130 result = SL_RESULT_PARAMETER_INVALID; 131 } else { 132 IEqualizer *thiz = (IEqualizer *) self; 133 // Note: no lock, but OK because it is const 134 if (NULL != pMin) 135 *pMin = thiz->mBandLevelRangeMin; 136 if (NULL != pMax) 137 *pMax = thiz->mBandLevelRangeMax; 138 result = SL_RESULT_SUCCESS; 139 } 140 141 SL_LEAVE_INTERFACE 142 } 143 144 145 static SLresult IEqualizer_SetBandLevel(SLEqualizerItf self, SLuint16 band, SLmillibel level) 146 { 147 SL_ENTER_INTERFACE 148 149 IEqualizer *thiz = (IEqualizer *) self; 150 if (!(thiz->mBandLevelRangeMin <= level && level <= thiz->mBandLevelRangeMax) || 151 (band >= thiz->mNumBands)) { 152 result = SL_RESULT_PARAMETER_INVALID; 153 } else { 154 interface_lock_exclusive(thiz); 155 #if !defined(ANDROID) 156 thiz->mLevels[band] = level; 157 thiz->mPreset = SL_EQUALIZER_UNDEFINED; 158 result = SL_RESULT_SUCCESS; 159 #else 160 if (NO_EQ(thiz)) { 161 result = SL_RESULT_CONTROL_LOST; 162 } else { 163 android::status_t status = 164 android_eq_setParam(thiz->mEqEffect, EQ_PARAM_BAND_LEVEL, band, &level); 165 result = android_fx_statusToResult(status); 166 } 167 #endif 168 interface_unlock_exclusive(thiz); 169 } 170 171 SL_LEAVE_INTERFACE 172 } 173 174 175 static SLresult IEqualizer_GetBandLevel(SLEqualizerItf self, SLuint16 band, SLmillibel *pLevel) 176 { 177 SL_ENTER_INTERFACE 178 179 if (NULL == pLevel) { 180 result = SL_RESULT_PARAMETER_INVALID; 181 } else { 182 IEqualizer *thiz = (IEqualizer *) self; 183 // const, no lock needed 184 if (band >= thiz->mNumBands) { 185 result = SL_RESULT_PARAMETER_INVALID; 186 } else { 187 SLmillibel level = 0; 188 interface_lock_shared(thiz); 189 #if !defined(ANDROID) 190 level = thiz->mLevels[band]; 191 result = SL_RESULT_SUCCESS; 192 #else 193 if (NO_EQ(thiz)) { 194 result = SL_RESULT_CONTROL_LOST; 195 } else { 196 android::status_t status = 197 android_eq_getParam(thiz->mEqEffect, EQ_PARAM_BAND_LEVEL, band, &level); 198 result = android_fx_statusToResult(status); 199 } 200 #endif 201 interface_unlock_shared(thiz); 202 *pLevel = level; 203 } 204 } 205 206 SL_LEAVE_INTERFACE 207 } 208 209 210 static SLresult IEqualizer_GetCenterFreq(SLEqualizerItf self, SLuint16 band, SLmilliHertz *pCenter) 211 { 212 SL_ENTER_INTERFACE 213 214 if (NULL == pCenter) { 215 result = SL_RESULT_PARAMETER_INVALID; 216 } else { 217 IEqualizer *thiz = (IEqualizer *) self; 218 if (band >= thiz->mNumBands) { 219 result = SL_RESULT_PARAMETER_INVALID; 220 } else { 221 #if !defined(ANDROID) 222 // Note: no lock, but OK because it is const 223 *pCenter = thiz->mBands[band].mCenter; 224 result = SL_RESULT_SUCCESS; 225 #else 226 SLmilliHertz center = 0; 227 interface_lock_shared(thiz); 228 if (NO_EQ(thiz)) { 229 result = SL_RESULT_CONTROL_LOST; 230 } else { 231 android::status_t status = 232 android_eq_getParam(thiz->mEqEffect, EQ_PARAM_CENTER_FREQ, band, ¢er); 233 result = android_fx_statusToResult(status); 234 } 235 interface_unlock_shared(thiz); 236 *pCenter = center; 237 #endif 238 } 239 } 240 241 SL_LEAVE_INTERFACE 242 } 243 244 245 static SLresult IEqualizer_GetBandFreqRange(SLEqualizerItf self, SLuint16 band, 246 SLmilliHertz *pMin, SLmilliHertz *pMax) 247 { 248 SL_ENTER_INTERFACE 249 250 if (NULL == pMin && NULL == pMax) { 251 result = SL_RESULT_PARAMETER_INVALID; 252 } else { 253 IEqualizer *thiz = (IEqualizer *) self; 254 if (band >= thiz->mNumBands) { 255 result = SL_RESULT_PARAMETER_INVALID; 256 } else { 257 #if !defined(ANDROID) 258 // Note: no lock, but OK because it is const 259 if (NULL != pMin) 260 *pMin = thiz->mBands[band].mMin; 261 if (NULL != pMax) 262 *pMax = thiz->mBands[band].mMax; 263 result = SL_RESULT_SUCCESS; 264 #else 265 SLmilliHertz range[2] = {0, 0}; // SLmilliHertz is SLuint32 266 interface_lock_shared(thiz); 267 if (NO_EQ(thiz)) { 268 result = SL_RESULT_CONTROL_LOST; 269 } else { 270 android::status_t status = 271 android_eq_getParam(thiz->mEqEffect, EQ_PARAM_BAND_FREQ_RANGE, band, range); 272 result = android_fx_statusToResult(status); 273 } 274 interface_unlock_shared(thiz); 275 if (NULL != pMin) { 276 *pMin = range[0]; 277 } 278 if (NULL != pMax) { 279 *pMax = range[1]; 280 } 281 #endif 282 } 283 } 284 285 SL_LEAVE_INTERFACE 286 } 287 288 289 static SLresult IEqualizer_GetBand(SLEqualizerItf self, SLmilliHertz frequency, SLuint16 *pBand) 290 { 291 SL_ENTER_INTERFACE 292 293 if (NULL == pBand) { 294 result = SL_RESULT_PARAMETER_INVALID; 295 } else { 296 IEqualizer *thiz = (IEqualizer *) self; 297 #if !defined(ANDROID) 298 // search for band whose center frequency has the closest ratio to 1.0 299 // assumes bands are unsorted (a pessimistic assumption) 300 // assumes bands can overlap (a pessimistic assumption) 301 // assumes a small number of bands, so no need for a fancier algorithm 302 const struct EqualizerBand *band; 303 float floatFreq = (float) frequency; 304 float bestRatio = 0.0; 305 SLuint16 bestBand = SL_EQUALIZER_UNDEFINED; 306 for (band = thiz->mBands; band < &thiz->mBands[thiz->mNumBands]; ++band) { 307 if (!(band->mMin <= frequency && frequency <= band->mMax)) 308 continue; 309 assert(band->mMin <= band->mCenter && band->mCenter <= band->mMax); 310 assert(band->mCenter != 0); 311 float ratio = frequency <= band->mCenter ? 312 floatFreq / band->mCenter : band->mCenter / floatFreq; 313 if (ratio > bestRatio) { 314 bestRatio = ratio; 315 bestBand = band - thiz->mBands; 316 } 317 } 318 *pBand = bestBand; 319 result = SL_RESULT_SUCCESS; 320 #else 321 uint16_t band = 0; 322 interface_lock_shared(thiz); 323 if (NO_EQ(thiz)) { 324 result = SL_RESULT_CONTROL_LOST; 325 } else { 326 android::status_t status = 327 android_eq_getParam(thiz->mEqEffect, EQ_PARAM_GET_BAND, frequency, &band); 328 result = android_fx_statusToResult(status); 329 } 330 interface_unlock_shared(thiz); 331 *pBand = (SLuint16)band; 332 #endif 333 } 334 335 SL_LEAVE_INTERFACE 336 } 337 338 339 static SLresult IEqualizer_GetCurrentPreset(SLEqualizerItf self, SLuint16 *pPreset) 340 { 341 SL_ENTER_INTERFACE 342 343 if (NULL == pPreset) { 344 result = SL_RESULT_PARAMETER_INVALID; 345 } else { 346 IEqualizer *thiz = (IEqualizer *) self; 347 interface_lock_shared(thiz); 348 #if !defined(ANDROID) 349 SLuint16 preset = thiz->mPreset; 350 interface_unlock_shared(thiz); 351 *pPreset = preset; 352 result = SL_RESULT_SUCCESS; 353 #else 354 uint16_t preset = 0; 355 if (NO_EQ(thiz)) { 356 result = SL_RESULT_CONTROL_LOST; 357 } else { 358 android::status_t status = 359 android_eq_getParam(thiz->mEqEffect, EQ_PARAM_CUR_PRESET, 0, &preset); 360 result = android_fx_statusToResult(status); 361 } 362 interface_unlock_shared(thiz); 363 364 if (preset < 0) { 365 *pPreset = SL_EQUALIZER_UNDEFINED; 366 } else { 367 *pPreset = (SLuint16) preset; 368 } 369 #endif 370 371 } 372 373 SL_LEAVE_INTERFACE 374 } 375 376 377 static SLresult IEqualizer_UsePreset(SLEqualizerItf self, SLuint16 index) 378 { 379 SL_ENTER_INTERFACE 380 SL_LOGV("Equalizer::UsePreset index=%u", index); 381 382 IEqualizer *thiz = (IEqualizer *) self; 383 if (index >= thiz->mNumPresets) { 384 result = SL_RESULT_PARAMETER_INVALID; 385 } else { 386 interface_lock_exclusive(thiz); 387 #if !defined(ANDROID) 388 SLuint16 band; 389 for (band = 0; band < thiz->mNumBands; ++band) 390 thiz->mLevels[band] = EqualizerPresets[index].mLevels[band]; 391 thiz->mPreset = index; 392 interface_unlock_exclusive(thiz); 393 result = SL_RESULT_SUCCESS; 394 #else 395 if (NO_EQ(thiz)) { 396 result = SL_RESULT_CONTROL_LOST; 397 } else { 398 android::status_t status = 399 android_eq_setParam(thiz->mEqEffect, EQ_PARAM_CUR_PRESET, 0, &index); 400 result = android_fx_statusToResult(status); 401 } 402 interface_unlock_shared(thiz); 403 #endif 404 } 405 406 SL_LEAVE_INTERFACE 407 } 408 409 410 static SLresult IEqualizer_GetNumberOfPresets(SLEqualizerItf self, SLuint16 *pNumPresets) 411 { 412 SL_ENTER_INTERFACE 413 414 if (NULL == pNumPresets) { 415 result = SL_RESULT_PARAMETER_INVALID; 416 } else { 417 IEqualizer *thiz = (IEqualizer *) self; 418 // Note: no lock, but OK because it is const 419 *pNumPresets = thiz->mNumPresets; 420 421 result = SL_RESULT_SUCCESS; 422 } 423 424 SL_LEAVE_INTERFACE 425 } 426 427 428 static SLresult IEqualizer_GetPresetName(SLEqualizerItf self, SLuint16 index, const SLchar **ppName) 429 { 430 SL_ENTER_INTERFACE 431 432 if (NULL == ppName) { 433 result = SL_RESULT_PARAMETER_INVALID; 434 } else { 435 IEqualizer *thiz = (IEqualizer *) self; 436 #if !defined(ANDROID) 437 if (index >= thiz->mNumPresets) { 438 result = SL_RESULT_PARAMETER_INVALID; 439 } else { 440 *ppName = (SLchar *) thiz->mPresets[index].mName; 441 result = SL_RESULT_SUCCESS; 442 } 443 #else 444 if (index >= thiz->mNumPresets) { 445 result = SL_RESULT_PARAMETER_INVALID; 446 } else { 447 // FIXME query preset name rather than retrieve it from the engine. 448 // In SL ES 1.0.1, the strings must exist for the lifetime of the engine. 449 // Starting in 1.1, this will change and we don't need to hold onto the strings 450 // for so long as they will copied into application space. 451 *ppName = (SLchar *) thiz->mThis->mEngine->mEqPresetNames[index]; 452 result = SL_RESULT_SUCCESS; 453 } 454 #endif 455 } 456 457 SL_LEAVE_INTERFACE 458 } 459 460 461 static const struct SLEqualizerItf_ IEqualizer_Itf = { 462 IEqualizer_SetEnabled, 463 IEqualizer_IsEnabled, 464 IEqualizer_GetNumberOfBands, 465 IEqualizer_GetBandLevelRange, 466 IEqualizer_SetBandLevel, 467 IEqualizer_GetBandLevel, 468 IEqualizer_GetCenterFreq, 469 IEqualizer_GetBandFreqRange, 470 IEqualizer_GetBand, 471 IEqualizer_GetCurrentPreset, 472 IEqualizer_UsePreset, 473 IEqualizer_GetNumberOfPresets, 474 IEqualizer_GetPresetName 475 }; 476 477 void IEqualizer_init(void *self) 478 { 479 IEqualizer *thiz = (IEqualizer *) self; 480 thiz->mItf = &IEqualizer_Itf; 481 thiz->mEnabled = SL_BOOLEAN_FALSE; 482 thiz->mPreset = SL_EQUALIZER_UNDEFINED; 483 #if 0 < MAX_EQ_BANDS 484 unsigned band; 485 for (band = 0; band < MAX_EQ_BANDS; ++band) 486 thiz->mLevels[band] = 0; 487 #endif 488 // const fields 489 thiz->mNumPresets = 0; 490 thiz->mNumBands = 0; 491 #if !defined(ANDROID) 492 thiz->mBands = EqualizerBands; 493 thiz->mPresets = EqualizerPresets; 494 #endif 495 thiz->mBandLevelRangeMin = 0; 496 thiz->mBandLevelRangeMax = 0; 497 #if defined(ANDROID) 498 memset(&thiz->mEqDescriptor, 0, sizeof(effect_descriptor_t)); 499 // placement new (explicit constructor) 500 (void) new (&thiz->mEqEffect) android::sp<android::AudioEffect>(); 501 #endif 502 } 503 504 void IEqualizer_deinit(void *self) 505 { 506 #if defined(ANDROID) 507 IEqualizer *thiz = (IEqualizer *) self; 508 // explicit destructor 509 thiz->mEqEffect.~sp(); 510 #endif 511 } 512 513 bool IEqualizer_Expose(void *self) 514 { 515 #if defined(ANDROID) 516 IEqualizer *thiz = (IEqualizer *) self; 517 if (!android_fx_initEffectDescriptor(SL_IID_EQUALIZER, &thiz->mEqDescriptor)) { 518 SL_LOGE("Equalizer initialization failed"); 519 thiz->mNumPresets = 0; 520 thiz->mNumBands = 0; 521 thiz->mBandLevelRangeMin = 0; 522 thiz->mBandLevelRangeMax = 0; 523 return false; 524 } 525 #endif 526 return true; 527 } 528