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