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