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 */
NO_EQ(IEqualizer * v)49 static inline bool NO_EQ(IEqualizer* v) {
50 return (v->mEqEffect == 0);
51 }
52 #endif
53
54
IEqualizer_SetEnabled(SLEqualizerItf self,SLboolean enabled)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
IEqualizer_IsEnabled(SLEqualizerItf self,SLboolean * pEnabled)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
IEqualizer_GetNumberOfBands(SLEqualizerItf self,SLuint16 * pNumBands)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
IEqualizer_GetBandLevelRange(SLEqualizerItf self,SLmillibel * pMin,SLmillibel * pMax)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
IEqualizer_SetBandLevel(SLEqualizerItf self,SLuint16 band,SLmillibel level)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
IEqualizer_GetBandLevel(SLEqualizerItf self,SLuint16 band,SLmillibel * pLevel)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
IEqualizer_GetCenterFreq(SLEqualizerItf self,SLuint16 band,SLmilliHertz * pCenter)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
IEqualizer_GetBandFreqRange(SLEqualizerItf self,SLuint16 band,SLmilliHertz * pMin,SLmilliHertz * pMax)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
IEqualizer_GetBand(SLEqualizerItf self,SLmilliHertz frequency,SLuint16 * pBand)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
IEqualizer_GetCurrentPreset(SLEqualizerItf self,SLuint16 * pPreset)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
IEqualizer_UsePreset(SLEqualizerItf self,SLuint16 index)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
IEqualizer_GetNumberOfPresets(SLEqualizerItf self,SLuint16 * pNumPresets)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
IEqualizer_GetPresetName(SLEqualizerItf self,SLuint16 index,const SLchar ** ppName)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
IEqualizer_init(void * self)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
IEqualizer_deinit(void * self)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
IEqualizer_Expose(void * self)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