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