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