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