Home | History | Annotate | Download | only in testlibs
      1 /*
      2  * Copyright (C) 2008 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 #define LOG_TAG "EffectReverb"
     18 //#define LOG_NDEBUG 0
     19 #include <cutils/log.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include <stdbool.h>
     23 #include "EffectReverb.h"
     24 #include "EffectsMath.h"
     25 
     26 // effect_handle_t interface implementation for reverb effect
     27 const struct effect_interface_s gReverbInterface = {
     28         Reverb_Process,
     29         Reverb_Command,
     30         Reverb_GetDescriptor,
     31         NULL
     32 };
     33 
     34 // Google auxiliary environmental reverb UUID: 1f0ae2e0-4ef7-11df-bc09-0002a5d5c51b
     35 static const effect_descriptor_t gAuxEnvReverbDescriptor = {
     36         {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
     37         {0x1f0ae2e0, 0x4ef7, 0x11df, 0xbc09, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
     38         EFFECT_CONTROL_API_VERSION,
     39         // flags other than EFFECT_FLAG_TYPE_AUXILIARY set for test purpose
     40         EFFECT_FLAG_TYPE_AUXILIARY | EFFECT_FLAG_DEVICE_IND | EFFECT_FLAG_AUDIO_MODE_IND,
     41         0, // TODO
     42         33,
     43         "Aux Environmental Reverb",
     44         "The Android Open Source Project"
     45 };
     46 
     47 // Google insert environmental reverb UUID: aa476040-6342-11df-91a4-0002a5d5c51b
     48 static const effect_descriptor_t gInsertEnvReverbDescriptor = {
     49         {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
     50         {0xaa476040, 0x6342, 0x11df, 0x91a4, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
     51         EFFECT_CONTROL_API_VERSION,
     52         EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
     53         0, // TODO
     54         33,
     55         "Insert Environmental reverb",
     56         "The Android Open Source Project"
     57 };
     58 
     59 // Google auxiliary preset reverb UUID: 63909320-53a6-11df-bdbd-0002a5d5c51b
     60 static const effect_descriptor_t gAuxPresetReverbDescriptor = {
     61         {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
     62         {0x63909320, 0x53a6, 0x11df, 0xbdbd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
     63         EFFECT_CONTROL_API_VERSION,
     64         EFFECT_FLAG_TYPE_AUXILIARY,
     65         0, // TODO
     66         33,
     67         "Aux Preset Reverb",
     68         "The Android Open Source Project"
     69 };
     70 
     71 // Google insert preset reverb UUID: d93dc6a0-6342-11df-b128-0002a5d5c51b
     72 static const effect_descriptor_t gInsertPresetReverbDescriptor = {
     73         {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
     74         {0xd93dc6a0, 0x6342, 0x11df, 0xb128, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
     75         EFFECT_CONTROL_API_VERSION,
     76         EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
     77         0, // TODO
     78         33,
     79         "Insert Preset Reverb",
     80         "The Android Open Source Project"
     81 };
     82 
     83 // gDescriptors contains pointers to all defined effect descriptor in this library
     84 static const effect_descriptor_t * const gDescriptors[] = {
     85         &gAuxEnvReverbDescriptor,
     86         &gInsertEnvReverbDescriptor,
     87         &gAuxPresetReverbDescriptor,
     88         &gInsertPresetReverbDescriptor
     89 };
     90 
     91 /*----------------------------------------------------------------------------
     92  * Effect API implementation
     93  *--------------------------------------------------------------------------*/
     94 
     95 /*--- Effect Library Interface Implementation ---*/
     96 
     97 int EffectQueryNumberEffects(uint32_t *pNumEffects) {
     98     *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
     99     return 0;
    100 }
    101 
    102 int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
    103     if (pDescriptor == NULL) {
    104         return -EINVAL;
    105     }
    106     if (index >= sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)) {
    107         return -EINVAL;
    108     }
    109     memcpy(pDescriptor, gDescriptors[index],
    110             sizeof(effect_descriptor_t));
    111     return 0;
    112 }
    113 
    114 int EffectCreate(const effect_uuid_t *uuid,
    115         int32_t sessionId,
    116         int32_t ioId,
    117         effect_handle_t *pHandle) {
    118     int ret;
    119     int i;
    120     reverb_module_t *module;
    121     const effect_descriptor_t *desc;
    122     int aux = 0;
    123     int preset = 0;
    124 
    125     ALOGV("EffectLibCreateEffect start");
    126 
    127     if (pHandle == NULL || uuid == NULL) {
    128         return -EINVAL;
    129     }
    130 
    131     for (i = 0; gDescriptors[i] != NULL; i++) {
    132         desc = gDescriptors[i];
    133         if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
    134                 == 0) {
    135             break;
    136         }
    137     }
    138 
    139     if (gDescriptors[i] == NULL) {
    140         return -ENOENT;
    141     }
    142 
    143     module = malloc(sizeof(reverb_module_t));
    144 
    145     module->itfe = &gReverbInterface;
    146 
    147     module->context.mState = REVERB_STATE_UNINITIALIZED;
    148 
    149     if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
    150         preset = 1;
    151     }
    152     if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
    153         aux = 1;
    154     }
    155     ret = Reverb_Init(module, aux, preset);
    156     if (ret < 0) {
    157         ALOGW("EffectLibCreateEffect() init failed");
    158         free(module);
    159         return ret;
    160     }
    161 
    162     *pHandle = (effect_handle_t) module;
    163 
    164     module->context.mState = REVERB_STATE_INITIALIZED;
    165 
    166     ALOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));
    167 
    168     return 0;
    169 }
    170 
    171 int EffectRelease(effect_handle_t handle) {
    172     reverb_module_t *pRvbModule = (reverb_module_t *)handle;
    173 
    174     ALOGV("EffectLibReleaseEffect %p", handle);
    175     if (handle == NULL) {
    176         return -EINVAL;
    177     }
    178 
    179     pRvbModule->context.mState = REVERB_STATE_UNINITIALIZED;
    180 
    181     free(pRvbModule);
    182     return 0;
    183 }
    184 
    185 int EffectGetDescriptor(const effect_uuid_t *uuid,
    186                         effect_descriptor_t *pDescriptor) {
    187     int i;
    188     int length = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
    189 
    190     if (pDescriptor == NULL || uuid == NULL){
    191         ALOGV("EffectGetDescriptor() called with NULL pointer");
    192         return -EINVAL;
    193     }
    194 
    195     for (i = 0; i < length; i++) {
    196         if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
    197             memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t));
    198             ALOGV("EffectGetDescriptor - UUID matched Reverb type %d, UUID = %x",
    199                  i, gDescriptors[i]->uuid.timeLow);
    200             return 0;
    201         }
    202     }
    203 
    204     return -EINVAL;
    205 } /* end EffectGetDescriptor */
    206 
    207 /*--- Effect Control Interface Implementation ---*/
    208 
    209 static int Reverb_Process(effect_handle_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
    210     reverb_object_t *pReverb;
    211     int16_t *pSrc, *pDst;
    212     reverb_module_t *pRvbModule = (reverb_module_t *)self;
    213 
    214     if (pRvbModule == NULL) {
    215         return -EINVAL;
    216     }
    217 
    218     if (inBuffer == NULL || inBuffer->raw == NULL ||
    219         outBuffer == NULL || outBuffer->raw == NULL ||
    220         inBuffer->frameCount != outBuffer->frameCount) {
    221         return -EINVAL;
    222     }
    223 
    224     pReverb = (reverb_object_t*) &pRvbModule->context;
    225 
    226     if (pReverb->mState == REVERB_STATE_UNINITIALIZED) {
    227         return -EINVAL;
    228     }
    229     if (pReverb->mState == REVERB_STATE_INITIALIZED) {
    230         return -ENODATA;
    231     }
    232 
    233     //if bypassed or the preset forces the signal to be completely dry
    234     if (pReverb->m_bBypass != 0) {
    235         if (inBuffer->raw != outBuffer->raw) {
    236             int16_t smp;
    237             pSrc = inBuffer->s16;
    238             pDst = outBuffer->s16;
    239             size_t count = inBuffer->frameCount;
    240             if (pRvbModule->config.inputCfg.channels == pRvbModule->config.outputCfg.channels) {
    241                 count *= 2;
    242                 while (count--) {
    243                     *pDst++ = *pSrc++;
    244                 }
    245             } else {
    246                 while (count--) {
    247                     smp = *pSrc++;
    248                     *pDst++ = smp;
    249                     *pDst++ = smp;
    250                 }
    251             }
    252         }
    253         return 0;
    254     }
    255 
    256     if (pReverb->m_nNextRoom != pReverb->m_nCurrentRoom) {
    257         ReverbUpdateRoom(pReverb, true);
    258     }
    259 
    260     pSrc = inBuffer->s16;
    261     pDst = outBuffer->s16;
    262     size_t numSamples = outBuffer->frameCount;
    263     while (numSamples) {
    264         uint32_t processedSamples;
    265         if (numSamples > (uint32_t) pReverb->m_nUpdatePeriodInSamples) {
    266             processedSamples = (uint32_t) pReverb->m_nUpdatePeriodInSamples;
    267         } else {
    268             processedSamples = numSamples;
    269         }
    270 
    271         /* increment update counter */
    272         pReverb->m_nUpdateCounter += (int16_t) processedSamples;
    273         /* check if update counter needs to be reset */
    274         if (pReverb->m_nUpdateCounter >= pReverb->m_nUpdatePeriodInSamples) {
    275             /* update interval has elapsed, so reset counter */
    276             pReverb->m_nUpdateCounter -= pReverb->m_nUpdatePeriodInSamples;
    277             ReverbUpdateXfade(pReverb, pReverb->m_nUpdatePeriodInSamples);
    278 
    279         } /* end if m_nUpdateCounter >= update interval */
    280 
    281         Reverb(pReverb, processedSamples, pDst, pSrc);
    282 
    283         numSamples -= processedSamples;
    284         if (pReverb->m_Aux) {
    285             pSrc += processedSamples;
    286         } else {
    287             pSrc += processedSamples * NUM_OUTPUT_CHANNELS;
    288         }
    289         pDst += processedSamples * NUM_OUTPUT_CHANNELS;
    290     }
    291 
    292     return 0;
    293 }
    294 
    295 
    296 static int Reverb_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
    297         void *pCmdData, uint32_t *replySize, void *pReplyData) {
    298     reverb_module_t *pRvbModule = (reverb_module_t *) self;
    299     reverb_object_t *pReverb;
    300     int retsize;
    301 
    302     if (pRvbModule == NULL ||
    303             pRvbModule->context.mState == REVERB_STATE_UNINITIALIZED) {
    304         return -EINVAL;
    305     }
    306 
    307     pReverb = (reverb_object_t*) &pRvbModule->context;
    308 
    309     ALOGV("Reverb_Command command %d cmdSize %d",cmdCode, cmdSize);
    310 
    311     switch (cmdCode) {
    312     case EFFECT_CMD_INIT:
    313         if (pReplyData == NULL || *replySize != sizeof(int)) {
    314             return -EINVAL;
    315         }
    316         *(int *) pReplyData = Reverb_Init(pRvbModule, pReverb->m_Aux, pReverb->m_Preset);
    317         if (*(int *) pReplyData == 0) {
    318             pRvbModule->context.mState = REVERB_STATE_INITIALIZED;
    319         }
    320         break;
    321     case EFFECT_CMD_SET_CONFIG:
    322         if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
    323                 || pReplyData == NULL || *replySize != sizeof(int)) {
    324             return -EINVAL;
    325         }
    326         *(int *) pReplyData = Reverb_setConfig(pRvbModule,
    327                 (effect_config_t *)pCmdData, false);
    328         break;
    329     case EFFECT_CMD_GET_CONFIG:
    330         if (pReplyData == NULL || *replySize != sizeof(effect_config_t)) {
    331             return -EINVAL;
    332         }
    333         Reverb_getConfig(pRvbModule, (effect_config_t *) pCmdData);
    334         break;
    335     case EFFECT_CMD_RESET:
    336         Reverb_Reset(pReverb, false);
    337         break;
    338     case EFFECT_CMD_GET_PARAM:
    339         ALOGV("Reverb_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p",pCmdData, *replySize, pReplyData);
    340 
    341         if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
    342             pReplyData == NULL || *replySize < (int) sizeof(effect_param_t)) {
    343             return -EINVAL;
    344         }
    345         effect_param_t *rep = (effect_param_t *) pReplyData;
    346         memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
    347         ALOGV("Reverb_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",*(int32_t *)rep->data, rep->vsize);
    348         rep->status = Reverb_getParameter(pReverb, *(int32_t *)rep->data, &rep->vsize,
    349                 rep->data + sizeof(int32_t));
    350         *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize;
    351         break;
    352     case EFFECT_CMD_SET_PARAM:
    353         ALOGV("Reverb_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
    354                 cmdSize, pCmdData, *replySize, pReplyData);
    355         if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
    356                 || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
    357             return -EINVAL;
    358         }
    359         effect_param_t *cmd = (effect_param_t *) pCmdData;
    360         *(int *)pReplyData = Reverb_setParameter(pReverb, *(int32_t *)cmd->data,
    361                 cmd->vsize, cmd->data + sizeof(int32_t));
    362         break;
    363     case EFFECT_CMD_ENABLE:
    364         if (pReplyData == NULL || *replySize != sizeof(int)) {
    365             return -EINVAL;
    366         }
    367         if (pReverb->mState != REVERB_STATE_INITIALIZED) {
    368             return -ENOSYS;
    369         }
    370         pReverb->mState = REVERB_STATE_ACTIVE;
    371         ALOGV("EFFECT_CMD_ENABLE() OK");
    372         *(int *)pReplyData = 0;
    373         break;
    374     case EFFECT_CMD_DISABLE:
    375         if (pReplyData == NULL || *replySize != sizeof(int)) {
    376             return -EINVAL;
    377         }
    378         if (pReverb->mState != REVERB_STATE_ACTIVE) {
    379             return -ENOSYS;
    380         }
    381         pReverb->mState = REVERB_STATE_INITIALIZED;
    382         ALOGV("EFFECT_CMD_DISABLE() OK");
    383         *(int *)pReplyData = 0;
    384         break;
    385     case EFFECT_CMD_SET_DEVICE:
    386         if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
    387             return -EINVAL;
    388         }
    389         ALOGV("Reverb_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData);
    390         break;
    391     case EFFECT_CMD_SET_VOLUME: {
    392         // audio output is always stereo => 2 channel volumes
    393         if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t) * 2) {
    394             return -EINVAL;
    395         }
    396         float left = (float)(*(uint32_t *)pCmdData) / (1 << 24);
    397         float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24);
    398         ALOGV("Reverb_Command EFFECT_CMD_SET_VOLUME: left %f, right %f ", left, right);
    399         break;
    400         }
    401     case EFFECT_CMD_SET_AUDIO_MODE:
    402         if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
    403             return -EINVAL;
    404         }
    405         ALOGV("Reverb_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
    406         break;
    407     default:
    408         ALOGW("Reverb_Command invalid command %d",cmdCode);
    409         return -EINVAL;
    410     }
    411 
    412     return 0;
    413 }
    414 
    415 int Reverb_GetDescriptor(effect_handle_t   self,
    416                                     effect_descriptor_t *pDescriptor)
    417 {
    418     reverb_module_t *pRvbModule = (reverb_module_t *) self;
    419     reverb_object_t *pReverb;
    420     const effect_descriptor_t *desc;
    421 
    422     if (pRvbModule == NULL ||
    423             pRvbModule->context.mState == REVERB_STATE_UNINITIALIZED) {
    424         return -EINVAL;
    425     }
    426 
    427     pReverb = (reverb_object_t*) &pRvbModule->context;
    428 
    429     if (pReverb->m_Aux) {
    430         if (pReverb->m_Preset) {
    431             desc = &gAuxPresetReverbDescriptor;
    432         } else {
    433             desc = &gAuxEnvReverbDescriptor;
    434         }
    435     } else {
    436         if (pReverb->m_Preset) {
    437             desc = &gInsertPresetReverbDescriptor;
    438         } else {
    439             desc = &gInsertEnvReverbDescriptor;
    440         }
    441     }
    442 
    443     memcpy(pDescriptor, desc, sizeof(effect_descriptor_t));
    444 
    445     return 0;
    446 }   /* end Reverb_getDescriptor */
    447 
    448 /*----------------------------------------------------------------------------
    449  * Reverb internal functions
    450  *--------------------------------------------------------------------------*/
    451 
    452 /*----------------------------------------------------------------------------
    453  * Reverb_Init()
    454  *----------------------------------------------------------------------------
    455  * Purpose:
    456  * Initialize reverb context and apply default parameters
    457  *
    458  * Inputs:
    459  *  pRvbModule    - pointer to reverb effect module
    460  *  aux           - indicates if the reverb is used as auxiliary (1) or insert (0)
    461  *  preset        - indicates if the reverb is used in preset (1) or environmental (0) mode
    462  *
    463  * Outputs:
    464  *
    465  * Side Effects:
    466  *
    467  *----------------------------------------------------------------------------
    468  */
    469 
    470 int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset) {
    471     int ret;
    472 
    473     ALOGV("Reverb_Init module %p, aux: %d, preset: %d", pRvbModule,aux, preset);
    474 
    475     memset(&pRvbModule->context, 0, sizeof(reverb_object_t));
    476 
    477     pRvbModule->context.m_Aux = (uint16_t)aux;
    478     pRvbModule->context.m_Preset = (uint16_t)preset;
    479 
    480     pRvbModule->config.inputCfg.samplingRate = 44100;
    481     if (aux) {
    482         pRvbModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_MONO;
    483     } else {
    484         pRvbModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
    485     }
    486     pRvbModule->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
    487     pRvbModule->config.inputCfg.bufferProvider.getBuffer = NULL;
    488     pRvbModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
    489     pRvbModule->config.inputCfg.bufferProvider.cookie = NULL;
    490     pRvbModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
    491     pRvbModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
    492     pRvbModule->config.outputCfg.samplingRate = 44100;
    493     pRvbModule->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
    494     pRvbModule->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
    495     pRvbModule->config.outputCfg.bufferProvider.getBuffer = NULL;
    496     pRvbModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
    497     pRvbModule->config.outputCfg.bufferProvider.cookie = NULL;
    498     pRvbModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
    499     pRvbModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;
    500 
    501     ret = Reverb_setConfig(pRvbModule, &pRvbModule->config, true);
    502     if (ret < 0) {
    503         ALOGV("Reverb_Init error %d on module %p", ret, pRvbModule);
    504     }
    505 
    506     return ret;
    507 }
    508 
    509 /*----------------------------------------------------------------------------
    510  * Reverb_setConfig()
    511  *----------------------------------------------------------------------------
    512  * Purpose:
    513  *  Set input and output audio configuration.
    514  *
    515  * Inputs:
    516  *  pRvbModule    - pointer to reverb effect module
    517  *  pConfig       - pointer to effect_config_t structure containing input
    518  *              and output audio parameters configuration
    519  *  init          - true if called from init function
    520  * Outputs:
    521  *
    522  * Side Effects:
    523  *
    524  *----------------------------------------------------------------------------
    525  */
    526 
    527 int Reverb_setConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig,
    528         bool init) {
    529     reverb_object_t *pReverb = &pRvbModule->context;
    530     int bufferSizeInSamples;
    531     int updatePeriodInSamples;
    532     int xfadePeriodInSamples;
    533 
    534     // Check configuration compatibility with build options
    535     if (pConfig->inputCfg.samplingRate
    536         != pConfig->outputCfg.samplingRate
    537         || pConfig->outputCfg.channels != OUTPUT_CHANNELS
    538         || pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT
    539         || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
    540         ALOGV("Reverb_setConfig invalid config");
    541         return -EINVAL;
    542     }
    543     if ((pReverb->m_Aux && (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_MONO)) ||
    544         (!pReverb->m_Aux && (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO))) {
    545         ALOGV("Reverb_setConfig invalid config");
    546         return -EINVAL;
    547     }
    548 
    549     memcpy(&pRvbModule->config, pConfig, sizeof(effect_config_t));
    550 
    551     pReverb->m_nSamplingRate = pRvbModule->config.outputCfg.samplingRate;
    552 
    553     switch (pReverb->m_nSamplingRate) {
    554     case 8000:
    555         pReverb->m_nUpdatePeriodInBits = 5;
    556         bufferSizeInSamples = 4096;
    557         pReverb->m_nCosWT_5KHz = -23170;
    558         break;
    559     case 16000:
    560         pReverb->m_nUpdatePeriodInBits = 6;
    561         bufferSizeInSamples = 8192;
    562         pReverb->m_nCosWT_5KHz = -12540;
    563         break;
    564     case 22050:
    565         pReverb->m_nUpdatePeriodInBits = 7;
    566         bufferSizeInSamples = 8192;
    567         pReverb->m_nCosWT_5KHz = 4768;
    568         break;
    569     case 32000:
    570         pReverb->m_nUpdatePeriodInBits = 7;
    571         bufferSizeInSamples = 16384;
    572         pReverb->m_nCosWT_5KHz = 18205;
    573         break;
    574     case 44100:
    575         pReverb->m_nUpdatePeriodInBits = 8;
    576         bufferSizeInSamples = 16384;
    577         pReverb->m_nCosWT_5KHz = 24799;
    578         break;
    579     case 48000:
    580         pReverb->m_nUpdatePeriodInBits = 8;
    581         bufferSizeInSamples = 16384;
    582         pReverb->m_nCosWT_5KHz = 25997;
    583         break;
    584     default:
    585         ALOGV("Reverb_setConfig invalid sampling rate %d", pReverb->m_nSamplingRate);
    586         return -EINVAL;
    587     }
    588 
    589     // Define a mask for circular addressing, so that array index
    590     // can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1)
    591     // The buffer size MUST be a power of two
    592     pReverb->m_nBufferMask = (int32_t) (bufferSizeInSamples - 1);
    593     /* reverb parameters are updated every 2^(pReverb->m_nUpdatePeriodInBits) samples */
    594     updatePeriodInSamples = (int32_t) (0x1L << pReverb->m_nUpdatePeriodInBits);
    595     /*
    596      calculate the update counter by bitwise ANDING with this value to
    597      generate a 2^n modulo value
    598      */
    599     pReverb->m_nUpdatePeriodInSamples = (int32_t) updatePeriodInSamples;
    600 
    601     xfadePeriodInSamples = (int32_t) (REVERB_XFADE_PERIOD_IN_SECONDS
    602             * (double) pReverb->m_nSamplingRate);
    603 
    604     // set xfade parameters
    605     pReverb->m_nPhaseIncrement
    606             = (int16_t) (65536 / ((int16_t) xfadePeriodInSamples
    607                     / (int16_t) updatePeriodInSamples));
    608 
    609     if (init) {
    610         ReverbReadInPresets(pReverb);
    611 
    612         // for debugging purposes, allow noise generator
    613         pReverb->m_bUseNoise = true;
    614 
    615         // for debugging purposes, allow bypass
    616         pReverb->m_bBypass = 0;
    617 
    618         pReverb->m_nNextRoom = 1;
    619 
    620         pReverb->m_nNoise = (int16_t) 0xABCD;
    621     }
    622 
    623     Reverb_Reset(pReverb, init);
    624 
    625     return 0;
    626 }
    627 
    628 /*----------------------------------------------------------------------------
    629  * Reverb_getConfig()
    630  *----------------------------------------------------------------------------
    631  * Purpose:
    632  *  Get input and output audio configuration.
    633  *
    634  * Inputs:
    635  *  pRvbModule    - pointer to reverb effect module
    636  *  pConfig       - pointer to effect_config_t structure containing input
    637  *              and output audio parameters configuration
    638  * Outputs:
    639  *
    640  * Side Effects:
    641  *
    642  *----------------------------------------------------------------------------
    643  */
    644 
    645 void Reverb_getConfig(reverb_module_t *pRvbModule, effect_config_t *pConfig)
    646 {
    647     memcpy(pConfig, &pRvbModule->config, sizeof(effect_config_t));
    648 }
    649 
    650 /*----------------------------------------------------------------------------
    651  * Reverb_Reset()
    652  *----------------------------------------------------------------------------
    653  * Purpose:
    654  *  Reset internal states and clear delay lines.
    655  *
    656  * Inputs:
    657  *  pReverb    - pointer to reverb context
    658  *  init       - true if called from init function
    659  *
    660  * Outputs:
    661  *
    662  * Side Effects:
    663  *
    664  *----------------------------------------------------------------------------
    665  */
    666 
    667 void Reverb_Reset(reverb_object_t *pReverb, bool init) {
    668     int bufferSizeInSamples = (int32_t) (pReverb->m_nBufferMask + 1);
    669     int maxApSamples;
    670     int maxDelaySamples;
    671     int maxEarlySamples;
    672     int ap1In;
    673     int delay0In;
    674     int delay1In;
    675     int32_t i;
    676     uint16_t nOffset;
    677 
    678     maxApSamples = ((int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16);
    679     maxDelaySamples = ((int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
    680             >> 16);
    681     maxEarlySamples = ((int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
    682             >> 16);
    683 
    684     ap1In = (AP0_IN + maxApSamples + GUARD);
    685     delay0In = (ap1In + maxApSamples + GUARD);
    686     delay1In = (delay0In + maxDelaySamples + GUARD);
    687     // Define the max offsets for the end points of each section
    688     // i.e., we don't expect a given section's taps to go beyond
    689     // the following limits
    690 
    691     pReverb->m_nEarly0in = (delay1In + maxDelaySamples + GUARD);
    692     pReverb->m_nEarly1in = (pReverb->m_nEarly0in + maxEarlySamples + GUARD);
    693 
    694     pReverb->m_sAp0.m_zApIn = AP0_IN;
    695 
    696     pReverb->m_zD0In = delay0In;
    697 
    698     pReverb->m_sAp1.m_zApIn = ap1In;
    699 
    700     pReverb->m_zD1In = delay1In;
    701 
    702     pReverb->m_zOutLpfL = 0;
    703     pReverb->m_zOutLpfR = 0;
    704 
    705     pReverb->m_nRevFbkR = 0;
    706     pReverb->m_nRevFbkL = 0;
    707 
    708     // set base index into circular buffer
    709     pReverb->m_nBaseIndex = 0;
    710 
    711     // clear the reverb delay line
    712     for (i = 0; i < bufferSizeInSamples; i++) {
    713         pReverb->m_nDelayLine[i] = 0;
    714     }
    715 
    716     ReverbUpdateRoom(pReverb, init);
    717 
    718     pReverb->m_nUpdateCounter = 0;
    719 
    720     pReverb->m_nPhase = -32768;
    721 
    722     pReverb->m_nSin = 0;
    723     pReverb->m_nCos = 0;
    724     pReverb->m_nSinIncrement = 0;
    725     pReverb->m_nCosIncrement = 0;
    726 
    727     // set delay tap lengths
    728     nOffset = ReverbCalculateNoise(pReverb);
    729 
    730     pReverb->m_zD1Cross = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
    731             + nOffset;
    732 
    733     nOffset = ReverbCalculateNoise(pReverb);
    734 
    735     pReverb->m_zD0Cross = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
    736             - nOffset;
    737 
    738     nOffset = ReverbCalculateNoise(pReverb);
    739 
    740     pReverb->m_zD0Self = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
    741             - nOffset;
    742 
    743     nOffset = ReverbCalculateNoise(pReverb);
    744 
    745     pReverb->m_zD1Self = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
    746             + nOffset;
    747 }
    748 
    749 /*----------------------------------------------------------------------------
    750  * Reverb_getParameter()
    751  *----------------------------------------------------------------------------
    752  * Purpose:
    753  * Get a Reverb parameter
    754  *
    755  * Inputs:
    756  *  pReverb       - handle to instance data
    757  *  param         - parameter
    758  *  pValue        - pointer to variable to hold retrieved value
    759  *  pSize         - pointer to value size: maximum size as input
    760  *
    761  * Outputs:
    762  *  *pValue updated with parameter value
    763  *  *pSize updated with actual value size
    764  *
    765  *
    766  * Side Effects:
    767  *
    768  *----------------------------------------------------------------------------
    769  */
    770 int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize,
    771         void *pValue) {
    772     int32_t *pValue32;
    773     int16_t *pValue16;
    774     t_reverb_settings *pProperties;
    775     int32_t i;
    776     int32_t temp;
    777     int32_t temp2;
    778     size_t size;
    779 
    780     if (pReverb->m_Preset) {
    781         if (param != REVERB_PARAM_PRESET || *pSize < sizeof(int16_t)) {
    782             return -EINVAL;
    783         }
    784         size = sizeof(int16_t);
    785         pValue16 = (int16_t *)pValue;
    786         // REVERB_PRESET_NONE is mapped to bypass
    787         if (pReverb->m_bBypass != 0) {
    788             *pValue16 = (int16_t)REVERB_PRESET_NONE;
    789         } else {
    790             *pValue16 = (int16_t)(pReverb->m_nNextRoom + 1);
    791         }
    792         ALOGV("get REVERB_PARAM_PRESET, preset %d", *pValue16);
    793     } else {
    794         switch (param) {
    795         case REVERB_PARAM_ROOM_LEVEL:
    796         case REVERB_PARAM_ROOM_HF_LEVEL:
    797         case REVERB_PARAM_DECAY_HF_RATIO:
    798         case REVERB_PARAM_REFLECTIONS_LEVEL:
    799         case REVERB_PARAM_REVERB_LEVEL:
    800         case REVERB_PARAM_DIFFUSION:
    801         case REVERB_PARAM_DENSITY:
    802             size = sizeof(int16_t);
    803             break;
    804 
    805         case REVERB_PARAM_BYPASS:
    806         case REVERB_PARAM_DECAY_TIME:
    807         case REVERB_PARAM_REFLECTIONS_DELAY:
    808         case REVERB_PARAM_REVERB_DELAY:
    809             size = sizeof(int32_t);
    810             break;
    811 
    812         case REVERB_PARAM_PROPERTIES:
    813             size = sizeof(t_reverb_settings);
    814             break;
    815 
    816         default:
    817             return -EINVAL;
    818         }
    819 
    820         if (*pSize < size) {
    821             return -EINVAL;
    822         }
    823 
    824         pValue32 = (int32_t *) pValue;
    825         pValue16 = (int16_t *) pValue;
    826         pProperties = (t_reverb_settings *) pValue;
    827 
    828         switch (param) {
    829         case REVERB_PARAM_BYPASS:
    830             *pValue32 = (int32_t) pReverb->m_bBypass;
    831             break;
    832 
    833         case REVERB_PARAM_PROPERTIES:
    834             pValue16 = &pProperties->roomLevel;
    835             /* FALL THROUGH */
    836 
    837         case REVERB_PARAM_ROOM_LEVEL:
    838             // Convert m_nRoomLpfFwd to millibels
    839             temp = (pReverb->m_nRoomLpfFwd << 15)
    840                     / (32767 - pReverb->m_nRoomLpfFbk);
    841             *pValue16 = Effects_Linear16ToMillibels(temp);
    842 
    843             ALOGV("get REVERB_PARAM_ROOM_LEVEL %d, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", *pValue16, temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
    844 
    845             if (param == REVERB_PARAM_ROOM_LEVEL) {
    846                 break;
    847             }
    848             pValue16 = &pProperties->roomHFLevel;
    849             /* FALL THROUGH */
    850 
    851         case REVERB_PARAM_ROOM_HF_LEVEL:
    852             // The ratio between linear gain at 0Hz and at 5000Hz for the room low pass is:
    853             // (1 + a1) / sqrt(a1^2 + 2*C*a1 + 1) where:
    854             // - a1 is minus the LP feedback gain: -pReverb->m_nRoomLpfFbk
    855             // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz
    856 
    857             temp = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFbk);
    858             ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 %d", temp);
    859             temp2 = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nCosWT_5KHz)
    860                     << 1;
    861             ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, 2 Cos a1 %d", temp2);
    862             temp = 32767 + temp - temp2;
    863             ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 + 2 Cos a1 + 1 %d", temp);
    864             temp = Effects_Sqrt(temp) * 181;
    865             ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, SQRT(a1^2 + 2 Cos a1 + 1) %d", temp);
    866             temp = ((32767 - pReverb->m_nRoomLpfFbk) << 15) / temp;
    867 
    868             ALOGV("get REVERB_PARAM_ROOM_HF_LEVEL, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
    869 
    870             *pValue16 = Effects_Linear16ToMillibels(temp);
    871 
    872             if (param == REVERB_PARAM_ROOM_HF_LEVEL) {
    873                 break;
    874             }
    875             pValue32 = (int32_t *)&pProperties->decayTime;
    876             /* FALL THROUGH */
    877 
    878         case REVERB_PARAM_DECAY_TIME:
    879             // Calculate reverb feedback path gain
    880             temp = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);
    881             temp = Effects_Linear16ToMillibels(temp);
    882 
    883             // Calculate decay time: g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time
    884             temp = (-6000 * pReverb->m_nLateDelay) / temp;
    885 
    886             // Convert samples to ms
    887             *pValue32 = (temp * 1000) / pReverb->m_nSamplingRate;
    888 
    889             ALOGV("get REVERB_PARAM_DECAY_TIME, samples %d, ms %d", temp, *pValue32);
    890 
    891             if (param == REVERB_PARAM_DECAY_TIME) {
    892                 break;
    893             }
    894             pValue16 = &pProperties->decayHFRatio;
    895             /* FALL THROUGH */
    896 
    897         case REVERB_PARAM_DECAY_HF_RATIO:
    898             // If r is the decay HF ratio  (r = REVERB_PARAM_DECAY_HF_RATIO/1000) we have:
    899             //       DT_5000Hz = DT_0Hz * r
    900             //  and  G_5000Hz = -6000 * d / DT_5000Hz and G_0Hz = -6000 * d / DT_0Hz in millibels so :
    901             // r = G_0Hz/G_5000Hz in millibels
    902             // The linear gain at 5000Hz is b0 / sqrt(a1^2 + 2*C*a1 + 1) where:
    903             // - a1 is minus the LP feedback gain: -pReverb->m_nRvbLpfFbk
    904             // - b0 is the LP forward gain: pReverb->m_nRvbLpfFwd
    905             // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz
    906             if (pReverb->m_nRvbLpfFbk == 0) {
    907                 *pValue16 = 1000;
    908                 ALOGV("get REVERB_PARAM_DECAY_HF_RATIO, pReverb->m_nRvbLpfFbk == 0, ratio %d", *pValue16);
    909             } else {
    910                 temp = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFbk);
    911                 temp2 = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nCosWT_5KHz)
    912                         << 1;
    913                 temp = 32767 + temp - temp2;
    914                 temp = Effects_Sqrt(temp) * 181;
    915                 temp = (pReverb->m_nRvbLpfFwd << 15) / temp;
    916                 // The linear gain at 0Hz is b0 / (a1 + 1)
    917                 temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767
    918                         - pReverb->m_nRvbLpfFbk);
    919 
    920                 temp = Effects_Linear16ToMillibels(temp);
    921                 temp2 = Effects_Linear16ToMillibels(temp2);
    922                 ALOGV("get REVERB_PARAM_DECAY_HF_RATIO, gain 5KHz %d mB, gain DC %d mB", temp, temp2);
    923 
    924                 if (temp == 0)
    925                     temp = 1;
    926                 temp = (int16_t) ((1000 * temp2) / temp);
    927                 if (temp > 1000)
    928                     temp = 1000;
    929 
    930                 *pValue16 = temp;
    931                 ALOGV("get REVERB_PARAM_DECAY_HF_RATIO, ratio %d", *pValue16);
    932             }
    933 
    934             if (param == REVERB_PARAM_DECAY_HF_RATIO) {
    935                 break;
    936             }
    937             pValue16 = &pProperties->reflectionsLevel;
    938             /* FALL THROUGH */
    939 
    940         case REVERB_PARAM_REFLECTIONS_LEVEL:
    941             *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nEarlyGain);
    942 
    943             ALOGV("get REVERB_PARAM_REFLECTIONS_LEVEL, %d", *pValue16);
    944             if (param == REVERB_PARAM_REFLECTIONS_LEVEL) {
    945                 break;
    946             }
    947             pValue32 = (int32_t *)&pProperties->reflectionsDelay;
    948             /* FALL THROUGH */
    949 
    950         case REVERB_PARAM_REFLECTIONS_DELAY:
    951             // convert samples to ms
    952             *pValue32 = (pReverb->m_nEarlyDelay * 1000) / pReverb->m_nSamplingRate;
    953 
    954             ALOGV("get REVERB_PARAM_REFLECTIONS_DELAY, samples %d, ms %d", pReverb->m_nEarlyDelay, *pValue32);
    955 
    956             if (param == REVERB_PARAM_REFLECTIONS_DELAY) {
    957                 break;
    958             }
    959             pValue16 = &pProperties->reverbLevel;
    960             /* FALL THROUGH */
    961 
    962         case REVERB_PARAM_REVERB_LEVEL:
    963             // Convert linear gain to millibels
    964             *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nLateGain << 2);
    965 
    966             ALOGV("get REVERB_PARAM_REVERB_LEVEL %d", *pValue16);
    967 
    968             if (param == REVERB_PARAM_REVERB_LEVEL) {
    969                 break;
    970             }
    971             pValue32 = (int32_t *)&pProperties->reverbDelay;
    972             /* FALL THROUGH */
    973 
    974         case REVERB_PARAM_REVERB_DELAY:
    975             // convert samples to ms
    976             *pValue32 = (pReverb->m_nLateDelay * 1000) / pReverb->m_nSamplingRate;
    977 
    978             ALOGV("get REVERB_PARAM_REVERB_DELAY, samples %d, ms %d", pReverb->m_nLateDelay, *pValue32);
    979 
    980             if (param == REVERB_PARAM_REVERB_DELAY) {
    981                 break;
    982             }
    983             pValue16 = &pProperties->diffusion;
    984             /* FALL THROUGH */
    985 
    986         case REVERB_PARAM_DIFFUSION:
    987             temp = (int16_t) ((1000 * (pReverb->m_sAp0.m_nApGain - AP0_GAIN_BASE))
    988                     / AP0_GAIN_RANGE);
    989 
    990             if (temp < 0)
    991                 temp = 0;
    992             if (temp > 1000)
    993                 temp = 1000;
    994 
    995             *pValue16 = temp;
    996             ALOGV("get REVERB_PARAM_DIFFUSION, %d, AP0 gain %d", *pValue16, pReverb->m_sAp0.m_nApGain);
    997 
    998             if (param == REVERB_PARAM_DIFFUSION) {
    999                 break;
   1000             }
   1001             pValue16 = &pProperties->density;
   1002             /* FALL THROUGH */
   1003 
   1004         case REVERB_PARAM_DENSITY:
   1005             // Calculate AP delay in time units
   1006             temp = ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) << 16)
   1007                     / pReverb->m_nSamplingRate;
   1008 
   1009             temp = (int16_t) ((1000 * (temp - AP0_TIME_BASE)) / AP0_TIME_RANGE);
   1010 
   1011             if (temp < 0)
   1012                 temp = 0;
   1013             if (temp > 1000)
   1014                 temp = 1000;
   1015 
   1016             *pValue16 = temp;
   1017 
   1018             ALOGV("get REVERB_PARAM_DENSITY, %d, AP0 delay smps %d", *pValue16, pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn);
   1019             break;
   1020 
   1021         default:
   1022             break;
   1023         }
   1024     }
   1025 
   1026     *pSize = size;
   1027 
   1028     ALOGV("Reverb_getParameter, context %p, param %d, value %d",
   1029             pReverb, param, *(int *)pValue);
   1030 
   1031     return 0;
   1032 } /* end Reverb_getParameter */
   1033 
   1034 /*----------------------------------------------------------------------------
   1035  * Reverb_setParameter()
   1036  *----------------------------------------------------------------------------
   1037  * Purpose:
   1038  * Set a Reverb parameter
   1039  *
   1040  * Inputs:
   1041  *  pReverb       - handle to instance data
   1042  *  param         - parameter
   1043  *  pValue        - pointer to parameter value
   1044  *  size          - value size
   1045  *
   1046  * Outputs:
   1047  *
   1048  *
   1049  * Side Effects:
   1050  *
   1051  *----------------------------------------------------------------------------
   1052  */
   1053 int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size,
   1054         void *pValue) {
   1055     int32_t value32;
   1056     int16_t value16;
   1057     t_reverb_settings *pProperties;
   1058     int32_t i;
   1059     int32_t temp;
   1060     int32_t temp2;
   1061     reverb_preset_t *pPreset;
   1062     int maxSamples;
   1063     int32_t averageDelay;
   1064     size_t paramSize;
   1065 
   1066     ALOGV("Reverb_setParameter, context %p, param %d, value16 %d, value32 %d",
   1067             pReverb, param, *(int16_t *)pValue, *(int32_t *)pValue);
   1068 
   1069     if (pReverb->m_Preset) {
   1070         if (param != REVERB_PARAM_PRESET || size != sizeof(int16_t)) {
   1071             return -EINVAL;
   1072         }
   1073         value16 = *(int16_t *)pValue;
   1074         ALOGV("set REVERB_PARAM_PRESET, preset %d", value16);
   1075         if (value16 < REVERB_PRESET_NONE || value16 > REVERB_PRESET_PLATE) {
   1076             return -EINVAL;
   1077         }
   1078         // REVERB_PRESET_NONE is mapped to bypass
   1079         if (value16 == REVERB_PRESET_NONE) {
   1080             pReverb->m_bBypass = 1;
   1081         } else {
   1082             pReverb->m_bBypass = 0;
   1083             pReverb->m_nNextRoom = value16 - 1;
   1084         }
   1085     } else {
   1086         switch (param) {
   1087         case REVERB_PARAM_ROOM_LEVEL:
   1088         case REVERB_PARAM_ROOM_HF_LEVEL:
   1089         case REVERB_PARAM_DECAY_HF_RATIO:
   1090         case REVERB_PARAM_REFLECTIONS_LEVEL:
   1091         case REVERB_PARAM_REVERB_LEVEL:
   1092         case REVERB_PARAM_DIFFUSION:
   1093         case REVERB_PARAM_DENSITY:
   1094             paramSize = sizeof(int16_t);
   1095             break;
   1096 
   1097         case REVERB_PARAM_BYPASS:
   1098         case REVERB_PARAM_DECAY_TIME:
   1099         case REVERB_PARAM_REFLECTIONS_DELAY:
   1100         case REVERB_PARAM_REVERB_DELAY:
   1101             paramSize = sizeof(int32_t);
   1102             break;
   1103 
   1104         case REVERB_PARAM_PROPERTIES:
   1105             paramSize = sizeof(t_reverb_settings);
   1106             break;
   1107 
   1108         default:
   1109             return -EINVAL;
   1110         }
   1111 
   1112         if (size != paramSize) {
   1113             return -EINVAL;
   1114         }
   1115 
   1116         if (paramSize == sizeof(int16_t)) {
   1117             value16 = *(int16_t *) pValue;
   1118         } else if (paramSize == sizeof(int32_t)) {
   1119             value32 = *(int32_t *) pValue;
   1120         } else {
   1121             pProperties = (t_reverb_settings *) pValue;
   1122         }
   1123 
   1124         pPreset = &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom];
   1125 
   1126         switch (param) {
   1127         case REVERB_PARAM_BYPASS:
   1128             pReverb->m_bBypass = (uint16_t)value32;
   1129             break;
   1130 
   1131         case REVERB_PARAM_PROPERTIES:
   1132             value16 = pProperties->roomLevel;
   1133             /* FALL THROUGH */
   1134 
   1135         case REVERB_PARAM_ROOM_LEVEL:
   1136             // Convert millibels to linear 16 bit signed => m_nRoomLpfFwd
   1137             if (value16 > 0)
   1138                 return -EINVAL;
   1139 
   1140             temp = Effects_MillibelsToLinear16(value16);
   1141 
   1142             pReverb->m_nRoomLpfFwd
   1143                     = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRoomLpfFbk));
   1144 
   1145             ALOGV("REVERB_PARAM_ROOM_LEVEL, gain %d, new m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
   1146             if (param == REVERB_PARAM_ROOM_LEVEL)
   1147                 break;
   1148             value16 = pProperties->roomHFLevel;
   1149             /* FALL THROUGH */
   1150 
   1151         case REVERB_PARAM_ROOM_HF_LEVEL:
   1152 
   1153             // Limit to 0 , -40dB range because of low pass implementation
   1154             if (value16 > 0 || value16 < -4000)
   1155                 return -EINVAL;
   1156             // Convert attenuation @ 5000H expressed in millibels to => m_nRoomLpfFbk
   1157             // m_nRoomLpfFbk is -a1 where a1 is the solution of:
   1158             // a1^2 + 2*(C-dG^2)/(1-dG^2)*a1 + 1 = 0 where:
   1159             // - C is cos(2*pi*5000/Fs) (pReverb->m_nCosWT_5KHz)
   1160             // - dG is G0/Gf (G0 is the linear gain at DC and Gf is the wanted gain at 5000Hz)
   1161 
   1162             // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged
   1163             // while changing HF level
   1164             temp2 = (pReverb->m_nRoomLpfFwd << 15) / (32767
   1165                     - pReverb->m_nRoomLpfFbk);
   1166             if (value16 == 0) {
   1167                 pReverb->m_nRoomLpfFbk = 0;
   1168             } else {
   1169                 int32_t dG2, b, delta;
   1170 
   1171                 // dG^2
   1172                 temp = Effects_MillibelsToLinear16(value16);
   1173                 ALOGV("REVERB_PARAM_ROOM_HF_LEVEL, HF gain %d", temp);
   1174                 temp = (1 << 30) / temp;
   1175                 ALOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain %d", temp);
   1176                 dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
   1177                 ALOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain ^ 2 %d", dG2);
   1178                 // b = 2*(C-dG^2)/(1-dG^2)
   1179                 b = (int32_t) ((((int64_t) 1 << (15 + 1))
   1180                         * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2))
   1181                         / ((int64_t) 32767 - (int64_t) dG2));
   1182 
   1183                 // delta = b^2 - 4
   1184                 delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15
   1185                         + 2)));
   1186 
   1187                 ALOGV_IF(delta > (1<<30), " delta overflow %d", delta);
   1188 
   1189                 ALOGV("REVERB_PARAM_ROOM_HF_LEVEL, dG2 %d, b %d, delta %d, m_nCosWT_5KHz %d", dG2, b, delta, pReverb->m_nCosWT_5KHz);
   1190                 // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2
   1191                 pReverb->m_nRoomLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;
   1192             }
   1193             ALOGV("REVERB_PARAM_ROOM_HF_LEVEL, olg DC gain %d new m_nRoomLpfFbk %d, old m_nRoomLpfFwd %d",
   1194                     temp2, pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFwd);
   1195 
   1196             pReverb->m_nRoomLpfFwd
   1197                     = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRoomLpfFbk));
   1198             ALOGV("REVERB_PARAM_ROOM_HF_LEVEL, new m_nRoomLpfFwd %d", pReverb->m_nRoomLpfFwd);
   1199 
   1200             if (param == REVERB_PARAM_ROOM_HF_LEVEL)
   1201                 break;
   1202             value32 = pProperties->decayTime;
   1203             /* FALL THROUGH */
   1204 
   1205         case REVERB_PARAM_DECAY_TIME:
   1206 
   1207             // Convert milliseconds to => m_nRvbLpfFwd (function of m_nRvbLpfFbk)
   1208             // convert ms to samples
   1209             value32 = (value32 * pReverb->m_nSamplingRate) / 1000;
   1210 
   1211             // calculate valid decay time range as a function of current reverb delay and
   1212             // max feed back gain. Min value <=> -40dB in one pass, Max value <=> feedback gain = -1 dB
   1213             // Calculate attenuation for each round in late reverb given a total attenuation of -6000 millibels.
   1214             // g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time
   1215             averageDelay = pReverb->m_nLateDelay - pReverb->m_nMaxExcursion;
   1216             averageDelay += ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn)
   1217                     + (pReverb->m_sAp1.m_zApOut - pReverb->m_sAp1.m_zApIn)) >> 1;
   1218 
   1219             temp = (-6000 * averageDelay) / value32;
   1220             ALOGV("REVERB_PARAM_DECAY_TIME, delay smps %d, DT smps %d, gain mB %d",averageDelay, value32, temp);
   1221             if (temp < -4000 || temp > -100)
   1222                 return -EINVAL;
   1223 
   1224             // calculate low pass gain by adding reverb input attenuation (pReverb->m_nLateGain) and substrating output
   1225             // xfade and sum gain (max +9dB)
   1226             temp -= Effects_Linear16ToMillibels(pReverb->m_nLateGain) + 900;
   1227             temp = Effects_MillibelsToLinear16(temp);
   1228 
   1229             // DC gain (temp) = b0 / (1 + a1) = pReverb->m_nRvbLpfFwd / (32767 - pReverb->m_nRvbLpfFbk)
   1230             pReverb->m_nRvbLpfFwd
   1231                     = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRvbLpfFbk));
   1232 
   1233             ALOGV("REVERB_PARAM_DECAY_TIME, gain %d, new m_nRvbLpfFwd %d, old m_nRvbLpfFbk %d, reverb gain %d", temp, pReverb->m_nRvbLpfFwd, pReverb->m_nRvbLpfFbk, Effects_Linear16ToMillibels(pReverb->m_nLateGain));
   1234 
   1235             if (param == REVERB_PARAM_DECAY_TIME)
   1236                 break;
   1237             value16 = pProperties->decayHFRatio;
   1238             /* FALL THROUGH */
   1239 
   1240         case REVERB_PARAM_DECAY_HF_RATIO:
   1241 
   1242             // We limit max value to 1000 because reverb filter is lowpass only
   1243             if (value16 < 100 || value16 > 1000)
   1244                 return -EINVAL;
   1245             // Convert per mille to => m_nLpfFwd, m_nLpfFbk
   1246 
   1247             // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged
   1248             // while changing HF level
   1249             temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);
   1250 
   1251             if (value16 == 1000) {
   1252                 pReverb->m_nRvbLpfFbk = 0;
   1253             } else {
   1254                 int32_t dG2, b, delta;
   1255 
   1256                 temp = Effects_Linear16ToMillibels(temp2);
   1257                 // G_5000Hz = G_DC * (1000/REVERB_PARAM_DECAY_HF_RATIO) in millibels
   1258 
   1259                 value32 = ((int32_t) 1000 << 15) / (int32_t) value16;
   1260                 ALOGV("REVERB_PARAM_DECAY_HF_RATIO, DC gain %d, DC gain mB %d, 1000/R %d", temp2, temp, value32);
   1261 
   1262                 temp = (int32_t) (((int64_t) temp * (int64_t) value32) >> 15);
   1263 
   1264                 if (temp < -4000) {
   1265                     ALOGV("REVERB_PARAM_DECAY_HF_RATIO HF gain overflow %d mB", temp);
   1266                     temp = -4000;
   1267                 }
   1268 
   1269                 temp = Effects_MillibelsToLinear16(temp);
   1270                 ALOGV("REVERB_PARAM_DECAY_HF_RATIO, HF gain %d", temp);
   1271                 // dG^2
   1272                 temp = (temp2 << 15) / temp;
   1273                 dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
   1274 
   1275                 // b = 2*(C-dG^2)/(1-dG^2)
   1276                 b = (int32_t) ((((int64_t) 1 << (15 + 1))
   1277                         * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2))
   1278                         / ((int64_t) 32767 - (int64_t) dG2));
   1279 
   1280                 // delta = b^2 - 4
   1281                 delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15
   1282                         + 2)));
   1283 
   1284                 // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2
   1285                 pReverb->m_nRvbLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;
   1286 
   1287                 ALOGV("REVERB_PARAM_DECAY_HF_RATIO, dG2 %d, b %d, delta %d", dG2, b, delta);
   1288 
   1289             }
   1290 
   1291             ALOGV("REVERB_PARAM_DECAY_HF_RATIO, gain %d, m_nRvbLpfFbk %d, m_nRvbLpfFwd %d", temp2, pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFwd);
   1292 
   1293             pReverb->m_nRvbLpfFwd
   1294                     = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRvbLpfFbk));
   1295 
   1296             if (param == REVERB_PARAM_DECAY_HF_RATIO)
   1297                 break;
   1298             value16 = pProperties->reflectionsLevel;
   1299             /* FALL THROUGH */
   1300 
   1301         case REVERB_PARAM_REFLECTIONS_LEVEL:
   1302             // We limit max value to 0 because gain is limited to 0dB
   1303             if (value16 > 0 || value16 < -6000)
   1304                 return -EINVAL;
   1305 
   1306             // Convert millibels to linear 16 bit signed and recompute m_sEarlyL.m_nGain[i] and m_sEarlyR.m_nGain[i].
   1307             value16 = Effects_MillibelsToLinear16(value16);
   1308             for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
   1309                 pReverb->m_sEarlyL.m_nGain[i]
   1310                         = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],value16);
   1311                 pReverb->m_sEarlyR.m_nGain[i]
   1312                         = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],value16);
   1313             }
   1314             pReverb->m_nEarlyGain = value16;
   1315             ALOGV("REVERB_PARAM_REFLECTIONS_LEVEL, m_nEarlyGain %d", pReverb->m_nEarlyGain);
   1316 
   1317             if (param == REVERB_PARAM_REFLECTIONS_LEVEL)
   1318                 break;
   1319             value32 = pProperties->reflectionsDelay;
   1320             /* FALL THROUGH */
   1321 
   1322         case REVERB_PARAM_REFLECTIONS_DELAY:
   1323             // We limit max value MAX_EARLY_TIME
   1324             // convert ms to time units
   1325             temp = (value32 * 65536) / 1000;
   1326             if (temp < 0 || temp > MAX_EARLY_TIME)
   1327                 return -EINVAL;
   1328 
   1329             maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
   1330                     >> 16;
   1331             temp = (temp * pReverb->m_nSamplingRate) >> 16;
   1332             for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
   1333                 temp2 = temp + (((int32_t) pPreset->m_sEarlyL.m_zDelay[i]
   1334                         * pReverb->m_nSamplingRate) >> 16);
   1335                 if (temp2 > maxSamples)
   1336                     temp2 = maxSamples;
   1337                 pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp2;
   1338                 temp2 = temp + (((int32_t) pPreset->m_sEarlyR.m_zDelay[i]
   1339                         * pReverb->m_nSamplingRate) >> 16);
   1340                 if (temp2 > maxSamples)
   1341                     temp2 = maxSamples;
   1342                 pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp2;
   1343             }
   1344             pReverb->m_nEarlyDelay = temp;
   1345 
   1346             ALOGV("REVERB_PARAM_REFLECTIONS_DELAY, m_nEarlyDelay smps %d max smp delay %d", pReverb->m_nEarlyDelay, maxSamples);
   1347 
   1348             // Convert milliseconds to sample count => m_nEarlyDelay
   1349             if (param == REVERB_PARAM_REFLECTIONS_DELAY)
   1350                 break;
   1351             value16 = pProperties->reverbLevel;
   1352             /* FALL THROUGH */
   1353 
   1354         case REVERB_PARAM_REVERB_LEVEL:
   1355             // We limit max value to 0 because gain is limited to 0dB
   1356             if (value16 > 0 || value16 < -6000)
   1357                 return -EINVAL;
   1358             // Convert millibels to linear 16 bits (gange 0 - 8191) => m_nLateGain.
   1359             pReverb->m_nLateGain = Effects_MillibelsToLinear16(value16) >> 2;
   1360 
   1361             ALOGV("REVERB_PARAM_REVERB_LEVEL, m_nLateGain %d", pReverb->m_nLateGain);
   1362 
   1363             if (param == REVERB_PARAM_REVERB_LEVEL)
   1364                 break;
   1365             value32 = pProperties->reverbDelay;
   1366             /* FALL THROUGH */
   1367 
   1368         case REVERB_PARAM_REVERB_DELAY:
   1369             // We limit max value to MAX_DELAY_TIME
   1370             // convert ms to time units
   1371             temp = (value32 * 65536) / 1000;
   1372             if (temp < 0 || temp > MAX_DELAY_TIME)
   1373                 return -EINVAL;
   1374 
   1375             maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
   1376                     >> 16;
   1377             temp = (temp * pReverb->m_nSamplingRate) >> 16;
   1378             if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
   1379                 temp = maxSamples - pReverb->m_nMaxExcursion;
   1380             }
   1381             if (temp < pReverb->m_nMaxExcursion) {
   1382                 temp = pReverb->m_nMaxExcursion;
   1383             }
   1384 
   1385             temp -= pReverb->m_nLateDelay;
   1386             pReverb->m_nDelay0Out += temp;
   1387             pReverb->m_nDelay1Out += temp;
   1388             pReverb->m_nLateDelay += temp;
   1389 
   1390             ALOGV("REVERB_PARAM_REVERB_DELAY, m_nLateDelay smps %d max smp delay %d", pReverb->m_nLateDelay, maxSamples);
   1391 
   1392             // Convert milliseconds to sample count => m_nDelay1Out + m_nMaxExcursion
   1393             if (param == REVERB_PARAM_REVERB_DELAY)
   1394                 break;
   1395 
   1396             value16 = pProperties->diffusion;
   1397             /* FALL THROUGH */
   1398 
   1399         case REVERB_PARAM_DIFFUSION:
   1400             if (value16 < 0 || value16 > 1000)
   1401                 return -EINVAL;
   1402 
   1403             // Convert per mille to m_sAp0.m_nApGain, m_sAp1.m_nApGain
   1404             pReverb->m_sAp0.m_nApGain = AP0_GAIN_BASE + ((int32_t) value16
   1405                     * AP0_GAIN_RANGE) / 1000;
   1406             pReverb->m_sAp1.m_nApGain = AP1_GAIN_BASE + ((int32_t) value16
   1407                     * AP1_GAIN_RANGE) / 1000;
   1408 
   1409             ALOGV("REVERB_PARAM_DIFFUSION, m_sAp0.m_nApGain %d m_sAp1.m_nApGain %d", pReverb->m_sAp0.m_nApGain, pReverb->m_sAp1.m_nApGain);
   1410 
   1411             if (param == REVERB_PARAM_DIFFUSION)
   1412                 break;
   1413 
   1414             value16 = pProperties->density;
   1415             /* FALL THROUGH */
   1416 
   1417         case REVERB_PARAM_DENSITY:
   1418             if (value16 < 0 || value16 > 1000)
   1419                 return -EINVAL;
   1420 
   1421             // Convert per mille to m_sAp0.m_zApOut, m_sAp1.m_zApOut
   1422             maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
   1423 
   1424             temp = AP0_TIME_BASE + ((int32_t) value16 * AP0_TIME_RANGE) / 1000;
   1425             /*lint -e{702} shift for performance */
   1426             temp = (temp * pReverb->m_nSamplingRate) >> 16;
   1427             if (temp > maxSamples)
   1428                 temp = maxSamples;
   1429             pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);
   1430 
   1431             ALOGV("REVERB_PARAM_DENSITY, Ap0 delay smps %d", temp);
   1432 
   1433             temp = AP1_TIME_BASE + ((int32_t) value16 * AP1_TIME_RANGE) / 1000;
   1434             /*lint -e{702} shift for performance */
   1435             temp = (temp * pReverb->m_nSamplingRate) >> 16;
   1436             if (temp > maxSamples)
   1437                 temp = maxSamples;
   1438             pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
   1439 
   1440             ALOGV("Ap1 delay smps %d", temp);
   1441 
   1442             break;
   1443 
   1444         default:
   1445             break;
   1446         }
   1447     }
   1448 
   1449     return 0;
   1450 } /* end Reverb_setParameter */
   1451 
   1452 /*----------------------------------------------------------------------------
   1453  * ReverbUpdateXfade
   1454  *----------------------------------------------------------------------------
   1455  * Purpose:
   1456  * Update the xfade parameters as required
   1457  *
   1458  * Inputs:
   1459  * nNumSamplesToAdd - number of samples to write to buffer
   1460  *
   1461  * Outputs:
   1462  *
   1463  *
   1464  * Side Effects:
   1465  * - xfade parameters will be changed
   1466  *
   1467  *----------------------------------------------------------------------------
   1468  */
   1469 static int ReverbUpdateXfade(reverb_object_t *pReverb, int nNumSamplesToAdd) {
   1470     uint16_t nOffset;
   1471     int16_t tempCos;
   1472     int16_t tempSin;
   1473 
   1474     if (pReverb->m_nXfadeCounter >= pReverb->m_nXfadeInterval) {
   1475         /* update interval has elapsed, so reset counter */
   1476         pReverb->m_nXfadeCounter = 0;
   1477 
   1478         // Pin the sin,cos values to min / max values to ensure that the
   1479         // modulated taps' coefs are zero (thus no clicks)
   1480         if (pReverb->m_nPhaseIncrement > 0) {
   1481             // if phase increment > 0, then sin -> 1, cos -> 0
   1482             pReverb->m_nSin = 32767;
   1483             pReverb->m_nCos = 0;
   1484 
   1485             // reset the phase to match the sin, cos values
   1486             pReverb->m_nPhase = 32767;
   1487 
   1488             // modulate the cross taps because their tap coefs are zero
   1489             nOffset = ReverbCalculateNoise(pReverb);
   1490 
   1491             pReverb->m_zD1Cross = pReverb->m_nDelay1Out
   1492                     - pReverb->m_nMaxExcursion + nOffset;
   1493 
   1494             nOffset = ReverbCalculateNoise(pReverb);
   1495 
   1496             pReverb->m_zD0Cross = pReverb->m_nDelay0Out
   1497                     - pReverb->m_nMaxExcursion - nOffset;
   1498         } else {
   1499             // if phase increment < 0, then sin -> 0, cos -> 1
   1500             pReverb->m_nSin = 0;
   1501             pReverb->m_nCos = 32767;
   1502 
   1503             // reset the phase to match the sin, cos values
   1504             pReverb->m_nPhase = -32768;
   1505 
   1506             // modulate the self taps because their tap coefs are zero
   1507             nOffset = ReverbCalculateNoise(pReverb);
   1508 
   1509             pReverb->m_zD0Self = pReverb->m_nDelay0Out
   1510                     - pReverb->m_nMaxExcursion - nOffset;
   1511 
   1512             nOffset = ReverbCalculateNoise(pReverb);
   1513 
   1514             pReverb->m_zD1Self = pReverb->m_nDelay1Out
   1515                     - pReverb->m_nMaxExcursion + nOffset;
   1516 
   1517         } // end if-else (pReverb->m_nPhaseIncrement > 0)
   1518 
   1519         // Reverse the direction of the sin,cos so that the
   1520         // tap whose coef was previously increasing now decreases
   1521         // and vice versa
   1522         pReverb->m_nPhaseIncrement = -pReverb->m_nPhaseIncrement;
   1523 
   1524     } // end if counter >= update interval
   1525 
   1526     //compute what phase will be next time
   1527     pReverb->m_nPhase += pReverb->m_nPhaseIncrement;
   1528 
   1529     //calculate what the new sin and cos need to reach by the next update
   1530     ReverbCalculateSinCos(pReverb->m_nPhase, &tempSin, &tempCos);
   1531 
   1532     //calculate the per-sample increment required to get there by the next update
   1533     /*lint -e{702} shift for performance */
   1534     pReverb->m_nSinIncrement = (tempSin - pReverb->m_nSin)
   1535             >> pReverb->m_nUpdatePeriodInBits;
   1536 
   1537     /*lint -e{702} shift for performance */
   1538     pReverb->m_nCosIncrement = (tempCos - pReverb->m_nCos)
   1539             >> pReverb->m_nUpdatePeriodInBits;
   1540 
   1541     /* increment update counter */
   1542     pReverb->m_nXfadeCounter += (uint16_t) nNumSamplesToAdd;
   1543 
   1544     return 0;
   1545 
   1546 } /* end ReverbUpdateXfade */
   1547 
   1548 /*----------------------------------------------------------------------------
   1549  * ReverbCalculateNoise
   1550  *----------------------------------------------------------------------------
   1551  * Purpose:
   1552  * Calculate a noise sample and limit its value
   1553  *
   1554  * Inputs:
   1555  * nMaxExcursion - noise value is limited to this value
   1556  * pnNoise - return new noise sample in this (not limited)
   1557  *
   1558  * Outputs:
   1559  * new limited noise value
   1560  *
   1561  * Side Effects:
   1562  * - *pnNoise noise value is updated
   1563  *
   1564  *----------------------------------------------------------------------------
   1565  */
   1566 static uint16_t ReverbCalculateNoise(reverb_object_t *pReverb) {
   1567     int16_t nNoise = pReverb->m_nNoise;
   1568 
   1569     // calculate new noise value
   1570     if (pReverb->m_bUseNoise) {
   1571         nNoise = (int16_t) (nNoise * 5 + 1);
   1572     } else {
   1573         nNoise = 0;
   1574     }
   1575 
   1576     pReverb->m_nNoise = nNoise;
   1577     // return the limited noise value
   1578     return (pReverb->m_nMaxExcursion & nNoise);
   1579 
   1580 } /* end ReverbCalculateNoise */
   1581 
   1582 /*----------------------------------------------------------------------------
   1583  * ReverbCalculateSinCos
   1584  *----------------------------------------------------------------------------
   1585  * Purpose:
   1586  * Calculate a new sin and cosine value based on the given phase
   1587  *
   1588  * Inputs:
   1589  * nPhase   - phase angle
   1590  * pnSin    - input old value, output new value
   1591  * pnCos    - input old value, output new value
   1592  *
   1593  * Outputs:
   1594  *
   1595  * Side Effects:
   1596  * - *pnSin, *pnCos are updated
   1597  *
   1598  *----------------------------------------------------------------------------
   1599  */
   1600 static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos) {
   1601     int32_t nTemp;
   1602     int32_t nNetAngle;
   1603 
   1604     //  -1 <=  nPhase  < 1
   1605     // However, for the calculation, we need a value
   1606     // that ranges from -1/2 to +1/2, so divide the phase by 2
   1607     /*lint -e{702} shift for performance */
   1608     nNetAngle = nPhase >> 1;
   1609 
   1610     /*
   1611      Implement the following
   1612      sin(x) = (2-4*c)*x^2 + c + x
   1613      cos(x) = (2-4*c)*x^2 + c - x
   1614 
   1615      where  c = 1/sqrt(2)
   1616      using the a0 + x*(a1 + x*a2) approach
   1617      */
   1618 
   1619     /* limit the input "angle" to be between -0.5 and +0.5 */
   1620     if (nNetAngle > EG1_HALF) {
   1621         nNetAngle = EG1_HALF;
   1622     } else if (nNetAngle < EG1_MINUS_HALF) {
   1623         nNetAngle = EG1_MINUS_HALF;
   1624     }
   1625 
   1626     /* calculate sin */
   1627     nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
   1628     nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
   1629     *pnSin = (int16_t) SATURATE_EG1(nTemp);
   1630 
   1631     /* calculate cos */
   1632     nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
   1633     nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
   1634     *pnCos = (int16_t) SATURATE_EG1(nTemp);
   1635 
   1636     return 0;
   1637 } /* end ReverbCalculateSinCos */
   1638 
   1639 /*----------------------------------------------------------------------------
   1640  * Reverb
   1641  *----------------------------------------------------------------------------
   1642  * Purpose:
   1643  * apply reverb to the given signal
   1644  *
   1645  * Inputs:
   1646  * nNu
   1647  * pnSin    - input old value, output new value
   1648  * pnCos    - input old value, output new value
   1649  *
   1650  * Outputs:
   1651  * number of samples actually reverberated
   1652  *
   1653  * Side Effects:
   1654  *
   1655  *----------------------------------------------------------------------------
   1656  */
   1657 static int Reverb(reverb_object_t *pReverb, int nNumSamplesToAdd,
   1658         short *pOutputBuffer, short *pInputBuffer) {
   1659     int32_t i;
   1660     int32_t nDelayOut0;
   1661     int32_t nDelayOut1;
   1662     uint16_t nBase;
   1663 
   1664     uint32_t nAddr;
   1665     int32_t nTemp1;
   1666     int32_t nTemp2;
   1667     int32_t nApIn;
   1668     int32_t nApOut;
   1669 
   1670     int32_t j;
   1671     int32_t nEarlyOut;
   1672 
   1673     int32_t tempValue;
   1674 
   1675     // get the base address
   1676     nBase = pReverb->m_nBaseIndex;
   1677 
   1678     for (i = 0; i < nNumSamplesToAdd; i++) {
   1679         // ********** Left Allpass - start
   1680         nApIn = *pInputBuffer;
   1681         if (!pReverb->m_Aux) {
   1682             pInputBuffer++;
   1683         }
   1684         // store to early delay line
   1685         nAddr = CIRCULAR(nBase, pReverb->m_nEarly0in, pReverb->m_nBufferMask);
   1686         pReverb->m_nDelayLine[nAddr] = (short) nApIn;
   1687 
   1688         // left input = (left dry * m_nLateGain) + right feedback from previous period
   1689 
   1690         nApIn = SATURATE(nApIn + pReverb->m_nRevFbkR);
   1691         nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain);
   1692 
   1693         // fetch allpass delay line out
   1694         //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, pReverb->m_nBufferMask);
   1695         nAddr
   1696                 = CIRCULAR(nBase, pReverb->m_sAp0.m_zApOut, pReverb->m_nBufferMask);
   1697         nDelayOut0 = pReverb->m_nDelayLine[nAddr];
   1698 
   1699         // calculate allpass feedforward; subtract the feedforward result
   1700         nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp0.m_nApGain);
   1701         nApOut = SATURATE(nDelayOut0 - nTemp1); // allpass output
   1702 
   1703         // calculate allpass feedback; add the feedback result
   1704         nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp0.m_nApGain);
   1705         nTemp1 = SATURATE(nApIn + nTemp1);
   1706 
   1707         // inject into allpass delay
   1708         nAddr
   1709                 = CIRCULAR(nBase, pReverb->m_sAp0.m_zApIn, pReverb->m_nBufferMask);
   1710         pReverb->m_nDelayLine[nAddr] = (short) nTemp1;
   1711 
   1712         // inject allpass output into delay line
   1713         nAddr = CIRCULAR(nBase, pReverb->m_zD0In, pReverb->m_nBufferMask);
   1714         pReverb->m_nDelayLine[nAddr] = (short) nApOut;
   1715 
   1716         // ********** Left Allpass - end
   1717 
   1718         // ********** Right Allpass - start
   1719         nApIn = (*pInputBuffer++);
   1720         // store to early delay line
   1721         nAddr = CIRCULAR(nBase, pReverb->m_nEarly1in, pReverb->m_nBufferMask);
   1722         pReverb->m_nDelayLine[nAddr] = (short) nApIn;
   1723 
   1724         // right input = (right dry * m_nLateGain) + left feedback from previous period
   1725         /*lint -e{702} use shift for performance */
   1726         nApIn = SATURATE(nApIn + pReverb->m_nRevFbkL);
   1727         nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain);
   1728 
   1729         // fetch allpass delay line out
   1730         nAddr
   1731                 = CIRCULAR(nBase, pReverb->m_sAp1.m_zApOut, pReverb->m_nBufferMask);
   1732         nDelayOut1 = pReverb->m_nDelayLine[nAddr];
   1733 
   1734         // calculate allpass feedforward; subtract the feedforward result
   1735         nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp1.m_nApGain);
   1736         nApOut = SATURATE(nDelayOut1 - nTemp1); // allpass output
   1737 
   1738         // calculate allpass feedback; add the feedback result
   1739         nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp1.m_nApGain);
   1740         nTemp1 = SATURATE(nApIn + nTemp1);
   1741 
   1742         // inject into allpass delay
   1743         nAddr
   1744                 = CIRCULAR(nBase, pReverb->m_sAp1.m_zApIn, pReverb->m_nBufferMask);
   1745         pReverb->m_nDelayLine[nAddr] = (short) nTemp1;
   1746 
   1747         // inject allpass output into delay line
   1748         nAddr = CIRCULAR(nBase, pReverb->m_zD1In, pReverb->m_nBufferMask);
   1749         pReverb->m_nDelayLine[nAddr] = (short) nApOut;
   1750 
   1751         // ********** Right Allpass - end
   1752 
   1753         // ********** D0 output - start
   1754         // fetch delay line self out
   1755         nAddr = CIRCULAR(nBase, pReverb->m_zD0Self, pReverb->m_nBufferMask);
   1756         nDelayOut0 = pReverb->m_nDelayLine[nAddr];
   1757 
   1758         // calculate delay line self out
   1759         nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nSin);
   1760 
   1761         // fetch delay line cross out
   1762         nAddr = CIRCULAR(nBase, pReverb->m_zD1Cross, pReverb->m_nBufferMask);
   1763         nDelayOut0 = pReverb->m_nDelayLine[nAddr];
   1764 
   1765         // calculate delay line self out
   1766         nTemp2 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nCos);
   1767 
   1768         // calculate unfiltered delay out
   1769         nDelayOut0 = SATURATE(nTemp1 + nTemp2);
   1770 
   1771         // ********** D0 output - end
   1772 
   1773         // ********** D1 output - start
   1774         // fetch delay line self out
   1775         nAddr = CIRCULAR(nBase, pReverb->m_zD1Self, pReverb->m_nBufferMask);
   1776         nDelayOut1 = pReverb->m_nDelayLine[nAddr];
   1777 
   1778         // calculate delay line self out
   1779         nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nSin);
   1780 
   1781         // fetch delay line cross out
   1782         nAddr = CIRCULAR(nBase, pReverb->m_zD0Cross, pReverb->m_nBufferMask);
   1783         nDelayOut1 = pReverb->m_nDelayLine[nAddr];
   1784 
   1785         // calculate delay line self out
   1786         nTemp2 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nCos);
   1787 
   1788         // calculate unfiltered delay out
   1789         nDelayOut1 = SATURATE(nTemp1 + nTemp2);
   1790 
   1791         // ********** D1 output - end
   1792 
   1793         // ********** mixer and feedback - start
   1794         // sum is fedback to right input (R + L)
   1795         nDelayOut0 = (short) SATURATE(nDelayOut0 + nDelayOut1);
   1796 
   1797         // difference is feedback to left input (R - L)
   1798         /*lint -e{685} lint complains that it can't saturate negative */
   1799         nDelayOut1 = (short) SATURATE(nDelayOut1 - nDelayOut0);
   1800 
   1801         // ********** mixer and feedback - end
   1802 
   1803         // calculate lowpass filter (mixer scale factor included in LPF feedforward)
   1804         nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRvbLpfFwd);
   1805 
   1806         nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkL, pReverb->m_nRvbLpfFbk);
   1807 
   1808         // calculate filtered delay out and simultaneously update LPF state variable
   1809         // filtered delay output is stored in m_nRevFbkL
   1810         pReverb->m_nRevFbkL = (short) SATURATE(nTemp1 + nTemp2);
   1811 
   1812         // calculate lowpass filter (mixer scale factor included in LPF feedforward)
   1813         nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRvbLpfFwd);
   1814 
   1815         nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkR, pReverb->m_nRvbLpfFbk);
   1816 
   1817         // calculate filtered delay out and simultaneously update LPF state variable
   1818         // filtered delay output is stored in m_nRevFbkR
   1819         pReverb->m_nRevFbkR = (short) SATURATE(nTemp1 + nTemp2);
   1820 
   1821         // ********** start early reflection generator, left
   1822         //psEarly = &(pReverb->m_sEarlyL);
   1823 
   1824 
   1825         for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) {
   1826             // fetch delay line out
   1827             //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], pReverb->m_nBufferMask);
   1828             nAddr
   1829                     = CIRCULAR(nBase, pReverb->m_sEarlyL.m_zDelay[j], pReverb->m_nBufferMask);
   1830 
   1831             nTemp1 = pReverb->m_nDelayLine[nAddr];
   1832 
   1833             // calculate reflection
   1834             //nTemp1 = MULT_EG1_EG1(nDelayOut0, psEarly->m_nGain[j]);
   1835             nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyL.m_nGain[j]);
   1836 
   1837             nDelayOut0 = SATURATE(nDelayOut0 + nTemp1);
   1838 
   1839         } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
   1840 
   1841         // apply lowpass to early reflections and reverb output
   1842         //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nRvbLpfFwd);
   1843         nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRoomLpfFwd);
   1844 
   1845         //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk);
   1846         nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfL, pReverb->m_nRoomLpfFbk);
   1847 
   1848         // calculate filtered out and simultaneously update LPF state variable
   1849         // filtered output is stored in m_zOutLpfL
   1850         pReverb->m_zOutLpfL = (short) SATURATE(nTemp1 + nTemp2);
   1851 
   1852         //sum with output buffer
   1853         tempValue = *pOutputBuffer;
   1854         *pOutputBuffer++ = (short) SATURATE(tempValue+pReverb->m_zOutLpfL);
   1855 
   1856         // ********** end early reflection generator, left
   1857 
   1858         // ********** start early reflection generator, right
   1859         //psEarly = &(pReverb->m_sEarlyR);
   1860 
   1861         for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) {
   1862             // fetch delay line out
   1863             nAddr
   1864                     = CIRCULAR(nBase, pReverb->m_sEarlyR.m_zDelay[j], pReverb->m_nBufferMask);
   1865             nTemp1 = pReverb->m_nDelayLine[nAddr];
   1866 
   1867             // calculate reflection
   1868             nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyR.m_nGain[j]);
   1869 
   1870             nDelayOut1 = SATURATE(nDelayOut1 + nTemp1);
   1871 
   1872         } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
   1873 
   1874         // apply lowpass to early reflections
   1875         nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRoomLpfFwd);
   1876 
   1877         nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfR, pReverb->m_nRoomLpfFbk);
   1878 
   1879         // calculate filtered out and simultaneously update LPF state variable
   1880         // filtered output is stored in m_zOutLpfR
   1881         pReverb->m_zOutLpfR = (short) SATURATE(nTemp1 + nTemp2);
   1882 
   1883         //sum with output buffer
   1884         tempValue = *pOutputBuffer;
   1885         *pOutputBuffer++ = (short) SATURATE(tempValue + pReverb->m_zOutLpfR);
   1886 
   1887         // ********** end early reflection generator, right
   1888 
   1889         // decrement base addr for next sample period
   1890         nBase--;
   1891 
   1892         pReverb->m_nSin += pReverb->m_nSinIncrement;
   1893         pReverb->m_nCos += pReverb->m_nCosIncrement;
   1894 
   1895     } // end for (i=0; i < nNumSamplesToAdd; i++)
   1896 
   1897     // store the most up to date version
   1898     pReverb->m_nBaseIndex = nBase;
   1899 
   1900     return 0;
   1901 } /* end Reverb */
   1902 
   1903 /*----------------------------------------------------------------------------
   1904  * ReverbUpdateRoom
   1905  *----------------------------------------------------------------------------
   1906  * Purpose:
   1907  * Update the room's preset parameters as required
   1908  *
   1909  * Inputs:
   1910  *
   1911  * Outputs:
   1912  *
   1913  *
   1914  * Side Effects:
   1915  * - reverb paramters (fbk, fwd, etc) will be changed
   1916  * - m_nCurrentRoom := m_nNextRoom
   1917  *----------------------------------------------------------------------------
   1918  */
   1919 static int ReverbUpdateRoom(reverb_object_t *pReverb, bool fullUpdate) {
   1920     int temp;
   1921     int i;
   1922     int maxSamples;
   1923     int earlyDelay;
   1924     int earlyGain;
   1925 
   1926     reverb_preset_t *pPreset =
   1927             &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom];
   1928 
   1929     if (fullUpdate) {
   1930         pReverb->m_nRvbLpfFwd = pPreset->m_nRvbLpfFwd;
   1931         pReverb->m_nRvbLpfFbk = pPreset->m_nRvbLpfFbk;
   1932 
   1933         pReverb->m_nEarlyGain = pPreset->m_nEarlyGain;
   1934         //stored as time based, convert to sample based
   1935         pReverb->m_nLateGain = pPreset->m_nLateGain;
   1936         pReverb->m_nRoomLpfFbk = pPreset->m_nRoomLpfFbk;
   1937         pReverb->m_nRoomLpfFwd = pPreset->m_nRoomLpfFwd;
   1938 
   1939         // set the early reflections gains
   1940         earlyGain = pPreset->m_nEarlyGain;
   1941         for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
   1942             pReverb->m_sEarlyL.m_nGain[i]
   1943                     = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],earlyGain);
   1944             pReverb->m_sEarlyR.m_nGain[i]
   1945                     = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],earlyGain);
   1946         }
   1947 
   1948         pReverb->m_nMaxExcursion = pPreset->m_nMaxExcursion;
   1949 
   1950         pReverb->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
   1951         pReverb->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;
   1952 
   1953         // set the early reflections delay
   1954         earlyDelay = ((int) pPreset->m_nEarlyDelay * pReverb->m_nSamplingRate)
   1955                 >> 16;
   1956         pReverb->m_nEarlyDelay = earlyDelay;
   1957         maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
   1958                 >> 16;
   1959         for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
   1960             //stored as time based, convert to sample based
   1961             temp = earlyDelay + (((int) pPreset->m_sEarlyL.m_zDelay[i]
   1962                     * pReverb->m_nSamplingRate) >> 16);
   1963             if (temp > maxSamples)
   1964                 temp = maxSamples;
   1965             pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp;
   1966             //stored as time based, convert to sample based
   1967             temp = earlyDelay + (((int) pPreset->m_sEarlyR.m_zDelay[i]
   1968                     * pReverb->m_nSamplingRate) >> 16);
   1969             if (temp > maxSamples)
   1970                 temp = maxSamples;
   1971             pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp;
   1972         }
   1973 
   1974         maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
   1975                 >> 16;
   1976         //stored as time based, convert to sample based
   1977         /*lint -e{702} shift for performance */
   1978         temp = (pPreset->m_nLateDelay * pReverb->m_nSamplingRate) >> 16;
   1979         if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
   1980             temp = maxSamples - pReverb->m_nMaxExcursion;
   1981         }
   1982         temp -= pReverb->m_nLateDelay;
   1983         pReverb->m_nDelay0Out += temp;
   1984         pReverb->m_nDelay1Out += temp;
   1985         pReverb->m_nLateDelay += temp;
   1986 
   1987         maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
   1988         //stored as time based, convert to absolute sample value
   1989         temp = pPreset->m_nAp0_ApOut;
   1990         /*lint -e{702} shift for performance */
   1991         temp = (temp * pReverb->m_nSamplingRate) >> 16;
   1992         if (temp > maxSamples)
   1993             temp = maxSamples;
   1994         pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);
   1995 
   1996         //stored as time based, convert to absolute sample value
   1997         temp = pPreset->m_nAp1_ApOut;
   1998         /*lint -e{702} shift for performance */
   1999         temp = (temp * pReverb->m_nSamplingRate) >> 16;
   2000         if (temp > maxSamples)
   2001             temp = maxSamples;
   2002         pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
   2003         //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
   2004     }
   2005 
   2006     //stored as time based, convert to sample based
   2007     temp = pPreset->m_nXfadeInterval;
   2008     /*lint -e{702} shift for performance */
   2009     temp = (temp * pReverb->m_nSamplingRate) >> 16;
   2010     pReverb->m_nXfadeInterval = (uint16_t) temp;
   2011     //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval;
   2012     pReverb->m_nXfadeCounter = pReverb->m_nXfadeInterval + 1; // force update on first iteration
   2013 
   2014     pReverb->m_nCurrentRoom = pReverb->m_nNextRoom;
   2015 
   2016     return 0;
   2017 
   2018 } /* end ReverbUpdateRoom */
   2019 
   2020 /*----------------------------------------------------------------------------
   2021  * ReverbReadInPresets()
   2022  *----------------------------------------------------------------------------
   2023  * Purpose: sets global reverb preset bank to defaults
   2024  *
   2025  * Inputs:
   2026  *
   2027  * Outputs:
   2028  *
   2029  *----------------------------------------------------------------------------
   2030  */
   2031 static int ReverbReadInPresets(reverb_object_t *pReverb) {
   2032 
   2033     int preset;
   2034 
   2035     // this is for test only. OpenSL ES presets are mapped to 4 presets.
   2036     // REVERB_PRESET_NONE is mapped to bypass
   2037     for (preset = 0; preset < REVERB_NUM_PRESETS; preset++) {
   2038         reverb_preset_t *pPreset = &pReverb->m_sPreset.m_sPreset[preset];
   2039         switch (preset + 1) {
   2040         case REVERB_PRESET_PLATE:
   2041         case REVERB_PRESET_SMALLROOM:
   2042             pPreset->m_nRvbLpfFbk = 5077;
   2043             pPreset->m_nRvbLpfFwd = 11076;
   2044             pPreset->m_nEarlyGain = 27690;
   2045             pPreset->m_nEarlyDelay = 1311;
   2046             pPreset->m_nLateGain = 8191;
   2047             pPreset->m_nLateDelay = 3932;
   2048             pPreset->m_nRoomLpfFbk = 3692;
   2049             pPreset->m_nRoomLpfFwd = 20474;
   2050             pPreset->m_sEarlyL.m_zDelay[0] = 1376;
   2051             pPreset->m_sEarlyL.m_nGain[0] = 22152;
   2052             pPreset->m_sEarlyL.m_zDelay[1] = 1462;
   2053             pPreset->m_sEarlyL.m_nGain[1] = 17537;
   2054             pPreset->m_sEarlyL.m_zDelay[2] = 0;
   2055             pPreset->m_sEarlyL.m_nGain[2] = 14768;
   2056             pPreset->m_sEarlyL.m_zDelay[3] = 1835;
   2057             pPreset->m_sEarlyL.m_nGain[3] = 14307;
   2058             pPreset->m_sEarlyL.m_zDelay[4] = 0;
   2059             pPreset->m_sEarlyL.m_nGain[4] = 13384;
   2060             pPreset->m_sEarlyR.m_zDelay[0] = 721;
   2061             pPreset->m_sEarlyR.m_nGain[0] = 20306;
   2062             pPreset->m_sEarlyR.m_zDelay[1] = 2621;
   2063             pPreset->m_sEarlyR.m_nGain[1] = 17537;
   2064             pPreset->m_sEarlyR.m_zDelay[2] = 0;
   2065             pPreset->m_sEarlyR.m_nGain[2] = 14768;
   2066             pPreset->m_sEarlyR.m_zDelay[3] = 0;
   2067             pPreset->m_sEarlyR.m_nGain[3] = 16153;
   2068             pPreset->m_sEarlyR.m_zDelay[4] = 0;
   2069             pPreset->m_sEarlyR.m_nGain[4] = 13384;
   2070             pPreset->m_nMaxExcursion = 127;
   2071             pPreset->m_nXfadeInterval = 6470; //6483;
   2072             pPreset->m_nAp0_ApGain = 14768;
   2073             pPreset->m_nAp0_ApOut = 792;
   2074             pPreset->m_nAp1_ApGain = 14777;
   2075             pPreset->m_nAp1_ApOut = 1191;
   2076             pPreset->m_rfu4 = 0;
   2077             pPreset->m_rfu5 = 0;
   2078             pPreset->m_rfu6 = 0;
   2079             pPreset->m_rfu7 = 0;
   2080             pPreset->m_rfu8 = 0;
   2081             pPreset->m_rfu9 = 0;
   2082             pPreset->m_rfu10 = 0;
   2083             break;
   2084         case REVERB_PRESET_MEDIUMROOM:
   2085         case REVERB_PRESET_LARGEROOM:
   2086             pPreset->m_nRvbLpfFbk = 5077;
   2087             pPreset->m_nRvbLpfFwd = 12922;
   2088             pPreset->m_nEarlyGain = 27690;
   2089             pPreset->m_nEarlyDelay = 1311;
   2090             pPreset->m_nLateGain = 8191;
   2091             pPreset->m_nLateDelay = 3932;
   2092             pPreset->m_nRoomLpfFbk = 3692;
   2093             pPreset->m_nRoomLpfFwd = 21703;
   2094             pPreset->m_sEarlyL.m_zDelay[0] = 1376;
   2095             pPreset->m_sEarlyL.m_nGain[0] = 22152;
   2096             pPreset->m_sEarlyL.m_zDelay[1] = 1462;
   2097             pPreset->m_sEarlyL.m_nGain[1] = 17537;
   2098             pPreset->m_sEarlyL.m_zDelay[2] = 0;
   2099             pPreset->m_sEarlyL.m_nGain[2] = 14768;
   2100             pPreset->m_sEarlyL.m_zDelay[3] = 1835;
   2101             pPreset->m_sEarlyL.m_nGain[3] = 14307;
   2102             pPreset->m_sEarlyL.m_zDelay[4] = 0;
   2103             pPreset->m_sEarlyL.m_nGain[4] = 13384;
   2104             pPreset->m_sEarlyR.m_zDelay[0] = 721;
   2105             pPreset->m_sEarlyR.m_nGain[0] = 20306;
   2106             pPreset->m_sEarlyR.m_zDelay[1] = 2621;
   2107             pPreset->m_sEarlyR.m_nGain[1] = 17537;
   2108             pPreset->m_sEarlyR.m_zDelay[2] = 0;
   2109             pPreset->m_sEarlyR.m_nGain[2] = 14768;
   2110             pPreset->m_sEarlyR.m_zDelay[3] = 0;
   2111             pPreset->m_sEarlyR.m_nGain[3] = 16153;
   2112             pPreset->m_sEarlyR.m_zDelay[4] = 0;
   2113             pPreset->m_sEarlyR.m_nGain[4] = 13384;
   2114             pPreset->m_nMaxExcursion = 127;
   2115             pPreset->m_nXfadeInterval = 6449;
   2116             pPreset->m_nAp0_ApGain = 15691;
   2117             pPreset->m_nAp0_ApOut = 774;
   2118             pPreset->m_nAp1_ApGain = 16317;
   2119             pPreset->m_nAp1_ApOut = 1155;
   2120             pPreset->m_rfu4 = 0;
   2121             pPreset->m_rfu5 = 0;
   2122             pPreset->m_rfu6 = 0;
   2123             pPreset->m_rfu7 = 0;
   2124             pPreset->m_rfu8 = 0;
   2125             pPreset->m_rfu9 = 0;
   2126             pPreset->m_rfu10 = 0;
   2127             break;
   2128         case REVERB_PRESET_MEDIUMHALL:
   2129             pPreset->m_nRvbLpfFbk = 6461;
   2130             pPreset->m_nRvbLpfFwd = 14307;
   2131             pPreset->m_nEarlyGain = 27690;
   2132             pPreset->m_nEarlyDelay = 1311;
   2133             pPreset->m_nLateGain = 8191;
   2134             pPreset->m_nLateDelay = 3932;
   2135             pPreset->m_nRoomLpfFbk = 3692;
   2136             pPreset->m_nRoomLpfFwd = 24569;
   2137             pPreset->m_sEarlyL.m_zDelay[0] = 1376;
   2138             pPreset->m_sEarlyL.m_nGain[0] = 22152;
   2139             pPreset->m_sEarlyL.m_zDelay[1] = 1462;
   2140             pPreset->m_sEarlyL.m_nGain[1] = 17537;
   2141             pPreset->m_sEarlyL.m_zDelay[2] = 0;
   2142             pPreset->m_sEarlyL.m_nGain[2] = 14768;
   2143             pPreset->m_sEarlyL.m_zDelay[3] = 1835;
   2144             pPreset->m_sEarlyL.m_nGain[3] = 14307;
   2145             pPreset->m_sEarlyL.m_zDelay[4] = 0;
   2146             pPreset->m_sEarlyL.m_nGain[4] = 13384;
   2147             pPreset->m_sEarlyR.m_zDelay[0] = 721;
   2148             pPreset->m_sEarlyR.m_nGain[0] = 20306;
   2149             pPreset->m_sEarlyR.m_zDelay[1] = 2621;
   2150             pPreset->m_sEarlyR.m_nGain[1] = 17537;
   2151             pPreset->m_sEarlyR.m_zDelay[2] = 0;
   2152             pPreset->m_sEarlyR.m_nGain[2] = 14768;
   2153             pPreset->m_sEarlyR.m_zDelay[3] = 0;
   2154             pPreset->m_sEarlyR.m_nGain[3] = 16153;
   2155             pPreset->m_sEarlyR.m_zDelay[4] = 0;
   2156             pPreset->m_sEarlyR.m_nGain[4] = 13384;
   2157             pPreset->m_nMaxExcursion = 127;
   2158             pPreset->m_nXfadeInterval = 6391;
   2159             pPreset->m_nAp0_ApGain = 15230;
   2160             pPreset->m_nAp0_ApOut = 708;
   2161             pPreset->m_nAp1_ApGain = 15547;
   2162             pPreset->m_nAp1_ApOut = 1023;
   2163             pPreset->m_rfu4 = 0;
   2164             pPreset->m_rfu5 = 0;
   2165             pPreset->m_rfu6 = 0;
   2166             pPreset->m_rfu7 = 0;
   2167             pPreset->m_rfu8 = 0;
   2168             pPreset->m_rfu9 = 0;
   2169             pPreset->m_rfu10 = 0;
   2170             break;
   2171         case REVERB_PRESET_LARGEHALL:
   2172             pPreset->m_nRvbLpfFbk = 8307;
   2173             pPreset->m_nRvbLpfFwd = 14768;
   2174             pPreset->m_nEarlyGain = 27690;
   2175             pPreset->m_nEarlyDelay = 1311;
   2176             pPreset->m_nLateGain = 8191;
   2177             pPreset->m_nLateDelay = 3932;
   2178             pPreset->m_nRoomLpfFbk = 3692;
   2179             pPreset->m_nRoomLpfFwd = 24569;
   2180             pPreset->m_sEarlyL.m_zDelay[0] = 1376;
   2181             pPreset->m_sEarlyL.m_nGain[0] = 22152;
   2182             pPreset->m_sEarlyL.m_zDelay[1] = 2163;
   2183             pPreset->m_sEarlyL.m_nGain[1] = 17537;
   2184             pPreset->m_sEarlyL.m_zDelay[2] = 0;
   2185             pPreset->m_sEarlyL.m_nGain[2] = 14768;
   2186             pPreset->m_sEarlyL.m_zDelay[3] = 1835;
   2187             pPreset->m_sEarlyL.m_nGain[3] = 14307;
   2188             pPreset->m_sEarlyL.m_zDelay[4] = 0;
   2189             pPreset->m_sEarlyL.m_nGain[4] = 13384;
   2190             pPreset->m_sEarlyR.m_zDelay[0] = 721;
   2191             pPreset->m_sEarlyR.m_nGain[0] = 20306;
   2192             pPreset->m_sEarlyR.m_zDelay[1] = 2621;
   2193             pPreset->m_sEarlyR.m_nGain[1] = 17537;
   2194             pPreset->m_sEarlyR.m_zDelay[2] = 0;
   2195             pPreset->m_sEarlyR.m_nGain[2] = 14768;
   2196             pPreset->m_sEarlyR.m_zDelay[3] = 0;
   2197             pPreset->m_sEarlyR.m_nGain[3] = 16153;
   2198             pPreset->m_sEarlyR.m_zDelay[4] = 0;
   2199             pPreset->m_sEarlyR.m_nGain[4] = 13384;
   2200             pPreset->m_nMaxExcursion = 127;
   2201             pPreset->m_nXfadeInterval = 6388;
   2202             pPreset->m_nAp0_ApGain = 15691;
   2203             pPreset->m_nAp0_ApOut = 711;
   2204             pPreset->m_nAp1_ApGain = 16317;
   2205             pPreset->m_nAp1_ApOut = 1029;
   2206             pPreset->m_rfu4 = 0;
   2207             pPreset->m_rfu5 = 0;
   2208             pPreset->m_rfu6 = 0;
   2209             pPreset->m_rfu7 = 0;
   2210             pPreset->m_rfu8 = 0;
   2211             pPreset->m_rfu9 = 0;
   2212             pPreset->m_rfu10 = 0;
   2213             break;
   2214         }
   2215     }
   2216 
   2217     return 0;
   2218 }
   2219 
   2220 audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
   2221     .tag = AUDIO_EFFECT_LIBRARY_TAG,
   2222     .version = EFFECT_LIBRARY_API_VERSION,
   2223     .name = "Test Equalizer Library",
   2224     .implementor = "The Android Open Source Project",
   2225     .query_num_effects = EffectQueryNumberEffects,
   2226     .query_effect = EffectQueryEffect,
   2227     .create_effect = EffectCreate,
   2228     .release_effect = EffectRelease,
   2229     .get_descriptor = EffectGetDescriptor,
   2230 };
   2231