Use an inline function to calculate the low-pass filter coefficient

This commit is contained in:
Chris Robinson 2009-12-09 07:21:59 -08:00
parent 5fcd6cc510
commit 656a406377
3 changed files with 29 additions and 54 deletions

View File

@ -412,8 +412,8 @@ static ALvoid CalcNonAttnSourceParams(const ALCcontext *ALContext, ALsource *ALS
ALfloat WetGain[MAX_SENDS];
ALfloat WetGainHF[MAX_SENDS];
ALint NumSends, Frequency;
ALfloat cw;
ALint i;
ALfloat cw, a, g;
//Get context properties
NumSends = ALContext->Device->NumAuxSends;
@ -479,27 +479,16 @@ static ALvoid CalcNonAttnSourceParams(const ALCcontext *ALContext, ALsource *ALS
/* Update filter coefficients. Calculations based on the I3DL2
* spec. */
cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Frequency);
/* We use two chained one-pole filters, so we need to take the
* square root of the squared gain, which is the same as the base
* gain. */
g = __max(DryGainHF, 0.01f);
a = 0.0f;
/* Be careful with gains < 0.0001, as that causes the coefficient
* head towards 1, which will flatten the signal */
if(g < 0.9999f) /* 1-epsilon */
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
(1 - g);
ALSource->Params.iirFilter.coeff = a;
ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw);
for(i = 0;i < NumSends;i++)
{
/* We use a one-pole filter, so we need to take the squared gain */
g = __max(WetGainHF[i], 0.1f);
g *= g;
a = 0.0f;
if(g < 0.9999f) /* 1-epsilon */
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
(1 - g);
ALfloat a = lpCoeffCalc(WetGainHF[i]*WetGainHF[i], cw);
ALSource->Params.Send[i].iirFilter.coeff = a;
}
}
@ -526,7 +515,7 @@ static ALvoid CalcSourceParams(const ALCcontext *ALContext, ALsource *ALSource)
ALuint Frequency;
ALint NumSends;
ALint pos, s, i;
ALfloat cw, a, g;
ALfloat cw;
for(i = 0;i < MAX_SENDS;i++)
WetGainHF[i] = 1.0f;
@ -862,26 +851,17 @@ static ALvoid CalcSourceParams(const ALCcontext *ALContext, ALsource *ALSource)
/* Update filter coefficients. */
cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Frequency);
/* Spatialized sources use four chained one-pole filters, so we need to
* take the fourth root of the squared gain, which is the same as the
* square root of the base gain. */
g = aluSqrt(__max(DryGainHF, 0.0001f));
a = 0.0f;
if(g < 0.9999f) /* 1-epsilon */
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
(1 - g);
ALSource->Params.iirFilter.coeff = a;
ALSource->Params.iirFilter.coeff = lpCoeffCalc(aluSqrt(DryGainHF), cw);
for(i = 0;i < NumSends;i++)
{
/* The wet path uses two chained one-pole filters, so take the
* base gain (square root of the squared gain) */
g = __max(WetGainHF[i], 0.01f);
a = 0.0f;
if(g < 0.9999f) /* 1-epsilon */
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
(1 - g);
ALSource->Params.Send[i].iirFilter.coeff = a;
ALSource->Params.Send[i].iirFilter.coeff = lpCoeffCalc(WetGainHF[i], cw);
}
}

View File

@ -328,24 +328,6 @@ static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency)
return cos(2.0f * M_PI * hfRef / frequency);
}
/* Calculate the I3DL2 coefficient given the gain and frequency parameters.
* To allow for optimization when using multiple chained filters, the gain
* is not squared in this function. Callers using a single filter should
* square it to produce the correct coefficient. Those using multiple
* filters should find its N-1 root (where N is the number of chained
* filters).
*/
static __inline ALfloat CalcI3DL2Coeff(ALfloat g, ALfloat cw)
{
ALfloat coeff;
coeff = 0.0f;
if(g < 0.9999f) // 1-epsilon
coeff = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g);
return coeff;
}
// Calculate an attenuation to be applied to the input of any echo models to
// compensate for modal density and decay time.
static __inline ALfloat CalcDensityGain(ALfloat a)
@ -417,11 +399,10 @@ static __inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloa
// Calculate the low-pass coefficient by dividing the HF decay
// coefficient by the full decay coefficient.
g = CalcDecayCoeff(length, decayTime * hfRatio) / decayCoeff;
g = __max(g, 0.1f);
// Damping is done with a 1-pole filter, so g needs to be squared.
g *= g;
coeff = CalcI3DL2Coeff(g, cw);
coeff = lpCoeffCalc(g, cw);
// Very low decay times will produce minimal output, so apply an
// upper bound to the coefficient.
@ -1067,13 +1048,12 @@ static ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeff
{
ALverbState *State = (ALverbState*)effect;
ALuint frequency = Context->Device->Frequency;
ALfloat cw, g, x, y, hfRatio;
ALfloat cw, x, y, hfRatio;
// Calculate the master low-pass filter (from the master effect HF gain).
cw = CalcI3DL2HFreq(Effect->Reverb.HFReference, frequency);
g = __max(Effect->Reverb.GainHF, 0.0001f);
// This is done with 2 chained 1-pole filters, so no need to square g.
State->LpFilter.coeff = CalcI3DL2Coeff(g, cw);
State->LpFilter.coeff = lpCoeffCalc(Effect->Reverb.GainHF, cw);
// Update the initial effect delay.
UpdateDelayLine(Effect->Reverb.ReflectionsDelay,
@ -1110,13 +1090,12 @@ static ALvoid EAXVerbUpdate(ALeffectState *effect, ALCcontext *Context, const AL
{
ALverbState *State = (ALverbState*)effect;
ALuint frequency = Context->Device->Frequency;
ALfloat cw, g, x, y, hfRatio;
ALfloat cw, x, y, hfRatio;
// Calculate the master low-pass filter (from the master effect HF gain).
cw = CalcI3DL2HFreq(Effect->Reverb.HFReference, frequency);
g = __max(Effect->Reverb.GainHF, 0.0001f);
// This is done with 2 chained 1-pole filters, so no need to square g.
State->LpFilter.coeff = CalcI3DL2Coeff(g, cw);
State->LpFilter.coeff = lpCoeffCalc(Effect->Reverb.GainHF, cw);
// Update the modulator line.
UpdateModulator(Effect->Reverb.ModulationTime,

View File

@ -61,6 +61,22 @@ static __inline ALfloat lpFilter1P(FILTER *iir, ALuint offset, ALfloat input)
return output;
}
/* Calculates the low-pass filter coefficient given the pre-scaled gain and
* cos(w) value. Note that g should be pre-scaled (sqr(gain) for one-pole,
* sqrt(gain) for four-pole, etc) */
static __inline ALfloat lpCoeffCalc(ALfloat g, ALfloat cw)
{
ALfloat a = 0.0f;
/* Be careful with gains < 0.01, as that causes the coefficient
* head towards 1, which will flatten the signal */
g = __max(g, 0.01f);
if(g < 0.9999f) /* 1-epsilon */
a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) /
(1 - g);
return a;
}
#define AL_FILTER_TYPE 0x8001