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 *pPreset = (SLuint16) preset; 365 #endif 366 367 } 368 369 SL_LEAVE_INTERFACE 370 } 371 372 373 static SLresult IEqualizer_UsePreset(SLEqualizerItf self, SLuint16 index) 374 { 375 SL_ENTER_INTERFACE 376 SL_LOGV("Equalizer::UsePreset index=%u", index); 377 378 IEqualizer *thiz = (IEqualizer *) self; 379 if (index >= thiz->mNumPresets) { 380 result = SL_RESULT_PARAMETER_INVALID; 381 } else { 382 interface_lock_exclusive(thiz); 383 #if !defined(ANDROID) 384 SLuint16 band; 385 for (band = 0; band < thiz->mNumBands; ++band) 386 thiz->mLevels[band] = EqualizerPresets[index].mLevels[band]; 387 thiz->mPreset = index; 388 interface_unlock_exclusive(thiz); 389 result = SL_RESULT_SUCCESS; 390 #else 391 if (NO_EQ(thiz)) { 392 result = SL_RESULT_CONTROL_LOST; 393 } else { 394 android::status_t status = 395 android_eq_setParam(thiz->mEqEffect, EQ_PARAM_CUR_PRESET, 0, &index); 396 result = android_fx_statusToResult(status); 397 } 398 interface_unlock_shared(thiz); 399 #endif 400 } 401 402 SL_LEAVE_INTERFACE 403 } 404 405 406 static SLresult IEqualizer_GetNumberOfPresets(SLEqualizerItf self, SLuint16 *pNumPresets) 407 { 408 SL_ENTER_INTERFACE 409 410 if (NULL == pNumPresets) { 411 result = SL_RESULT_PARAMETER_INVALID; 412 } else { 413 IEqualizer *thiz = (IEqualizer *) self; 414 // Note: no lock, but OK because it is const 415 *pNumPresets = thiz->mNumPresets; 416 417 result = SL_RESULT_SUCCESS; 418 } 419 420 SL_LEAVE_INTERFACE 421 } 422 423 424 static SLresult IEqualizer_GetPresetName(SLEqualizerItf self, SLuint16 index, const SLchar **ppName) 425 { 426 SL_ENTER_INTERFACE 427 428 if (NULL == ppName) { 429 result = SL_RESULT_PARAMETER_INVALID; 430 } else { 431 IEqualizer *thiz = (IEqualizer *) self; 432 #if !defined(ANDROID) 433 if (index >= thiz->mNumPresets) { 434 result = SL_RESULT_PARAMETER_INVALID; 435 } else { 436 *ppName = (SLchar *) thiz->mPresets[index].mName; 437 result = SL_RESULT_SUCCESS; 438 } 439 #else 440 if (index >= thiz->mNumPresets) { 441 result = SL_RESULT_PARAMETER_INVALID; 442 } else { 443 // FIXME query preset name rather than retrieve it from the engine. 444 // In SL ES 1.0.1, the strings must exist for the lifetime of the engine. 445 // Starting in 1.1, this will change and we don't need to hold onto the strings 446 // for so long as they will copied into application space. 447 *ppName = (SLchar *) thiz->mThis->mEngine->mEqPresetNames[index]; 448 result = SL_RESULT_SUCCESS; 449 } 450 #endif 451 } 452 453 SL_LEAVE_INTERFACE 454 } 455 456 457 static const struct SLEqualizerItf_ IEqualizer_Itf = { 458 IEqualizer_SetEnabled, 459 IEqualizer_IsEnabled, 460 IEqualizer_GetNumberOfBands, 461 IEqualizer_GetBandLevelRange, 462 IEqualizer_SetBandLevel, 463 IEqualizer_GetBandLevel, 464 IEqualizer_GetCenterFreq, 465 IEqualizer_GetBandFreqRange, 466 IEqualizer_GetBand, 467 IEqualizer_GetCurrentPreset, 468 IEqualizer_UsePreset, 469 IEqualizer_GetNumberOfPresets, 470 IEqualizer_GetPresetName 471 }; 472 473 void IEqualizer_init(void *self) 474 { 475 IEqualizer *thiz = (IEqualizer *) self; 476 thiz->mItf = &IEqualizer_Itf; 477 thiz->mEnabled = SL_BOOLEAN_FALSE; 478 thiz->mPreset = SL_EQUALIZER_UNDEFINED; 479 #if 0 < MAX_EQ_BANDS 480 unsigned band; 481 for (band = 0; band < MAX_EQ_BANDS; ++band) 482 thiz->mLevels[band] = 0; 483 #endif 484 // const fields 485 thiz->mNumPresets = 0; 486 thiz->mNumBands = 0; 487 #if !defined(ANDROID) 488 thiz->mBands = EqualizerBands; 489 thiz->mPresets = EqualizerPresets; 490 #endif 491 thiz->mBandLevelRangeMin = 0; 492 thiz->mBandLevelRangeMax = 0; 493 #if defined(ANDROID) 494 memset(&thiz->mEqDescriptor, 0, sizeof(effect_descriptor_t)); 495 // placement new (explicit constructor) 496 (void) new (&thiz->mEqEffect) android::sp<android::AudioEffect>(); 497 #endif 498 } 499 500 void IEqualizer_deinit(void *self) 501 { 502 #if defined(ANDROID) 503 IEqualizer *thiz = (IEqualizer *) self; 504 // explicit destructor 505 thiz->mEqEffect.~sp(); 506 #endif 507 } 508 509 bool IEqualizer_Expose(void *self) 510 { 511 #if defined(ANDROID) 512 IEqualizer *thiz = (IEqualizer *) self; 513 if (!android_fx_initEffectDescriptor(SL_IID_EQUALIZER, &thiz->mEqDescriptor)) { 514 SL_LOGE("Equalizer initialization failed"); 515 thiz->mNumPresets = 0; 516 thiz->mNumBands = 0; 517 thiz->mBandLevelRangeMin = 0; 518 thiz->mBandLevelRangeMax = 0; 519 return false; 520 } 521 #endif 522 return true; 523 } 524