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 */
41 static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
42 static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples);
43 static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
44 static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
45 static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
46
47 /* common effects interface for configuration module */
48 const 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
61 static 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 */
ChorusInit(EAS_DATA_HANDLE pEASData,EAS_VOID_PTR * pInstData)85 static 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 */
WeightedTap(const EAS_I16 * array,EAS_I16 indexReference,EAS_I32 indexDesired,EAS_I16 indexLimit)197 static 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
ChorusProcess(EAS_VOID_PTR pInstData,EAS_PCM * pSrc,EAS_PCM * pDst,EAS_I32 numSamples)252 static 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 */
ChorusShutdown(EAS_DATA_HANDLE pEASData,EAS_VOID_PTR pInstData)404 static 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 */
ChorusGetParam(EAS_VOID_PTR pInstData,EAS_I32 param,EAS_I32 * pValue)430 static 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 */
ChorusSetParam(EAS_VOID_PTR pInstData,EAS_I32 param,EAS_I32 value)478 static 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 */
ChorusReadInPresets(S_CHORUS_OBJECT * pChorusData)529 static 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 */
ChorusUpdate(S_CHORUS_OBJECT * pChorusData)585 static 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