Clean up the biquad filter a bit

This commit is contained in:
Chris Robinson
2018-11-19 09:10:36 -08:00
parent 07386e79de
commit 387a34ca00
8 changed files with 49 additions and 50 deletions
+4 -4
View File
@@ -973,11 +973,11 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
if(gainHF != 1.0f) voice->Direct.FilterType |= AF_LowPass;
if(gainLF != 1.0f) voice->Direct.FilterType |= AF_HighPass;
BiquadFilter_setParams(
&voice->Direct.Params[0].LowPass, BiquadType_HighShelf,
&voice->Direct.Params[0].LowPass, BiquadType::HighShelf,
gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
);
BiquadFilter_setParams(
&voice->Direct.Params[0].HighPass, BiquadType_LowShelf,
&voice->Direct.Params[0].HighPass, BiquadType::LowShelf,
gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
);
for(c = 1;c < num_channels;c++)
@@ -999,11 +999,11 @@ static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALflo
if(gainHF != 1.0f) voice->Send[i].FilterType |= AF_LowPass;
if(gainLF != 1.0f) voice->Send[i].FilterType |= AF_HighPass;
BiquadFilter_setParams(
&voice->Send[i].Params[0].LowPass, BiquadType_HighShelf,
&voice->Send[i].Params[0].LowPass, BiquadType::HighShelf,
gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
);
BiquadFilter_setParams(
&voice->Send[i].Params[0].HighPass, BiquadType_LowShelf,
&voice->Send[i].Params[0].HighPass, BiquadType::LowShelf,
gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
);
for(c = 1;c < num_channels;c++)
+2 -2
View File
@@ -93,14 +93,14 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCcontex
/* Multiply sampling frequency by the amount of oversampling done during
* processing.
*/
BiquadFilter_setParams(&state->lowpass, BiquadType_LowPass, 1.0f,
BiquadFilter_setParams(&state->lowpass, BiquadType::LowPass, 1.0f,
cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
);
cutoff = props->Distortion.EQCenter;
/* Convert bandwidth in Hz to octaves. */
bandwidth = props->Distortion.EQBandwidth / (cutoff * 0.67f);
BiquadFilter_setParams(&state->bandpass, BiquadType_BandPass, 1.0f,
BiquadFilter_setParams(&state->bandpass, BiquadType::BandPass, 1.0f,
cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
);
+1 -1
View File
@@ -136,7 +136,7 @@ static ALvoid ALechoState_update(ALechoState *state, const ALCcontext *context,
state->FeedGain = props->Echo.Feedback;
gainhf = maxf(1.0f - props->Echo.Damping, 0.0625f); /* Limit -24dB */
BiquadFilter_setParams(&state->Filter, BiquadType_HighShelf,
BiquadFilter_setParams(&state->Filter, BiquadType::HighShelf,
gainhf, LOWPASSFREQREF/frequency, calc_rcpQ_from_slope(gainhf, 1.0f)
);
+4 -4
View File
@@ -136,13 +136,13 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCcontext
*/
gain = maxf(sqrtf(props->Equalizer.LowGain), 0.0625f); /* Limit -24dB */
f0norm = props->Equalizer.LowCutoff/frequency;
BiquadFilter_setParams(&state->Chans[0].filter[0], BiquadType_LowShelf,
BiquadFilter_setParams(&state->Chans[0].filter[0], BiquadType::LowShelf,
gain, f0norm, calc_rcpQ_from_slope(gain, 0.75f)
);
gain = maxf(props->Equalizer.Mid1Gain, 0.0625f);
f0norm = props->Equalizer.Mid1Center/frequency;
BiquadFilter_setParams(&state->Chans[0].filter[1], BiquadType_Peaking,
BiquadFilter_setParams(&state->Chans[0].filter[1], BiquadType::Peaking,
gain, f0norm, calc_rcpQ_from_bandwidth(
f0norm, props->Equalizer.Mid1Width
)
@@ -150,7 +150,7 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCcontext
gain = maxf(props->Equalizer.Mid2Gain, 0.0625f);
f0norm = props->Equalizer.Mid2Center/frequency;
BiquadFilter_setParams(&state->Chans[0].filter[2], BiquadType_Peaking,
BiquadFilter_setParams(&state->Chans[0].filter[2], BiquadType::Peaking,
gain, f0norm, calc_rcpQ_from_bandwidth(
f0norm, props->Equalizer.Mid2Width
)
@@ -158,7 +158,7 @@ static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCcontext
gain = maxf(sqrtf(props->Equalizer.HighGain), 0.0625f);
f0norm = props->Equalizer.HighCutoff/frequency;
BiquadFilter_setParams(&state->Chans[0].filter[3], BiquadType_HighShelf,
BiquadFilter_setParams(&state->Chans[0].filter[3], BiquadType::HighShelf,
gain, f0norm, calc_rcpQ_from_slope(gain, 0.75f)
);
+1 -1
View File
@@ -152,7 +152,7 @@ static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCcontext
f0norm = props->Modulator.HighPassCutoff / (ALfloat)device->Frequency;
f0norm = clampf(f0norm, 1.0f/512.0f, 0.49f);
/* Bandwidth value is constant in octaves. */
BiquadFilter_setParams(&state->Chans[0].Filter, BiquadType_HighPass, 1.0f,
BiquadFilter_setParams(&state->Chans[0].Filter, BiquadType::HighPass, 1.0f,
f0norm, calc_rcpQ_from_bandwidth(f0norm, 0.75f));
for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
BiquadFilter_copyParams(&state->Chans[i].Filter, &state->Chans[0].Filter);
+4 -4
View File
@@ -728,9 +728,9 @@ static void CalcT60DampingCoeffs(const ALfloat length, const ALfloat lfDecayTime
ALfloat hfGain = CalcDecayCoeff(length, hfDecayTime);
filter->MidGain[1] = mfGain;
BiquadFilter_setParams(&filter->LFFilter, BiquadType_LowShelf, lfGain/mfGain, lf0norm,
BiquadFilter_setParams(&filter->LFFilter, BiquadType::LowShelf, lfGain/mfGain, lf0norm,
calc_rcpQ_from_slope(lfGain/mfGain, 1.0f));
BiquadFilter_setParams(&filter->HFFilter, BiquadType_HighShelf, hfGain/mfGain, hf0norm,
BiquadFilter_setParams(&filter->HFFilter, BiquadType::HighShelf, hfGain/mfGain, hf0norm,
calc_rcpQ_from_slope(hfGain/mfGain, 1.0f));
}
@@ -964,11 +964,11 @@ static void ReverbState_update(ReverbState *State, const ALCcontext *Context, co
* killing most of the signal.
*/
gainhf = maxf(props->Reverb.GainHF, 0.001f);
BiquadFilter_setParams(&State->Filter[0].Lp, BiquadType_HighShelf, gainhf, hf0norm,
BiquadFilter_setParams(&State->Filter[0].Lp, BiquadType::HighShelf, gainhf, hf0norm,
calc_rcpQ_from_slope(gainhf, 1.0f));
lf0norm = minf(props->Reverb.LFReference / frequency, 0.49f);
gainlf = maxf(props->Reverb.GainLF, 0.001f);
BiquadFilter_setParams(&State->Filter[0].Hp, BiquadType_LowShelf, gainlf, lf0norm,
BiquadFilter_setParams(&State->Filter[0].Hp, BiquadType::LowShelf, gainlf, lf0norm,
calc_rcpQ_from_slope(gainlf, 1.0f));
for(i = 1;i < NUM_LINES;i++)
{
+20 -23
View File
@@ -1,12 +1,11 @@
#ifndef ALC_FILTER_H
#define ALC_FILTER_H
#include <cmath>
#include "AL/al.h"
#include "math_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Filters implementation is based on the "Cookbook formulae for audio
* EQ biquad filter coefficients" by Robert Bristow-Johnson
@@ -18,28 +17,30 @@ extern "C" {
* the square root of the desired linear gain (or halve the dB gain).
*/
typedef enum BiquadType {
enum class BiquadType {
/** EFX-style low-pass filter, specifying a gain and reference frequency. */
BiquadType_HighShelf,
HighShelf,
/** EFX-style high-pass filter, specifying a gain and reference frequency. */
BiquadType_LowShelf,
LowShelf,
/** Peaking filter, specifying a gain and reference frequency. */
BiquadType_Peaking,
Peaking,
/** Low-pass cut-off filter, specifying a cut-off frequency. */
BiquadType_LowPass,
LowPass,
/** High-pass cut-off filter, specifying a cut-off frequency. */
BiquadType_HighPass,
HighPass,
/** Band-pass filter, specifying a center frequency. */
BiquadType_BandPass,
} BiquadType;
BandPass,
};
typedef struct BiquadFilter {
ALfloat z1, z2; /* Last two delayed components for direct form II. */
ALfloat b0, b1, b2; /* Transfer function coefficients "b" (numerator) */
ALfloat a1, a2; /* Transfer function coefficients "a" (denominator; a0 is
* pre-applied). */
} BiquadFilter;
struct BiquadFilter {
/* Last two delayed components for direct form II. */
ALfloat z1{0.0f}, z2{0.0f};
/* Transfer function coefficients "b" (numerator) */
ALfloat b0{1.0f}, b1{0.0f}, b2{0.0f};
/* Transfer function coefficients "a" (denominator; a0 is pre-applied). */
ALfloat a1{0.0f}, a2{0.0f};
};
/* Currently only a C-based filter process method is implemented. */
#define BiquadFilter_process BiquadFilter_processC
@@ -51,7 +52,7 @@ typedef struct BiquadFilter {
*/
inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope)
{
return sqrtf((gain + 1.0f/gain)*(1.0f/slope - 1.0f) + 2.0f);
return std::sqrt((gain + 1.0f/gain)*(1.0f/slope - 1.0f) + 2.0f);
}
/**
* Calculates the rcpQ (i.e. 1/Q) coefficient for filters, using the normalized
@@ -62,7 +63,7 @@ inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope)
inline ALfloat calc_rcpQ_from_bandwidth(ALfloat f0norm, ALfloat bandwidth)
{
ALfloat w0 = F_TAU * f0norm;
return 2.0f*sinhf(logf(2.0f)/2.0f*bandwidth*w0/sinf(w0));
return 2.0f*std::sinh(std::log(2.0f)/2.0f*bandwidth*w0/std::sin(w0));
}
inline void BiquadFilter_clear(BiquadFilter *filter)
@@ -113,8 +114,4 @@ inline void BiquadFilter_passthru(BiquadFilter *filter, ALsizei numsamples)
}
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ALC_FILTER_H */
+13 -11
View File
@@ -1,6 +1,8 @@
#include "config.h"
#include <cmath>
#include "AL/alc.h"
#include "AL/al.h"
@@ -19,15 +21,15 @@ void BiquadFilter_setParams(BiquadFilter *filter, BiquadType type, ALfloat gain,
assert(gain > 0.00001f);
w0 = F_TAU * f0norm;
sin_w0 = sinf(w0);
cos_w0 = cosf(w0);
sin_w0 = std::sin(w0);
cos_w0 = std::cos(w0);
alpha = sin_w0/2.0f * rcpQ;
/* Calculate filter coefficients depending on filter type */
switch(type)
{
case BiquadType_HighShelf:
sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
case BiquadType::HighShelf:
sqrtgain_alpha_2 = 2.0f * std::sqrt(gain) * alpha;
b[0] = gain*((gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cos_w0 );
b[2] = gain*((gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
@@ -35,8 +37,8 @@ void BiquadFilter_setParams(BiquadFilter *filter, BiquadType type, ALfloat gain,
a[1] = 2.0f* ((gain-1.0f) - (gain+1.0f)*cos_w0 );
a[2] = (gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
break;
case BiquadType_LowShelf:
sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
case BiquadType::LowShelf:
sqrtgain_alpha_2 = 2.0f * std::sqrt(gain) * alpha;
b[0] = gain*((gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
b[1] = 2.0f*gain*((gain-1.0f) - (gain+1.0f)*cos_w0 );
b[2] = gain*((gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
@@ -44,8 +46,8 @@ void BiquadFilter_setParams(BiquadFilter *filter, BiquadType type, ALfloat gain,
a[1] = -2.0f* ((gain-1.0f) + (gain+1.0f)*cos_w0 );
a[2] = (gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
break;
case BiquadType_Peaking:
gain = sqrtf(gain);
case BiquadType::Peaking:
gain = std::sqrt(gain);
b[0] = 1.0f + alpha * gain;
b[1] = -2.0f * cos_w0;
b[2] = 1.0f - alpha * gain;
@@ -54,7 +56,7 @@ void BiquadFilter_setParams(BiquadFilter *filter, BiquadType type, ALfloat gain,
a[2] = 1.0f - alpha / gain;
break;
case BiquadType_LowPass:
case BiquadType::LowPass:
b[0] = (1.0f - cos_w0) / 2.0f;
b[1] = 1.0f - cos_w0;
b[2] = (1.0f - cos_w0) / 2.0f;
@@ -62,7 +64,7 @@ void BiquadFilter_setParams(BiquadFilter *filter, BiquadType type, ALfloat gain,
a[1] = -2.0f * cos_w0;
a[2] = 1.0f - alpha;
break;
case BiquadType_HighPass:
case BiquadType::HighPass:
b[0] = (1.0f + cos_w0) / 2.0f;
b[1] = -(1.0f + cos_w0);
b[2] = (1.0f + cos_w0) / 2.0f;
@@ -70,7 +72,7 @@ void BiquadFilter_setParams(BiquadFilter *filter, BiquadType type, ALfloat gain,
a[1] = -2.0f * cos_w0;
a[2] = 1.0f - alpha;
break;
case BiquadType_BandPass:
case BiquadType::BandPass:
b[0] = alpha;
b[1] = 0;
b[2] = -alpha;