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