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