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