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