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