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