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