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 <system/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 #if !defined(ANDROID)
89 SLboolean enabled = thiz->mEnabled;
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 *pPreset = (SLuint16) preset;
365 #endif
366
367 }
368
369 SL_LEAVE_INTERFACE
370 }
371
372
IEqualizer_UsePreset(SLEqualizerItf self,SLuint16 index)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
IEqualizer_GetNumberOfPresets(SLEqualizerItf self,SLuint16 * pNumPresets)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
IEqualizer_GetPresetName(SLEqualizerItf self,SLuint16 index,const SLchar ** ppName)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
IEqualizer_init(void * self)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
IEqualizer_deinit(void * self)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
IEqualizer_Expose(void * self)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