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 <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         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 
    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         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 
    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 
    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 
    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 
    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 
    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 
    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