Home | History | Annotate | Download | only in lib_src
      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 */
     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 */
    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
    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 */
    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 */
    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 */
    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 */
    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 */
    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