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