Use an inline function to calculate the low-pass filter coefficient
This commit is contained in:
parent
5fcd6cc510
commit
656a406377
36
Alc/ALu.c
36
Alc/ALu.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user