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