1/*---------------------------------------------------------------------------- 2 * 3 * File: 4 * eas_chorus.c 5 * 6 * Contents and purpose: 7 * Contains the implementation of the Chorus effect. 8 * 9 * 10 * Copyright Sonic Network Inc. 2006 11 12 * Licensed under the Apache License, Version 2.0 (the "License"); 13 * you may not use this file except in compliance with the License. 14 * You may obtain a copy of the License at 15 * 16 * http://www.apache.org/licenses/LICENSE-2.0 17 * 18 * Unless required by applicable law or agreed to in writing, software 19 * distributed under the License is distributed on an "AS IS" BASIS, 20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 * See the License for the specific language governing permissions and 22 * limitations under the License. 23 * 24 *---------------------------------------------------------------------------- 25 * Revision Control: 26 * $Revision: 499 $ 27 * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ 28 *---------------------------------------------------------------------------- 29*/ 30 31#include "eas_data.h" 32#include "eas_effects.h" 33#include "eas_math.h" 34#include "eas_chorusdata.h" 35#include "eas_chorus.h" 36#include "eas_config.h" 37#include "eas_host.h" 38#include "eas_report.h" 39 40/* prototypes for effects interface */ 41static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); 42static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); 43static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); 44static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); 45static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); 46 47/* common effects interface for configuration module */ 48const S_EFFECTS_INTERFACE EAS_Chorus = 49{ 50 ChorusInit, 51 ChorusProcess, 52 ChorusShutdown, 53 ChorusGetParam, 54 ChorusSetParam 55}; 56 57 58 59//LFO shape table used by the chorus, larger table would sound better 60//this is a sine wave, where 32767 = 1.0 61static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = { 62 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170, 63 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728, 64 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329, 65 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212, 66 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519, 67 -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785, 68 -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621, 69 -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010, 70 -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608 71}; 72 73/*---------------------------------------------------------------------------- 74 * InitializeChorus() 75 *---------------------------------------------------------------------------- 76 * Purpose: Initializes chorus parameters 77 * 78 * 79 * Inputs: 80 * 81 * Outputs: 82 * 83 *---------------------------------------------------------------------------- 84*/ 85static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) 86{ 87 S_CHORUS_OBJECT *pChorusData; 88 S_CHORUS_PRESET *pPreset; 89 EAS_I32 index; 90 91 /* check Configuration Module for data allocation */ 92 if (pEASData->staticMemoryModel) 93 pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS); 94 95 /* allocate dynamic memory */ 96 else 97 pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT)); 98 99 if (pChorusData == NULL) 100 { 101 { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ } 102 return EAS_ERROR_MALLOC_FAILED; 103 } 104 105 /* clear the structure */ 106 EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT)); 107 108 ChorusReadInPresets(pChorusData); 109 110 /* set some default values */ 111 pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT; 112 pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT; 113 pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT; 114 pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT; 115 pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT; 116 117 //chorus rate and depth need some massaging from preset value (which is sample rate independent) 118 119 //convert rate from steps of .05 Hz to value which can be used as phase increment, 120 //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits 121 //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate; 122 //computing it as below allows rate steps to be evenly spaced 123 //uses 32 bit divide, but only once when new value is selected 124 pChorusData->m_nRate = (EAS_I16) 125 ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); 126 127 //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction 128 //want to compute ((depth * sampleRate)/20000) 129 //use the following approximation since 105/32 is roughly 65536/20000 130 /*lint -e{704} use shift for performance */ 131 pChorusData->m_nDepth = (EAS_I16) 132 (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); 133 134 pChorusData->m_nLevel = pChorusData->m_nLevel; 135 136 //zero delay memory for chorus 137 for (index = CHORUS_L_SIZE - 1; index >= 0; index--) 138 { 139 pChorusData->chorusDelayL[index] = 0; 140 } 141 for (index = CHORUS_R_SIZE - 1; index >= 0; index--) 142 { 143 pChorusData->chorusDelayR[index] = 0; 144 } 145 146 //init delay line index, these are used to implement circular delay buffer 147 pChorusData->chorusIndexL = 0; 148 pChorusData->chorusIndexR = 0; 149 150 //init LFO phase 151 //16 bit whole part, 16 bit fraction 152 pChorusData->lfoLPhase = 0; 153 pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase; 154 155 //init chorus delay position 156 //right now chorus delay is a compile-time value, as is sample rate 157 pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000); 158 159 //now copy from the new preset into Chorus 160 pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; 161 162 pChorusData->m_nLevel = pPreset->m_nLevel; 163 pChorusData->m_nRate = pPreset->m_nRate; 164 pChorusData->m_nDepth = pPreset->m_nDepth; 165 166 pChorusData->m_nRate = (EAS_I16) 167 ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); 168 169 /*lint -e{704} use shift for performance */ 170 pChorusData->m_nDepth = (EAS_I16) 171 (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); 172 173 *pInstData = pChorusData; 174 175 return EAS_SUCCESS; 176} /* end ChorusInit */ 177 178/*---------------------------------------------------------------------------- 179 * WeightedTap() 180 *---------------------------------------------------------------------------- 181 * Purpose: Does fractional array look-up using linear interpolation 182 * 183 * first convert indexDesired to actual desired index by taking into account indexReference 184 * then do linear interpolation between two actual samples using fractional part 185 * 186 * Inputs: 187 * array: pointer to array of signed 16 bit values, typically either PCM data or control data 188 * indexReference: the circular buffer relative offset 189 * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) 190 * indexLimit: the total size of the array, used to compute buffer wrap 191 * 192 * Outputs: 193 * Value from the input array, linearly interpolated between two actual data values 194 * 195 *---------------------------------------------------------------------------- 196*/ 197static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit) 198{ 199 EAS_I16 index; 200 EAS_I16 fraction; 201 EAS_I16 val1; 202 EAS_I16 val2; 203 204 //separate indexDesired into whole and fractional parts 205 /*lint -e{704} use shift for performance */ 206 index = (EAS_I16)(indexDesired >> 16); 207 /*lint -e{704} use shift for performance */ 208 fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part 209 210 //adjust whole part by indexReference 211 index = indexReference - index; 212 //make sure we stay within array bounds, this implements circular buffer 213 while (index < 0) 214 { 215 index += indexLimit; 216 } 217 218 //get two adjacent values from the array 219 val1 = array[index]; 220 221 //handle special case when index == 0, else typical case 222 if (index == 0) 223 { 224 val2 = array[indexLimit-1]; //get last value from array 225 } 226 else 227 { 228 val2 = array[index-1]; //get previous value from array 229 } 230 231 //compute linear interpolation as (val1 + ((val2-val1)*fraction)) 232 return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction)); 233} 234 235/*---------------------------------------------------------------------------- 236 * ChorusProcess() 237 *---------------------------------------------------------------------------- 238 * Purpose: compute the chorus on the input buffer, and mix into output buffer 239 * 240 * 241 * Inputs: 242 * src: pointer to input buffer of PCM values to be processed 243 * dst: pointer to output buffer of PCM values we are to sume the result with 244 * bufSize: the number of sample frames (i.e. stereo samples) in the buffer 245 * 246 * Outputs: 247 * None 248 * 249 *---------------------------------------------------------------------------- 250*/ 251//compute the chorus, and mix into output buffer 252static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) 253{ 254 EAS_I32 ix; 255 EAS_I32 nChannelNumber; 256 EAS_I16 lfoValueLeft; 257 EAS_I16 lfoValueRight; 258 EAS_I32 positionOffsetL; 259 EAS_I32 positionOffsetR; 260 EAS_PCM tapL; 261 EAS_PCM tapR; 262 EAS_I32 tempValue; 263 EAS_PCM nInputSample; 264 EAS_I32 nOutputSample; 265 EAS_PCM *pIn; 266 EAS_PCM *pOut; 267 268 S_CHORUS_OBJECT *pChorusData; 269 270 pChorusData = (S_CHORUS_OBJECT*) pInstData; 271 272 //if the chorus is disabled or turned all the way down 273 if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0) 274 { 275 if (pSrc != pDst) 276 EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); 277 return; 278 } 279 280 if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus) 281 { 282 ChorusUpdate(pChorusData); 283 } 284 285 for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++) 286 { 287 288 pIn = pSrc + nChannelNumber; 289 pOut = pDst + nChannelNumber; 290 291 if(nChannelNumber==0) 292 { 293 for (ix = 0; ix < numSamples; ix++) 294 { 295 nInputSample = *pIn; 296 pIn += NUM_OUTPUT_CHANNELS; 297 298 //feed input into chorus delay line 299 pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample; 300 301 //compute chorus lfo value using phase as fractional index into chorus shape table 302 //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number 303 lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE); 304 305 //scale chorus depth by lfo value to get relative fractional sample index 306 //index is expressed as 32 bit number with 16 bit fractional part 307 /*lint -e{703} use shift for performance */ 308 positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1); 309 310 //add fixed chorus delay to get actual fractional sample index 311 positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16; 312 313 //get tap value from chorus delay using fractional sample index 314 tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE); 315 316 //scale by chorus level, then sum with input buffer contents and saturate 317 tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel); 318 nOutputSample = SATURATE(tempValue + nInputSample); 319 320 *pOut = (EAS_I16)SATURATE(nOutputSample); 321 pOut += NUM_OUTPUT_CHANNELS; 322 323 324 //increment chorus delay index and make it wrap as needed 325 //this implements circular buffer 326 if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE) 327 pChorusData->chorusIndexL = 0; 328 329 //increment fractional lfo phase, and make it wrap as needed 330 pChorusData->lfoLPhase += pChorusData->m_nRate; 331 while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16)) 332 { 333 pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16); 334 } 335 } 336 } 337 else 338 { 339 for (ix = 0; ix < numSamples; ix++) 340 { 341 nInputSample = *pIn; 342 pIn += NUM_OUTPUT_CHANNELS; 343 344 //feed input into chorus delay line 345 pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample; 346 347 //compute chorus lfo value using phase as fractional index into chorus shape table 348 //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number 349 lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE); 350 351 //scale chorus depth by lfo value to get relative fractional sample index 352 //index is expressed as 32 bit number with 16 bit fractional part 353 /*lint -e{703} use shift for performance */ 354 positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1); 355 356 //add fixed chorus delay to get actual fractional sample index 357 positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16; 358 359 //get tap value from chorus delay using fractional sample index 360 tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE); 361 362 //scale by chorus level, then sum with output buffer contents and saturate 363 tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel); 364 nOutputSample = SATURATE(tempValue + nInputSample); 365 366 *pOut = (EAS_I16)SATURATE(nOutputSample); 367 pOut += NUM_OUTPUT_CHANNELS; 368 369 //increment chorus delay index and make it wrap as needed 370 //this implements circular buffer 371 if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE) 372 pChorusData->chorusIndexR = 0; 373 374 //increment fractional lfo phase, and make it wrap as needed 375 pChorusData->lfoRPhase += pChorusData->m_nRate; 376 while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16)) 377 { 378 pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16); 379 } 380 } 381 } 382 383 } 384} /* end ChorusProcess */ 385 386 387 388/*---------------------------------------------------------------------------- 389 * ChorusShutdown() 390 *---------------------------------------------------------------------------- 391 * Purpose: 392 * Initializes the Chorus effect. 393 * 394 * Inputs: 395 * pInstData - handle to instance data 396 * 397 * Outputs: 398 * 399 * 400 * Side Effects: 401 * 402 *---------------------------------------------------------------------------- 403*/ 404static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) 405{ 406 /* check Configuration Module for static memory allocation */ 407 if (!pEASData->staticMemoryModel) 408 EAS_HWFree(pEASData->hwInstData, pInstData); 409 return EAS_SUCCESS; 410} /* end ChorusShutdown */ 411 412/*---------------------------------------------------------------------------- 413 * ChorusGetParam() 414 *---------------------------------------------------------------------------- 415 * Purpose: 416 * Get a Chorus parameter 417 * 418 * Inputs: 419 * pInstData - handle to instance data 420 * param - parameter index 421 * *pValue - pointer to variable to hold retrieved value 422 * 423 * Outputs: 424 * 425 * 426 * Side Effects: 427 * 428 *---------------------------------------------------------------------------- 429*/ 430static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) 431{ 432 S_CHORUS_OBJECT *p; 433 434 p = (S_CHORUS_OBJECT*) pInstData; 435 436 switch (param) 437 { 438 case EAS_PARAM_CHORUS_BYPASS: 439 *pValue = (EAS_I32) p->bypass; 440 break; 441 case EAS_PARAM_CHORUS_PRESET: 442 *pValue = (EAS_I8) p->m_nCurrentChorus; 443 break; 444 case EAS_PARAM_CHORUS_RATE: 445 *pValue = (EAS_I32) p->m_nRate; 446 break; 447 case EAS_PARAM_CHORUS_DEPTH: 448 *pValue = (EAS_I32) p->m_nDepth; 449 break; 450 case EAS_PARAM_CHORUS_LEVEL: 451 *pValue = (EAS_I32) p->m_nLevel; 452 break; 453 default: 454 return EAS_ERROR_INVALID_PARAMETER; 455 } 456 return EAS_SUCCESS; 457} /* end ChorusGetParam */ 458 459 460/*---------------------------------------------------------------------------- 461 * ChorusSetParam() 462 *---------------------------------------------------------------------------- 463 * Purpose: 464 * Set a Chorus parameter 465 * 466 * Inputs: 467 * pInstData - handle to instance data 468 * param - parameter index 469 * *pValue - new paramter value 470 * 471 * Outputs: 472 * 473 * 474 * Side Effects: 475 * 476 *---------------------------------------------------------------------------- 477*/ 478static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) 479{ 480 S_CHORUS_OBJECT *p; 481 482 p = (S_CHORUS_OBJECT*) pInstData; 483 484 switch (param) 485 { 486 case EAS_PARAM_CHORUS_BYPASS: 487 p->bypass = (EAS_BOOL) value; 488 break; 489 case EAS_PARAM_CHORUS_PRESET: 490 if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 && 491 value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4) 492 return EAS_ERROR_INVALID_PARAMETER; 493 p->m_nNextChorus = (EAS_I8)value; 494 break; 495 case EAS_PARAM_CHORUS_RATE: 496 if(value<EAS_CHORUS_RATE_MIN || value>EAS_CHORUS_RATE_MAX) 497 return EAS_ERROR_INVALID_PARAMETER; 498 p->m_nRate = (EAS_I16) value; 499 break; 500 case EAS_PARAM_CHORUS_DEPTH: 501 if(value<EAS_CHORUS_DEPTH_MIN || value>EAS_CHORUS_DEPTH_MAX) 502 return EAS_ERROR_INVALID_PARAMETER; 503 p->m_nDepth = (EAS_I16) value; 504 break; 505 case EAS_PARAM_CHORUS_LEVEL: 506 if(value<EAS_CHORUS_LEVEL_MIN || value>EAS_CHORUS_LEVEL_MAX) 507 return EAS_ERROR_INVALID_PARAMETER; 508 p->m_nLevel = (EAS_I16) value; 509 break; 510 511 default: 512 return EAS_ERROR_INVALID_PARAMETER; 513 } 514 return EAS_SUCCESS; 515} /* end ChorusSetParam */ 516 517 518/*---------------------------------------------------------------------------- 519 * ChorusReadInPresets() 520 *---------------------------------------------------------------------------- 521 * Purpose: sets global Chorus preset bank to defaults 522 * 523 * Inputs: 524 * 525 * Outputs: 526 * 527 *---------------------------------------------------------------------------- 528*/ 529static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData) 530{ 531 532 int preset = 0; 533 int defaultPreset = 0; 534 535 //now init any remaining presets to defaults 536 for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++) 537 { 538 S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset]; 539 if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1) 540 { 541 pPreset->m_nDepth = 39; 542 pPreset->m_nRate = 30; 543 pPreset->m_nLevel = 32767; 544 } 545 else if (defaultPreset == 1) 546 { 547 pPreset->m_nDepth = 21; 548 pPreset->m_nRate = 45; 549 pPreset->m_nLevel = 25000; 550 } 551 else if (defaultPreset == 2) 552 { 553 pPreset->m_nDepth = 53; 554 pPreset->m_nRate = 25; 555 pPreset->m_nLevel = 32000; 556 } 557 else if (defaultPreset == 3) 558 { 559 pPreset->m_nDepth = 32; 560 pPreset->m_nRate = 37; 561 pPreset->m_nLevel = 29000; 562 } 563 } 564 565 return EAS_SUCCESS; 566} 567 568 569/*---------------------------------------------------------------------------- 570 * ChorusUpdate 571 *---------------------------------------------------------------------------- 572 * Purpose: 573 * Update the Chorus preset parameters as required 574 * 575 * Inputs: 576 * 577 * Outputs: 578 * 579 * 580 * Side Effects: 581 * - chorus paramters will be changed 582 * - m_nCurrentRoom := m_nNextRoom 583 *---------------------------------------------------------------------------- 584*/ 585static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData) 586{ 587 S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; 588 589 pChorusData->m_nLevel = pPreset->m_nLevel; 590 pChorusData->m_nRate = pPreset->m_nRate; 591 pChorusData->m_nDepth = pPreset->m_nDepth; 592 593 pChorusData->m_nRate = (EAS_I16) 594 ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); 595 596 /*lint -e{704} use shift for performance */ 597 pChorusData->m_nDepth = (EAS_I16) 598 (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); 599 600 pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus; 601 602 return EAS_SUCCESS; 603 604} /* end ChorusUpdate */ 605