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