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) || defined(USE_BACKPORT)
24 static 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
31 static 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) && !defined(USE_BACKPORT)
43 /**
44 * returns true if this interface is not associated with an initialized Equalizer effect
45 */
NO_EQ(IEqualizer * v)46 static inline bool NO_EQ(IEqualizer* v) {
47 return (v->mEqEffect == 0);
48 }
49 #endif
50
51
IEqualizer_SetEnabled(SLEqualizerItf self,SLboolean enabled)52 static 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) || defined(USE_BACKPORT)
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
IEqualizer_IsEnabled(SLEqualizerItf self,SLboolean * pEnabled)76 static 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) || defined(USE_BACKPORT)
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
IEqualizer_GetNumberOfBands(SLEqualizerItf self,SLuint16 * pNumBands)104 static 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
IEqualizer_GetBandLevelRange(SLEqualizerItf self,SLmillibel * pMin,SLmillibel * pMax)121 static 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
IEqualizer_SetBandLevel(SLEqualizerItf self,SLuint16 band,SLmillibel level)142 static 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) || defined(USE_BACKPORT)
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
IEqualizer_GetBandLevel(SLEqualizerItf self,SLuint16 band,SLmillibel * pLevel)172 static 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) || defined(USE_BACKPORT)
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
IEqualizer_GetCenterFreq(SLEqualizerItf self,SLuint16 band,SLmilliHertz * pCenter)207 static 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) || defined(USE_BACKPORT)
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
IEqualizer_GetBandFreqRange(SLEqualizerItf self,SLuint16 band,SLmilliHertz * pMin,SLmilliHertz * pMax)242 static 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) || defined(USE_BACKPORT)
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
IEqualizer_GetBand(SLEqualizerItf self,SLmilliHertz frequency,SLuint16 * pBand)286 static 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) || defined(USE_BACKPORT)
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
IEqualizer_GetCurrentPreset(SLEqualizerItf self,SLuint16 * pPreset)336 static 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) || defined(USE_BACKPORT)
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
IEqualizer_UsePreset(SLEqualizerItf self,SLuint16 index)374 static 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) || defined(USE_BACKPORT)
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
IEqualizer_GetNumberOfPresets(SLEqualizerItf self,SLuint16 * pNumPresets)407 static 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
IEqualizer_GetPresetName(SLEqualizerItf self,SLuint16 index,const SLchar ** ppName)425 static 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) || defined(USE_BACKPORT)
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
458 static 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
IEqualizer_init(void * self)474 void 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) || defined(USE_BACKPORT)
489 this->mBands = EqualizerBands;
490 this->mPresets = EqualizerPresets;
491 #endif
492 this->mBandLevelRangeMin = 0;
493 this->mBandLevelRangeMax = 0;
494 #if defined(ANDROID) && !defined(USE_BACKPORT)
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
IEqualizer_deinit(void * self)501 void IEqualizer_deinit(void *self)
502 {
503 #if defined(ANDROID) && !defined(USE_BACKPORT)
504 IEqualizer *this = (IEqualizer *) self;
505 // explicit destructor
506 this->mEqEffect.~sp();
507 #endif
508 }
509
IEqualizer_Expose(void * self)510 bool IEqualizer_Expose(void *self)
511 {
512 #if defined(ANDROID) && !defined(USE_BACKPORT)
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