Home | History | Annotate | Download | only in itf
      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  */
     49 static inline bool NO_EQ(IEqualizer* v) {
     50     return (v->mEqEffect == 0);
     51 }
     52 #endif
     53 
     54 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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