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