Home | History | Annotate | Download | only in libopensles
      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 
     18 #include "sles_allinclusive.h"
     19 #include "math.h"
     20 #include "utils/RefBase.h"
     21 
     22 
     23 static const int EQUALIZER_PARAM_SIZE_MAX = sizeof(effect_param_t) + 2 * sizeof(int32_t)
     24         + EFFECT_STRING_LEN_MAX;
     25 
     26 static const int BASSBOOST_PARAM_SIZE_MAX = sizeof(effect_param_t) + 2 * sizeof(int32_t);
     27 
     28 static const int VIRTUALIZER_PARAM_SIZE_MAX = sizeof(effect_param_t) + 2 * sizeof(int32_t);
     29 
     30 static const int ENVREVERB_PARAM_SIZE_MAX_SINGLE = sizeof(effect_param_t) + 2 * sizeof(int32_t);
     31 
     32 static const int ENVREVERB_PARAM_SIZE_MAX_ALL = sizeof(effect_param_t) + sizeof(int32_t)
     33         + sizeof(s_reverb_settings);
     34 
     35 static inline SLuint32 KEY_FROM_GUID(SLInterfaceID pUuid) {
     36     return pUuid->time_low;
     37 }
     38 
     39 
     40 //-----------------------------------------------------------------------------
     41 uint32_t eq_paramSize(int32_t param) {
     42     uint32_t size;
     43 
     44     switch (param) {
     45     case EQ_PARAM_NUM_BANDS:
     46     case EQ_PARAM_LEVEL_RANGE:
     47     case EQ_PARAM_CUR_PRESET:
     48     case EQ_PARAM_GET_NUM_OF_PRESETS:
     49         size = sizeof(int32_t);
     50         break;
     51     case EQ_PARAM_BAND_LEVEL:
     52     case EQ_PARAM_CENTER_FREQ:
     53     case EQ_PARAM_BAND_FREQ_RANGE:
     54     case EQ_PARAM_GET_BAND:
     55     case EQ_PARAM_GET_PRESET_NAME:
     56         size = 2 * sizeof(int32_t);
     57         break;
     58     default:
     59         size = 2 * sizeof(int32_t);
     60         SL_LOGE("Trying to use an unknown EQ parameter %d", param);
     61         break;
     62     }
     63     return size;
     64 }
     65 
     66 uint32_t eq_valueSize(int32_t param) {
     67     uint32_t size;
     68 
     69     switch (param) {
     70     case EQ_PARAM_NUM_BANDS:
     71     case EQ_PARAM_CUR_PRESET:
     72     case EQ_PARAM_GET_NUM_OF_PRESETS:
     73     case EQ_PARAM_BAND_LEVEL:
     74     case EQ_PARAM_GET_BAND:
     75         size = sizeof(int16_t);
     76         break;
     77     case EQ_PARAM_LEVEL_RANGE:
     78         size = 2 * sizeof(int16_t);
     79         break;
     80     case EQ_PARAM_CENTER_FREQ:
     81         size = sizeof(int32_t);
     82         break;
     83     case EQ_PARAM_BAND_FREQ_RANGE:
     84         size = 2 * sizeof(int32_t);
     85         break;
     86     case EQ_PARAM_GET_PRESET_NAME:
     87         size = EFFECT_STRING_LEN_MAX;
     88         break;
     89     default:
     90         size = sizeof(int32_t);
     91         SL_LOGE("Trying to access an unknown EQ parameter %d", param);
     92         break;
     93     }
     94     return size;
     95 }
     96 
     97 //-----------------------------------------------------------------------------
     98 /**
     99  * returns the size in bytes of the value of each bass boost parameter
    100  */
    101 uint32_t bb_valueSize(int32_t param) {
    102     uint32_t size;
    103 
    104     switch (param) {
    105     case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
    106         size = sizeof(int32_t);
    107         break;
    108     case BASSBOOST_PARAM_STRENGTH:
    109         size = sizeof(int16_t);
    110         break;
    111     default:
    112         size = sizeof(int32_t);
    113         SL_LOGE("Trying to access an unknown BassBoost parameter %d", param);
    114         break;
    115     }
    116 
    117     return size;
    118 }
    119 
    120 //-----------------------------------------------------------------------------
    121 /**
    122  * returns the size in bytes of the value of each virtualizer parameter
    123  */
    124 uint32_t virt_valueSize(int32_t param) {
    125     uint32_t size;
    126 
    127     switch (param) {
    128     case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
    129         size = sizeof(int32_t);
    130         break;
    131     case VIRTUALIZER_PARAM_STRENGTH:
    132         size = sizeof(int16_t);
    133         break;
    134     default:
    135         size = sizeof(int32_t);
    136         SL_LOGE("Trying to access an unknown Virtualizer parameter %d", param);
    137         break;
    138     }
    139 
    140     return size;
    141 }
    142 
    143 //-----------------------------------------------------------------------------
    144 /**
    145  * returns the size in bytes of the value of each environmental reverb parameter
    146  */
    147 uint32_t erev_valueSize(int32_t param) {
    148     uint32_t size;
    149 
    150     switch (param) {
    151     case REVERB_PARAM_ROOM_LEVEL:
    152     case REVERB_PARAM_ROOM_HF_LEVEL:
    153     case REVERB_PARAM_REFLECTIONS_LEVEL:
    154     case REVERB_PARAM_REVERB_LEVEL:
    155         size = sizeof(int16_t); // millibel
    156         break;
    157     case REVERB_PARAM_DECAY_TIME:
    158     case REVERB_PARAM_REFLECTIONS_DELAY:
    159     case REVERB_PARAM_REVERB_DELAY:
    160         size = sizeof(uint32_t); // milliseconds
    161         break;
    162     case REVERB_PARAM_DECAY_HF_RATIO:
    163     case REVERB_PARAM_DIFFUSION:
    164     case REVERB_PARAM_DENSITY:
    165         size = sizeof(int16_t); // permille
    166         break;
    167     case REVERB_PARAM_PROPERTIES:
    168         size = sizeof(s_reverb_settings); // struct of all reverb properties
    169         break;
    170     default:
    171         size = sizeof(int32_t);
    172         SL_LOGE("Trying to access an unknown Environmental Reverb parameter %d", param);
    173         break;
    174     }
    175 
    176     return size;
    177 }
    178 
    179 //-----------------------------------------------------------------------------
    180 android::status_t android_eq_getParam(android::sp<android::AudioEffect> pFx,
    181         int32_t param, int32_t param2, void *pValue)
    182 {
    183      android::status_t status;
    184      uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1];
    185      effect_param_t *p = (effect_param_t *)buf32;
    186 
    187      p->psize = eq_paramSize(param);
    188      *(int32_t *)p->data = param;
    189      if (p->psize == 2 * sizeof(int32_t)) {
    190          *((int32_t *)p->data + 1) = param2;
    191      }
    192      p->vsize = eq_valueSize(param);
    193      status = pFx->getParameter(p);
    194      if (android::NO_ERROR == status) {
    195          status = p->status;
    196          if (android::NO_ERROR == status) {
    197              memcpy(pValue, p->data + p->psize, p->vsize);
    198          }
    199      }
    200 
    201      return status;
    202  }
    203 
    204 
    205 //-----------------------------------------------------------------------------
    206 android::status_t android_eq_setParam(android::sp<android::AudioEffect> pFx,
    207         int32_t param, int32_t param2, void *pValue)
    208 {
    209     android::status_t status;
    210     uint32_t buf32[(EQUALIZER_PARAM_SIZE_MAX - 1) / sizeof(uint32_t) + 1];
    211     effect_param_t *p = (effect_param_t *)buf32;
    212 
    213     p->psize = eq_paramSize(param);
    214     *(int32_t *)p->data = param;
    215     if (p->psize == 2 * sizeof(int32_t)) {
    216         *((int32_t *)p->data + 1) = param2;
    217     }
    218     p->vsize = eq_valueSize(param);
    219     memcpy(p->data + p->psize, pValue, p->vsize);
    220     status = pFx->setParameter(p);
    221     if (android::NO_ERROR == status) {
    222         status = p->status;
    223     }
    224 
    225     return status;
    226 }
    227 
    228 //-----------------------------------------------------------------------------
    229 android::status_t android_bb_setParam(android::sp<android::AudioEffect> pFx,
    230         int32_t param, void *pValue) {
    231 
    232     return android_fx_setParam(pFx, param, BASSBOOST_PARAM_SIZE_MAX,
    233             pValue, bb_valueSize(param));
    234 }
    235 
    236 //-----------------------------------------------------------------------------
    237 android::status_t android_bb_getParam(android::sp<android::AudioEffect> pFx,
    238         int32_t param, void *pValue) {
    239 
    240     return android_fx_getParam(pFx, param, BASSBOOST_PARAM_SIZE_MAX,
    241             pValue, bb_valueSize(param));
    242 }
    243 
    244 //-----------------------------------------------------------------------------
    245 void android_bb_init(int sessionId, IBassBoost* ibb) {
    246     SL_LOGV("session %d", sessionId);
    247 
    248     if (!android_fx_initEffectObj(sessionId, ibb->mBassBoostEffect,
    249             &ibb->mBassBoostDescriptor.type))
    250     {
    251         SL_LOGE("BassBoost effect initialization failed");
    252         return;
    253     }
    254 
    255     // initialize strength
    256     int16_t strength;
    257     if (android::NO_ERROR == android_bb_getParam(ibb->mBassBoostEffect,
    258             BASSBOOST_PARAM_STRENGTH, &strength)) {
    259         ibb->mStrength = (SLpermille) strength;
    260     }
    261 }
    262 
    263 
    264 //-----------------------------------------------------------------------------
    265 void android_eq_init(int sessionId, IEqualizer* ieq) {
    266     SL_LOGV("android_eq_init on session %d", sessionId);
    267 
    268     if (!android_fx_initEffectObj(sessionId, ieq->mEqEffect, &ieq->mEqDescriptor.type)) {
    269         SL_LOGE("Equalizer effect initialization failed");
    270         return;
    271     }
    272 
    273     // initialize number of bands, band level range, and number of presets
    274     uint16_t num = 0;
    275     if (android::NO_ERROR == android_eq_getParam(ieq->mEqEffect, EQ_PARAM_NUM_BANDS, 0, &num)) {
    276         ieq->mNumBands = num;
    277     }
    278     int16_t range[2] = {0, 0};
    279     if (android::NO_ERROR == android_eq_getParam(ieq->mEqEffect, EQ_PARAM_LEVEL_RANGE, 0, range)) {
    280         ieq->mBandLevelRangeMin = range[0];
    281         ieq->mBandLevelRangeMax = range[1];
    282     }
    283 
    284     SL_LOGV(" EQ init: num bands = %u, band range=[%d %d]mB", num, range[0], range[1]);
    285 
    286     // FIXME don't store presets names, they can be queried each time they're needed
    287     // initialize preset number and names, store in IEngine
    288     uint16_t numPresets = 0;
    289     if (android::NO_ERROR == android_eq_getParam(ieq->mEqEffect,
    290             EQ_PARAM_GET_NUM_OF_PRESETS, 0, &numPresets)) {
    291         ieq->mThis->mEngine->mEqNumPresets = numPresets;
    292         ieq->mNumPresets = numPresets;
    293     }
    294 
    295     interface_lock_exclusive(ieq->mThis->mEngine);
    296     char name[EFFECT_STRING_LEN_MAX];
    297     if ((0 < numPresets) && (NULL == ieq->mThis->mEngine->mEqPresetNames)) {
    298         ieq->mThis->mEngine->mEqPresetNames = (char **)new char *[numPresets];
    299         for(uint32_t i = 0 ; i < numPresets ; i++) {
    300             if (android::NO_ERROR == android_eq_getParam(ieq->mEqEffect,
    301                     EQ_PARAM_GET_PRESET_NAME, i, name)) {
    302                 ieq->mThis->mEngine->mEqPresetNames[i] = new char[strlen(name) + 1];
    303                 strcpy(ieq->mThis->mEngine->mEqPresetNames[i], name);
    304                 SL_LOGV(" EQ init: presets = %u is %s", i, ieq->mThis->mEngine->mEqPresetNames[i]);
    305             }
    306         }
    307     }
    308     interface_unlock_exclusive(ieq->mThis->mEngine);
    309 
    310 #if 0
    311     // configure the EQ so it can easily be heard, for test only
    312     uint32_t freq = 1977;
    313     uint32_t frange[2];
    314     int16_t value = ap->mEqualizer.mBandLevelRangeMin;
    315     for(int32_t i=0 ; i< ap->mEqualizer.mNumBands ; i++) {
    316         android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, i, &value);
    317         // display EQ characteristics
    318         android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_CENTER_FREQ, i, &freq);
    319         android_eq_getParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_FREQ_RANGE, i, frange);
    320         SL_LOGV(" EQ init: band %d = %d - %d - %dHz", i, frange[0]/1000, freq/1000,
    321                 frange[1]/1000);
    322     }
    323     value = ap->mEqualizer.mBandLevelRangeMax;
    324     if (ap->mEqualizer.mNumBands > 2) {
    325         android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 2, &value);
    326     }
    327     if (ap->mEqualizer.mNumBands > 3) {
    328         android_eq_setParam(ap->mEqualizer.mEqEffect, EQ_PARAM_BAND_LEVEL, 3, &value);
    329     }
    330 
    331     ap->mEqualizer.mEqEffect->setEnabled(true);
    332 #endif
    333 }
    334 
    335 
    336 //-----------------------------------------------------------------------------
    337 void android_virt_init(int sessionId, IVirtualizer* ivi) {
    338     SL_LOGV("android_virt_init on session %d", sessionId);
    339 
    340     if (!android_fx_initEffectObj(sessionId, ivi->mVirtualizerEffect,
    341             &ivi->mVirtualizerDescriptor.type)) {
    342         SL_LOGE("Virtualizer effect initialization failed");
    343         return;
    344     }
    345 
    346     // initialize strength
    347     int16_t strength;
    348     if (android::NO_ERROR == android_virt_getParam(ivi->mVirtualizerEffect,
    349             VIRTUALIZER_PARAM_STRENGTH, &strength)) {
    350         ivi->mStrength = (SLpermille) strength;
    351     }
    352 }
    353 
    354 //-----------------------------------------------------------------------------
    355 android::status_t android_virt_setParam(android::sp<android::AudioEffect> pFx,
    356         int32_t param, void *pValue) {
    357 
    358     return android_fx_setParam(pFx, param, VIRTUALIZER_PARAM_SIZE_MAX,
    359             pValue, virt_valueSize(param));
    360 }
    361 
    362 //-----------------------------------------------------------------------------
    363 android::status_t android_virt_getParam(android::sp<android::AudioEffect> pFx,
    364         int32_t param, void *pValue) {
    365 
    366     return android_fx_getParam(pFx, param, VIRTUALIZER_PARAM_SIZE_MAX,
    367             pValue, virt_valueSize(param));
    368 }
    369 
    370 
    371 //-----------------------------------------------------------------------------
    372 void android_prev_init(IPresetReverb* ipr) {
    373     SL_LOGV("session is implicitly %d (aux effect)", android::AudioSystem::SESSION_OUTPUT_MIX);
    374 
    375     if (!android_fx_initEffectObj(android::AudioSystem::SESSION_OUTPUT_MIX /*sessionId*/,
    376             ipr->mPresetReverbEffect, &ipr->mPresetReverbDescriptor.type)) {
    377         SL_LOGE("PresetReverb effect initialization failed");
    378         return;
    379     }
    380 
    381     // initialize preset
    382     uint16_t preset;
    383     if (android::NO_ERROR == android_prev_getPreset(ipr->mPresetReverbEffect, &preset)) {
    384         ipr->mPreset = preset;
    385         // enable the effect is it has a effective preset loaded
    386         ipr->mPresetReverbEffect->setEnabled(SL_REVERBPRESET_NONE != preset);
    387     }
    388 }
    389 
    390 //-----------------------------------------------------------------------------
    391 android::status_t android_prev_setPreset(android::sp<android::AudioEffect> pFx, uint16_t preset) {
    392     android::status_t status = android_fx_setParam(pFx, REVERB_PARAM_PRESET, sizeof(uint16_t),
    393             &preset, sizeof(uint16_t));
    394     // enable the effect if the preset is different from SL_REVERBPRESET_NONE
    395     pFx->setEnabled(SL_REVERBPRESET_NONE != preset);
    396     return status;
    397 }
    398 
    399 //-----------------------------------------------------------------------------
    400 android::status_t android_prev_getPreset(android::sp<android::AudioEffect> pFx, uint16_t* preset) {
    401     return android_fx_getParam(pFx, REVERB_PARAM_PRESET, sizeof(uint16_t), preset,
    402             sizeof(uint16_t));
    403 }
    404 
    405 
    406 //-----------------------------------------------------------------------------
    407 void android_erev_init(IEnvironmentalReverb* ier) {
    408     SL_LOGV("session is implicitly %d (aux effect)", android::AudioSystem::SESSION_OUTPUT_MIX);
    409 
    410     if (!android_fx_initEffectObj(android::AudioSystem::SESSION_OUTPUT_MIX /*sessionId*/,
    411             ier->mEnvironmentalReverbEffect, &ier->mEnvironmentalReverbDescriptor.type)) {
    412         SL_LOGE("EnvironmentalReverb effect initialization failed");
    413         return;
    414     }
    415 
    416     // enable env reverb: other SL ES effects have an explicit SetEnabled() function, and the
    417     //  preset reverb state depends on the selected preset.
    418     ier->mEnvironmentalReverbEffect->setEnabled(true);
    419 
    420     // initialize reverb properties
    421     SLEnvironmentalReverbSettings properties;
    422     if (android::NO_ERROR == android_erev_getParam(ier->mEnvironmentalReverbEffect,
    423             REVERB_PARAM_PROPERTIES, &properties)) {
    424         ier->mProperties = properties;
    425     }
    426 }
    427 
    428 //-----------------------------------------------------------------------------
    429 android::status_t android_erev_setParam(android::sp<android::AudioEffect> pFx,
    430         int32_t param, void *pValue) {
    431 
    432     // given the size difference between a single reverb property and the whole set of reverb
    433     // properties, select which max size to pass to avoid allocating too much memory
    434     if (param == REVERB_PARAM_PROPERTIES) {
    435         return android_fx_setParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_ALL,
    436                 pValue, erev_valueSize(param));
    437     } else {
    438         return android_fx_setParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_SINGLE,
    439                 pValue, erev_valueSize(param));
    440     }
    441 }
    442 
    443 //-----------------------------------------------------------------------------
    444 android::status_t android_erev_getParam(android::sp<android::AudioEffect> pFx,
    445         int32_t param, void *pValue) {
    446 
    447     // given the size difference between a single reverb property and the whole set of reverb
    448     // properties, select which max size to pass to avoid allocating too much memory
    449     if (param == REVERB_PARAM_PROPERTIES) {
    450         return android_fx_getParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_ALL,
    451                 pValue, erev_valueSize(param));
    452     } else {
    453         return android_fx_getParam(pFx, param, ENVREVERB_PARAM_SIZE_MAX_SINGLE,
    454                 pValue, erev_valueSize(param));
    455     }
    456 }
    457 
    458 
    459 //-----------------------------------------------------------------------------
    460 android::status_t android_fxSend_attach(CAudioPlayer* ap, bool attach,
    461         android::sp<android::AudioEffect> pFx, SLmillibel sendLevel) {
    462 
    463     if (pFx == 0) {
    464         return android::INVALID_OPERATION;
    465     }
    466 
    467     if (NULL == ap->mAudioTrack) {
    468         // the player doesn't have an AudioTrack at the moment, so store this info to use it
    469         // when the AudioTrack becomes available
    470         if (attach) {
    471             ap->mAuxEffect = pFx;
    472         } else {
    473             ap->mAuxEffect.clear();
    474         }
    475         // we keep track of the send level, independently of the current audio player level
    476         ap->mAuxSendLevel = sendLevel - ap->mVolume.mLevel;
    477         return android::NO_ERROR;
    478     }
    479 
    480     if (attach) {
    481         android::status_t status = ap->mAudioTrack->attachAuxEffect(pFx->id());
    482         //SL_LOGV("attachAuxEffect(%d) returned %d", pFx->id(), status);
    483         if (android::NO_ERROR == status) {
    484             status =
    485                 ap->mAudioTrack->setAuxEffectSendLevel( sles_to_android_amplification(sendLevel) );
    486         }
    487         return status;
    488     } else {
    489         return ap->mAudioTrack->attachAuxEffect(0);
    490     }
    491 }
    492 
    493 //-----------------------------------------------------------------------------
    494 /**
    495  * pre-condition:
    496  *    ap != NULL
    497  *    ap->mOutputMix != NULL
    498  */
    499 SLresult android_fxSend_attachToAux(CAudioPlayer* ap, SLInterfaceID pUuid, SLboolean attach,
    500         SLmillibel sendLevel) {
    501     COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
    502     ssize_t index = outputMix->mAndroidEffect.mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
    503 
    504     if (0 > index) {
    505         SL_LOGE("invalid effect ID: no such effect attached to the OutputMix");
    506         return SL_RESULT_PARAMETER_INVALID;
    507     }
    508 
    509     android::AudioEffect* pFx = outputMix->mAndroidEffect.mEffects->valueAt(index);
    510     if (NULL == pFx) {
    511         return SL_RESULT_RESOURCE_ERROR;
    512     }
    513     if (android::NO_ERROR == android_fxSend_attach( ap, (bool) attach, pFx, sendLevel) ) {
    514         return SL_RESULT_SUCCESS;
    515     } else {
    516         return SL_RESULT_RESOURCE_ERROR;
    517     }
    518 
    519 }
    520 
    521 //-----------------------------------------------------------------------------
    522 android::status_t android_fxSend_setSendLevel(CAudioPlayer* ap, SLmillibel sendLevel) {
    523     // we keep track of the send level, independently of the current audio player level
    524     ap->mAuxSendLevel = sendLevel - ap->mVolume.mLevel;
    525 
    526     if (NULL == ap->mAudioTrack) {
    527         return android::NO_ERROR;
    528     }
    529 
    530     return ap->mAudioTrack->setAuxEffectSendLevel( sles_to_android_amplification(sendLevel) );
    531 }
    532 
    533 //-----------------------------------------------------------------------------
    534 android::status_t android_fx_setParam(android::sp<android::AudioEffect> pFx,
    535         int32_t param, uint32_t paramSizeMax, void *pValue, uint32_t valueSize)
    536 {
    537 
    538     android::status_t status;
    539     uint32_t buf32[(paramSizeMax - 1) / sizeof(uint32_t) + 1];
    540     effect_param_t *p = (effect_param_t *)buf32;
    541 
    542     p->psize = sizeof(int32_t);
    543     *(int32_t *)p->data = param;
    544     p->vsize = valueSize;
    545     memcpy(p->data + p->psize, pValue, p->vsize);
    546     status = pFx->setParameter(p);
    547     if (android::NO_ERROR == status) {
    548         status = p->status;
    549     }
    550     return status;
    551 }
    552 
    553 
    554 //-----------------------------------------------------------------------------
    555 android::status_t android_fx_getParam(android::sp<android::AudioEffect> pFx,
    556         int32_t param, uint32_t paramSizeMax, void *pValue, uint32_t valueSize)
    557 {
    558     android::status_t status;
    559     uint32_t buf32[(paramSizeMax - 1) / sizeof(uint32_t) + 1];
    560     effect_param_t *p = (effect_param_t *)buf32;
    561 
    562     p->psize = sizeof(int32_t);
    563     *(int32_t *)p->data = param;
    564     p->vsize = valueSize;
    565     status = pFx->getParameter(p);
    566     if (android::NO_ERROR == status) {
    567         status = p->status;
    568         if (android::NO_ERROR == status) {
    569             memcpy(pValue, p->data + p->psize, p->vsize);
    570         }
    571     }
    572 
    573     return status;
    574 }
    575 
    576 
    577 //-----------------------------------------------------------------------------
    578 SLresult android_fx_statusToResult(android::status_t status) {
    579 
    580     if ((android::INVALID_OPERATION == status) || (android::DEAD_OBJECT == status)) {
    581         return SL_RESULT_CONTROL_LOST;
    582     } else {
    583         return SL_RESULT_SUCCESS;
    584     }
    585 }
    586 
    587 
    588 //-----------------------------------------------------------------------------
    589 bool android_fx_initEffectObj(int sessionId, android::sp<android::AudioEffect>& effect,
    590         const effect_uuid_t *type) {
    591     //SL_LOGV("android_fx_initEffectObj on session %d", sessionId);
    592 
    593     effect = new android::AudioEffect(type, EFFECT_UUID_NULL,
    594             0,// priority
    595             0,// effect callback
    596             0,// callback data
    597             sessionId,// session ID
    598             0 );// output
    599 
    600     android::status_t status = effect->initCheck();
    601     if (android::NO_ERROR != status) {
    602         effect.clear();
    603         SL_LOGE("Effect initCheck() returned %d", status);
    604         return false;
    605     }
    606 
    607     return true;
    608 }
    609 
    610 
    611 //-----------------------------------------------------------------------------
    612 bool android_fx_initEffectDescriptor(const SLInterfaceID effectId,
    613         effect_descriptor_t* fxDescrLoc) {
    614     uint32_t numEffects = 0;
    615     effect_descriptor_t descriptor;
    616     bool foundEffect = false;
    617 
    618     // any effects?
    619     android::status_t res = android::AudioEffect::queryNumberEffects(&numEffects);
    620     if (android::NO_ERROR != res) {
    621         SL_LOGE("unable to find any effects.");
    622         goto effectError;
    623     }
    624 
    625     // request effect in the effects?
    626     for (uint32_t i=0 ; i < numEffects ; i++) {
    627         res = android::AudioEffect::queryEffect(i, &descriptor);
    628         if ((android::NO_ERROR == res) &&
    629                 (0 == memcmp(effectId, &descriptor.type, sizeof(effect_uuid_t)))) {
    630             SL_LOGV("found effect %d %s", i, descriptor.name);
    631             foundEffect = true;
    632             break;
    633         }
    634     }
    635     if (foundEffect) {
    636         memcpy(fxDescrLoc, &descriptor, sizeof(effect_descriptor_t));
    637     } else {
    638         SL_LOGE("unable to find an implementation for the requested effect.");
    639         goto effectError;
    640     }
    641 
    642     return true;
    643 
    644 effectError:
    645     // the requested effect wasn't found
    646     memset(fxDescrLoc, 0, sizeof(effect_descriptor_t));
    647 
    648     return false;
    649 }
    650 
    651 //-----------------------------------------------------------------------------
    652 SLresult android_genericFx_queryNumEffects(SLuint32 *pNumSupportedAudioEffects) {
    653 
    654     if (NULL == pNumSupportedAudioEffects) {
    655         return SL_RESULT_PARAMETER_INVALID;
    656     }
    657 
    658     android::status_t status =
    659             android::AudioEffect::queryNumberEffects((uint32_t*)pNumSupportedAudioEffects);
    660 
    661     SLresult result = SL_RESULT_SUCCESS;
    662     switch(status) {
    663         case android::NO_ERROR:
    664             result = SL_RESULT_SUCCESS;
    665             break;
    666         case android::PERMISSION_DENIED:
    667             result = SL_RESULT_PERMISSION_DENIED;
    668             break;
    669         case android::NO_INIT:
    670             result = SL_RESULT_RESOURCE_ERROR;
    671             break;
    672         case android::BAD_VALUE:
    673             result = SL_RESULT_PARAMETER_INVALID;
    674             break;
    675         default:
    676             result = SL_RESULT_INTERNAL_ERROR;
    677             SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
    678             break;
    679     }
    680     return result;
    681 }
    682 
    683 
    684 //-----------------------------------------------------------------------------
    685 SLresult android_genericFx_queryEffect(SLuint32 index, effect_descriptor_t* pDescriptor) {
    686 
    687     if (NULL == pDescriptor) {
    688         return SL_RESULT_PARAMETER_INVALID;
    689     }
    690 
    691     android::status_t status =
    692                 android::AudioEffect::queryEffect(index, pDescriptor);
    693 
    694     SLresult result = SL_RESULT_SUCCESS;
    695     if (android::NO_ERROR != status) {
    696         switch(status) {
    697         case android::PERMISSION_DENIED:
    698             result = SL_RESULT_PERMISSION_DENIED;
    699             break;
    700         case android::NO_INIT:
    701         case android::INVALID_OPERATION:
    702             result = SL_RESULT_RESOURCE_ERROR;
    703             break;
    704         case android::BAD_VALUE:
    705             result = SL_RESULT_PARAMETER_INVALID;
    706             break;
    707         default:
    708             result = SL_RESULT_INTERNAL_ERROR;
    709             SL_LOGE("received invalid status %d from AudioEffect::queryNumberEffects()", status);
    710             break;
    711         }
    712         // an error occurred, reset the effect descriptor
    713         memset(pDescriptor, 0, sizeof(effect_descriptor_t));
    714     }
    715 
    716     return result;
    717 }
    718 
    719 
    720 //-----------------------------------------------------------------------------
    721 SLresult android_genericFx_createEffect(IAndroidEffect* iae, SLInterfaceID pUuid, int sessionId) {
    722 
    723     SLresult result = SL_RESULT_SUCCESS;
    724 
    725     // does this effect already exist?
    726     if (0 <= iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid))) {
    727         return result;
    728     }
    729 
    730     // create new effect
    731     android::AudioEffect* pFx = new android::AudioEffect(
    732             NULL, // not using type to create effect
    733             (const effect_uuid_t*)pUuid,
    734             0,// priority
    735             0,// effect callback
    736             0,// callback data
    737             sessionId,
    738             0 );// output
    739 
    740     // verify effect was successfully created before storing it
    741     android::status_t status = pFx->initCheck();
    742     if (android::NO_ERROR != status) {
    743         SL_LOGE("AudioEffect initCheck() returned %d, effect will not be stored", status);
    744         delete pFx;
    745         result = SL_RESULT_RESOURCE_ERROR;
    746     } else {
    747         SL_LOGV("AudioEffect successfully created on session %d", sessionId);
    748         iae->mEffects->add(KEY_FROM_GUID(pUuid), pFx);
    749     }
    750 
    751     return result;
    752 }
    753 
    754 
    755 //-----------------------------------------------------------------------------
    756 SLresult android_genericFx_releaseEffect(IAndroidEffect* iae, SLInterfaceID pUuid) {
    757 
    758     ssize_t index = iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
    759 
    760     if (0 > index) {
    761         return SL_RESULT_PARAMETER_INVALID;
    762     } else {
    763         android::AudioEffect* pFx = iae->mEffects->valueAt(index);
    764         delete pFx;
    765         iae->mEffects->removeItem(index);
    766         return SL_RESULT_SUCCESS;
    767     }
    768 }
    769 
    770 
    771 //-----------------------------------------------------------------------------
    772 SLresult android_genericFx_setEnabled(IAndroidEffect* iae, SLInterfaceID pUuid, SLboolean enabled) {
    773 
    774     ssize_t index = iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
    775 
    776     if (0 > index) {
    777         return SL_RESULT_PARAMETER_INVALID;
    778     } else {
    779         android::AudioEffect* pFx = iae->mEffects->valueAt(index);
    780         android::status_t status = pFx->setEnabled(SL_BOOLEAN_TRUE == enabled);
    781         return android_fx_statusToResult(status);
    782     }
    783 }
    784 
    785 
    786 //-----------------------------------------------------------------------------
    787 SLresult android_genericFx_isEnabled(IAndroidEffect* iae, SLInterfaceID pUuid, SLboolean *pEnabled)
    788 {
    789     ssize_t index = iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
    790 
    791     if (0 > index) {
    792         return SL_RESULT_PARAMETER_INVALID;
    793     } else {
    794         android::AudioEffect* pFx = iae->mEffects->valueAt(index);
    795         *pEnabled = (SLboolean) pFx->getEnabled();
    796         return SL_RESULT_SUCCESS;
    797     }
    798 }
    799 
    800 
    801 //-----------------------------------------------------------------------------
    802 SLresult android_genericFx_sendCommand(IAndroidEffect* iae, SLInterfaceID pUuid,
    803         SLuint32 command, SLuint32 commandSize, void* pCommandData,
    804         SLuint32 *replySize, void *pReplyData) {
    805 
    806     ssize_t index = iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid));
    807 
    808     if (0 > index) {
    809         return SL_RESULT_PARAMETER_INVALID;
    810     } else {
    811         android::AudioEffect* pFx = iae->mEffects->valueAt(index);
    812         android::status_t status = pFx->command(
    813                 (uint32_t) command,
    814                 (uint32_t) commandSize,
    815                 pCommandData,
    816                 (uint32_t*)replySize,
    817                 pReplyData);
    818         if (android::BAD_VALUE == status) {
    819                 return SL_RESULT_PARAMETER_INVALID;
    820         } else {
    821             return SL_RESULT_SUCCESS;
    822         }
    823     }
    824 }
    825 
    826 //-----------------------------------------------------------------------------
    827 /**
    828  * returns true if the given effect id is present in the AndroidEffect interface
    829  */
    830 bool android_genericFx_hasEffect(IAndroidEffect* iae, SLInterfaceID pUuid) {
    831     return( 0 <= iae->mEffects->indexOfKey(KEY_FROM_GUID(pUuid)));
    832 }
    833 
    834