I think there are two issues that could cause your filter to pass through without affecting the sound.
1. In your code, calculate_coefficients()
is called within the sample render function for every sample, which recomputes the filter coefficients on every run. To fix this you need to move calculate_coefficients()
outside the sample loop and call it only when necessary.
And 2nd is; the provided coefficients are for a simple first order low pass filter. If the cutoff frequency is set too high (for eg. close to the Nyquist frequency) the effect may be subtle especially if the input signal doesn't contain many high frequencies.
so here is corrected one:
Coefficient Calculation Function
void calculate_coefficients(float cutoffFreq, float sampleRate, float& a0, float& a1, float& b1) {
float omega = 2.0f * M_PI * cutoffFreq / sampleRate;
float alpha = omega / (omega + 1.0f);
a0 = alpha;
a1 = alpha;
b1 = 1.0f - alpha;
}
Filter Processing Function
float process(float input, float& prevInput, float& prevOutput, float a0, float a1, float b1) {
float output = a0 * input + a1 * prevInput - b1 * prevOutput;
prevInput = input;
prevOutput = output;
return output;
}
Synthesizer Integration
// outside the sample render loop
float ca0, ca1, cb1;
static float prevInput = 0.0f, prevOutput = 0.0f;
// calculate coefficients once, or when cutoff frequency changes
calculate_coefficients(500.0f, 44100.0f, ca0, ca1, cb1);
// in the sample render loop
sond = process(sond, prevInput, prevOutput, ca0, ca1, cb1);
And to implement a second order low pass filter, we use the biquad filter formula. here is how;
Coefficient Calculation for 2nd Order
void calculate_biquad_coefficients(float cutoffFreq, float sampleRate, float Q,
float& a0, float& a1, float& a2, float& b1, float& b2) {
float omega = 2.0f * M_PI * cutoffFreq / sampleRate;
float alpha = sin(omega) / (2.0f * Q);
float cos_omega = cos(omega);
float norm = 1.0f / (1.0f + alpha);
a0 = (1.0f - cos_omega) / 2.0f * norm;
a1 = (1.0f - cos_omega) * norm;
a2 = a0;
b1 = -2.0f * cos_omega * norm;
b2 = (1.0f - alpha) * norm;
}
Filter Processing for 2nd Order
float process_biquad(float input, float& prevInput1, float& prevInput2,
float& prevOutput1, float& prevOutput2,
float a0, float a1, float a2, float b1, float b2) {
float output = a0 * input + a1 * prevInput1 + a2 * prevInput2
- b1 * prevOutput1 - b2 * prevOutput2;
prevInput2 = prevInput1;
prevInput1 = input;
prevOutput2 = prevOutput1;
prevOutput1 = output;
return output;
}
Using the Biquad Filter
// outside the sample render loop
float a0, a1, a2, b1, b2;
static float prevInput1 = 0.0f, prevInput2 = 0.0f;
static float prevOutput1 = 0.0f, prevOutput2 = 0.0f;
// calculate coefficients once or when cutoff frequency changes
calculate_biquad_coefficients(500.0f, 44100.0f, 0.707f, a0, a1, a2, b1, b2);
// in the sample render loop
sond = process_biquad(sond, prevInput1, prevInput2, prevOutput1, prevOutput2, a0, a1, a2, b1, b2);
hope it work as expected…