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