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, &center);
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