mirror of
https://github.com/id-Software/DOOM-IOS2.git
synced 2026-03-20 08:59:35 +01:00
605 lines
21 KiB
C
Executable File
605 lines
21 KiB
C
Executable File
/*----------------------------------------------------------------------------
|
|
*
|
|
* File:
|
|
* eas_chorus.c
|
|
*
|
|
* Contents and purpose:
|
|
* Contains the implementation of the Chorus effect.
|
|
*
|
|
*
|
|
* Copyright Sonic Network Inc. 2006
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
* Revision Control:
|
|
* $Revision: 499 $
|
|
* $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "eas_data.h"
|
|
#include "eas_effects.h"
|
|
#include "eas_math.h"
|
|
#include "eas_chorusdata.h"
|
|
#include "eas_chorus.h"
|
|
#include "eas_config.h"
|
|
#include "eas_host.h"
|
|
#include "eas_report.h"
|
|
|
|
/* prototypes for effects interface */
|
|
static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData);
|
|
static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples);
|
|
static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData);
|
|
static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue);
|
|
static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value);
|
|
|
|
/* common effects interface for configuration module */
|
|
const S_EFFECTS_INTERFACE EAS_Chorus =
|
|
{
|
|
ChorusInit,
|
|
ChorusProcess,
|
|
ChorusShutdown,
|
|
ChorusGetParam,
|
|
ChorusSetParam
|
|
};
|
|
|
|
|
|
|
|
//LFO shape table used by the chorus, larger table would sound better
|
|
//this is a sine wave, where 32767 = 1.0
|
|
static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = {
|
|
0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170,
|
|
24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728,
|
|
32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329,
|
|
24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212,
|
|
1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519,
|
|
-20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785,
|
|
-32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621,
|
|
-28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010,
|
|
-12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608
|
|
};
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* InitializeChorus()
|
|
*----------------------------------------------------------------------------
|
|
* Purpose: Initializes chorus parameters
|
|
*
|
|
*
|
|
* Inputs:
|
|
*
|
|
* Outputs:
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData)
|
|
{
|
|
S_CHORUS_OBJECT *pChorusData;
|
|
S_CHORUS_PRESET *pPreset;
|
|
EAS_I32 index;
|
|
|
|
/* check Configuration Module for data allocation */
|
|
if (pEASData->staticMemoryModel)
|
|
pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS);
|
|
|
|
/* allocate dynamic memory */
|
|
else
|
|
pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT));
|
|
|
|
if (pChorusData == NULL)
|
|
{
|
|
{ /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ }
|
|
return EAS_ERROR_MALLOC_FAILED;
|
|
}
|
|
|
|
/* clear the structure */
|
|
EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT));
|
|
|
|
ChorusReadInPresets(pChorusData);
|
|
|
|
/* set some default values */
|
|
pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT;
|
|
pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT;
|
|
pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT;
|
|
pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT;
|
|
pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT;
|
|
|
|
//chorus rate and depth need some massaging from preset value (which is sample rate independent)
|
|
|
|
//convert rate from steps of .05 Hz to value which can be used as phase increment,
|
|
//with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits
|
|
//want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate;
|
|
//computing it as below allows rate steps to be evenly spaced
|
|
//uses 32 bit divide, but only once when new value is selected
|
|
pChorusData->m_nRate = (EAS_I16)
|
|
((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
|
|
|
|
//convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction
|
|
//want to compute ((depth * sampleRate)/20000)
|
|
//use the following approximation since 105/32 is roughly 65536/20000
|
|
/*lint -e{704} use shift for performance */
|
|
pChorusData->m_nDepth = (EAS_I16)
|
|
(((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
|
|
|
|
pChorusData->m_nLevel = pChorusData->m_nLevel;
|
|
|
|
//zero delay memory for chorus
|
|
for (index = CHORUS_L_SIZE - 1; index >= 0; index--)
|
|
{
|
|
pChorusData->chorusDelayL[index] = 0;
|
|
}
|
|
for (index = CHORUS_R_SIZE - 1; index >= 0; index--)
|
|
{
|
|
pChorusData->chorusDelayR[index] = 0;
|
|
}
|
|
|
|
//init delay line index, these are used to implement circular delay buffer
|
|
pChorusData->chorusIndexL = 0;
|
|
pChorusData->chorusIndexR = 0;
|
|
|
|
//init LFO phase
|
|
//16 bit whole part, 16 bit fraction
|
|
pChorusData->lfoLPhase = 0;
|
|
pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase;
|
|
|
|
//init chorus delay position
|
|
//right now chorus delay is a compile-time value, as is sample rate
|
|
pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000);
|
|
|
|
//now copy from the new preset into Chorus
|
|
pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus];
|
|
|
|
pChorusData->m_nLevel = pPreset->m_nLevel;
|
|
pChorusData->m_nRate = pPreset->m_nRate;
|
|
pChorusData->m_nDepth = pPreset->m_nDepth;
|
|
|
|
pChorusData->m_nRate = (EAS_I16)
|
|
((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
|
|
|
|
/*lint -e{704} use shift for performance */
|
|
pChorusData->m_nDepth = (EAS_I16)
|
|
(((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
|
|
|
|
*pInstData = pChorusData;
|
|
|
|
return EAS_SUCCESS;
|
|
} /* end ChorusInit */
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* WeightedTap()
|
|
*----------------------------------------------------------------------------
|
|
* Purpose: Does fractional array look-up using linear interpolation
|
|
*
|
|
* first convert indexDesired to actual desired index by taking into account indexReference
|
|
* then do linear interpolation between two actual samples using fractional part
|
|
*
|
|
* Inputs:
|
|
* array: pointer to array of signed 16 bit values, typically either PCM data or control data
|
|
* indexReference: the circular buffer relative offset
|
|
* indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction)
|
|
* indexLimit: the total size of the array, used to compute buffer wrap
|
|
*
|
|
* Outputs:
|
|
* Value from the input array, linearly interpolated between two actual data values
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit)
|
|
{
|
|
EAS_I16 index;
|
|
EAS_I16 fraction;
|
|
EAS_I16 val1;
|
|
EAS_I16 val2;
|
|
|
|
//separate indexDesired into whole and fractional parts
|
|
/*lint -e{704} use shift for performance */
|
|
index = (EAS_I16)(indexDesired >> 16);
|
|
/*lint -e{704} use shift for performance */
|
|
fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part
|
|
|
|
//adjust whole part by indexReference
|
|
index = indexReference - index;
|
|
//make sure we stay within array bounds, this implements circular buffer
|
|
while (index < 0)
|
|
{
|
|
index += indexLimit;
|
|
}
|
|
|
|
//get two adjacent values from the array
|
|
val1 = array[index];
|
|
|
|
//handle special case when index == 0, else typical case
|
|
if (index == 0)
|
|
{
|
|
val2 = array[indexLimit-1]; //get last value from array
|
|
}
|
|
else
|
|
{
|
|
val2 = array[index-1]; //get previous value from array
|
|
}
|
|
|
|
//compute linear interpolation as (val1 + ((val2-val1)*fraction))
|
|
return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction));
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* ChorusProcess()
|
|
*----------------------------------------------------------------------------
|
|
* Purpose: compute the chorus on the input buffer, and mix into output buffer
|
|
*
|
|
*
|
|
* Inputs:
|
|
* src: pointer to input buffer of PCM values to be processed
|
|
* dst: pointer to output buffer of PCM values we are to sume the result with
|
|
* bufSize: the number of sample frames (i.e. stereo samples) in the buffer
|
|
*
|
|
* Outputs:
|
|
* None
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
//compute the chorus, and mix into output buffer
|
|
static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples)
|
|
{
|
|
EAS_I32 ix;
|
|
EAS_I32 nChannelNumber;
|
|
EAS_I16 lfoValueLeft;
|
|
EAS_I16 lfoValueRight;
|
|
EAS_I32 positionOffsetL;
|
|
EAS_I32 positionOffsetR;
|
|
EAS_PCM tapL;
|
|
EAS_PCM tapR;
|
|
EAS_I32 tempValue;
|
|
EAS_PCM nInputSample;
|
|
EAS_I32 nOutputSample;
|
|
EAS_PCM *pIn;
|
|
EAS_PCM *pOut;
|
|
|
|
S_CHORUS_OBJECT *pChorusData;
|
|
|
|
pChorusData = (S_CHORUS_OBJECT*) pInstData;
|
|
|
|
//if the chorus is disabled or turned all the way down
|
|
if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0)
|
|
{
|
|
if (pSrc != pDst)
|
|
EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM));
|
|
return;
|
|
}
|
|
|
|
if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus)
|
|
{
|
|
ChorusUpdate(pChorusData);
|
|
}
|
|
|
|
for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++)
|
|
{
|
|
|
|
pIn = pSrc + nChannelNumber;
|
|
pOut = pDst + nChannelNumber;
|
|
|
|
if(nChannelNumber==0)
|
|
{
|
|
for (ix = 0; ix < numSamples; ix++)
|
|
{
|
|
nInputSample = *pIn;
|
|
pIn += NUM_OUTPUT_CHANNELS;
|
|
|
|
//feed input into chorus delay line
|
|
pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample;
|
|
|
|
//compute chorus lfo value using phase as fractional index into chorus shape table
|
|
//resulting value is between -1.0 and 1.0, expressed as signed 16 bit number
|
|
lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE);
|
|
|
|
//scale chorus depth by lfo value to get relative fractional sample index
|
|
//index is expressed as 32 bit number with 16 bit fractional part
|
|
/*lint -e{703} use shift for performance */
|
|
positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1);
|
|
|
|
//add fixed chorus delay to get actual fractional sample index
|
|
positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16;
|
|
|
|
//get tap value from chorus delay using fractional sample index
|
|
tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE);
|
|
|
|
//scale by chorus level, then sum with input buffer contents and saturate
|
|
tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel);
|
|
nOutputSample = SATURATE(tempValue + nInputSample);
|
|
|
|
*pOut = (EAS_I16)SATURATE(nOutputSample);
|
|
pOut += NUM_OUTPUT_CHANNELS;
|
|
|
|
|
|
//increment chorus delay index and make it wrap as needed
|
|
//this implements circular buffer
|
|
if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE)
|
|
pChorusData->chorusIndexL = 0;
|
|
|
|
//increment fractional lfo phase, and make it wrap as needed
|
|
pChorusData->lfoLPhase += pChorusData->m_nRate;
|
|
while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16))
|
|
{
|
|
pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ix = 0; ix < numSamples; ix++)
|
|
{
|
|
nInputSample = *pIn;
|
|
pIn += NUM_OUTPUT_CHANNELS;
|
|
|
|
//feed input into chorus delay line
|
|
pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample;
|
|
|
|
//compute chorus lfo value using phase as fractional index into chorus shape table
|
|
//resulting value is between -1.0 and 1.0, expressed as signed 16 bit number
|
|
lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE);
|
|
|
|
//scale chorus depth by lfo value to get relative fractional sample index
|
|
//index is expressed as 32 bit number with 16 bit fractional part
|
|
/*lint -e{703} use shift for performance */
|
|
positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1);
|
|
|
|
//add fixed chorus delay to get actual fractional sample index
|
|
positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16;
|
|
|
|
//get tap value from chorus delay using fractional sample index
|
|
tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE);
|
|
|
|
//scale by chorus level, then sum with output buffer contents and saturate
|
|
tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel);
|
|
nOutputSample = SATURATE(tempValue + nInputSample);
|
|
|
|
*pOut = (EAS_I16)SATURATE(nOutputSample);
|
|
pOut += NUM_OUTPUT_CHANNELS;
|
|
|
|
//increment chorus delay index and make it wrap as needed
|
|
//this implements circular buffer
|
|
if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE)
|
|
pChorusData->chorusIndexR = 0;
|
|
|
|
//increment fractional lfo phase, and make it wrap as needed
|
|
pChorusData->lfoRPhase += pChorusData->m_nRate;
|
|
while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16))
|
|
{
|
|
pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
} /* end ChorusProcess */
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* ChorusShutdown()
|
|
*----------------------------------------------------------------------------
|
|
* Purpose:
|
|
* Initializes the Chorus effect.
|
|
*
|
|
* Inputs:
|
|
* pInstData - handle to instance data
|
|
*
|
|
* Outputs:
|
|
*
|
|
*
|
|
* Side Effects:
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData)
|
|
{
|
|
/* check Configuration Module for static memory allocation */
|
|
if (!pEASData->staticMemoryModel)
|
|
EAS_HWFree(pEASData->hwInstData, pInstData);
|
|
return EAS_SUCCESS;
|
|
} /* end ChorusShutdown */
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* ChorusGetParam()
|
|
*----------------------------------------------------------------------------
|
|
* Purpose:
|
|
* Get a Chorus parameter
|
|
*
|
|
* Inputs:
|
|
* pInstData - handle to instance data
|
|
* param - parameter index
|
|
* *pValue - pointer to variable to hold retrieved value
|
|
*
|
|
* Outputs:
|
|
*
|
|
*
|
|
* Side Effects:
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue)
|
|
{
|
|
S_CHORUS_OBJECT *p;
|
|
|
|
p = (S_CHORUS_OBJECT*) pInstData;
|
|
|
|
switch (param)
|
|
{
|
|
case EAS_PARAM_CHORUS_BYPASS:
|
|
*pValue = (EAS_I32) p->bypass;
|
|
break;
|
|
case EAS_PARAM_CHORUS_PRESET:
|
|
*pValue = (EAS_I8) p->m_nCurrentChorus;
|
|
break;
|
|
case EAS_PARAM_CHORUS_RATE:
|
|
*pValue = (EAS_I32) p->m_nRate;
|
|
break;
|
|
case EAS_PARAM_CHORUS_DEPTH:
|
|
*pValue = (EAS_I32) p->m_nDepth;
|
|
break;
|
|
case EAS_PARAM_CHORUS_LEVEL:
|
|
*pValue = (EAS_I32) p->m_nLevel;
|
|
break;
|
|
default:
|
|
return EAS_ERROR_INVALID_PARAMETER;
|
|
}
|
|
return EAS_SUCCESS;
|
|
} /* end ChorusGetParam */
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* ChorusSetParam()
|
|
*----------------------------------------------------------------------------
|
|
* Purpose:
|
|
* Set a Chorus parameter
|
|
*
|
|
* Inputs:
|
|
* pInstData - handle to instance data
|
|
* param - parameter index
|
|
* *pValue - new paramter value
|
|
*
|
|
* Outputs:
|
|
*
|
|
*
|
|
* Side Effects:
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value)
|
|
{
|
|
S_CHORUS_OBJECT *p;
|
|
|
|
p = (S_CHORUS_OBJECT*) pInstData;
|
|
|
|
switch (param)
|
|
{
|
|
case EAS_PARAM_CHORUS_BYPASS:
|
|
p->bypass = (EAS_BOOL) value;
|
|
break;
|
|
case EAS_PARAM_CHORUS_PRESET:
|
|
if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 &&
|
|
value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4)
|
|
return EAS_ERROR_INVALID_PARAMETER;
|
|
p->m_nNextChorus = (EAS_I8)value;
|
|
break;
|
|
case EAS_PARAM_CHORUS_RATE:
|
|
if(value<EAS_CHORUS_RATE_MIN || value>EAS_CHORUS_RATE_MAX)
|
|
return EAS_ERROR_INVALID_PARAMETER;
|
|
p->m_nRate = (EAS_I16) value;
|
|
break;
|
|
case EAS_PARAM_CHORUS_DEPTH:
|
|
if(value<EAS_CHORUS_DEPTH_MIN || value>EAS_CHORUS_DEPTH_MAX)
|
|
return EAS_ERROR_INVALID_PARAMETER;
|
|
p->m_nDepth = (EAS_I16) value;
|
|
break;
|
|
case EAS_PARAM_CHORUS_LEVEL:
|
|
if(value<EAS_CHORUS_LEVEL_MIN || value>EAS_CHORUS_LEVEL_MAX)
|
|
return EAS_ERROR_INVALID_PARAMETER;
|
|
p->m_nLevel = (EAS_I16) value;
|
|
break;
|
|
|
|
default:
|
|
return EAS_ERROR_INVALID_PARAMETER;
|
|
}
|
|
return EAS_SUCCESS;
|
|
} /* end ChorusSetParam */
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* ChorusReadInPresets()
|
|
*----------------------------------------------------------------------------
|
|
* Purpose: sets global Chorus preset bank to defaults
|
|
*
|
|
* Inputs:
|
|
*
|
|
* Outputs:
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData)
|
|
{
|
|
|
|
int preset = 0;
|
|
int defaultPreset = 0;
|
|
|
|
//now init any remaining presets to defaults
|
|
for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++)
|
|
{
|
|
S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset];
|
|
if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1)
|
|
{
|
|
pPreset->m_nDepth = 39;
|
|
pPreset->m_nRate = 30;
|
|
pPreset->m_nLevel = 32767;
|
|
}
|
|
else if (defaultPreset == 1)
|
|
{
|
|
pPreset->m_nDepth = 21;
|
|
pPreset->m_nRate = 45;
|
|
pPreset->m_nLevel = 25000;
|
|
}
|
|
else if (defaultPreset == 2)
|
|
{
|
|
pPreset->m_nDepth = 53;
|
|
pPreset->m_nRate = 25;
|
|
pPreset->m_nLevel = 32000;
|
|
}
|
|
else if (defaultPreset == 3)
|
|
{
|
|
pPreset->m_nDepth = 32;
|
|
pPreset->m_nRate = 37;
|
|
pPreset->m_nLevel = 29000;
|
|
}
|
|
}
|
|
|
|
return EAS_SUCCESS;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* ChorusUpdate
|
|
*----------------------------------------------------------------------------
|
|
* Purpose:
|
|
* Update the Chorus preset parameters as required
|
|
*
|
|
* Inputs:
|
|
*
|
|
* Outputs:
|
|
*
|
|
*
|
|
* Side Effects:
|
|
* - chorus paramters will be changed
|
|
* - m_nCurrentRoom := m_nNextRoom
|
|
*----------------------------------------------------------------------------
|
|
*/
|
|
static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData)
|
|
{
|
|
S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus];
|
|
|
|
pChorusData->m_nLevel = pPreset->m_nLevel;
|
|
pChorusData->m_nRate = pPreset->m_nRate;
|
|
pChorusData->m_nDepth = pPreset->m_nDepth;
|
|
|
|
pChorusData->m_nRate = (EAS_I16)
|
|
((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate);
|
|
|
|
/*lint -e{704} use shift for performance */
|
|
pChorusData->m_nDepth = (EAS_I16)
|
|
(((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16);
|
|
|
|
pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus;
|
|
|
|
return EAS_SUCCESS;
|
|
|
|
} /* end ChorusUpdate */
|