二阶IIR滤波器C代码实现
#define PI 3.14159265358979323846 typedef double sample_t; enum { BIQUAD_LOWPASS, BIQUAD_HIGHPASS, BIQUAD_BANDPASS_PEAK, }; typedef struct { sample_t a0, a1, a2, a3, a4; sample_t x1, x2, y1, y2; }biquad_state; // 计算滤波器的系数,2nd-order Butterworth: q_value=0.7071 ,2nd-order Chebyshev (ripple 1 dB): q_value=0.9565,2nd-order Thomson-Bessel: // q_value=0.5773。带通滤波器的q_value = sqrt(f1*f2)/(f2-f1),fs是指信号的采样频率,fc为cutoff frequence 或者是centern frequenc(带通滤波器) void filter_init(biquad_state *state, int type, int fs, float fc, float q_value) { sample_t w0, sin_w0, cos_w0, alpha; sample_t b0, b1, b2, a0, a1, a2; w0 = 2 * PI * fc / fs; sin_w0 = sin(w0); cos_w0 = cos(w0); alpha = sin_w0 / (2.0 * q_value); switch(type) { case BIQUAD_LOWPASS: b0 = (1.0 - cos_w0) / 2.0; b1 = b0 * 2; b2 = b0; a0 = 1.0 + alpha; a1 = -2.0 * cos_w0; a2 = 1.0 - alpha; break; case BIQUAD_HIGHPASS: b0 = (1.0 + cos_w0) / 2.0; b1 = -b0 * 2; b2 = b0; a0 = 1.0 + alpha; a1 = -2.0 * cos_w0; a2 = 1.0 - alpha; break; case BIQUAD_BANDPASS_PEAK: b0 = alpha; b1 = 0.0; b2 = -alpha; a0 = 1.0 + alpha; a1 = -2.0 * cos_w0; a2 = 1.0 - alpha; break; } state->a0 = b0 / a0; state->a1 = b1 / a0; state->a2 = b2 / a0; state->a3 = a1 / a0; state->a4 = a2 / a0; state->x1 = state->x2 = 0.0; state->y1 = state->y2 = 0.0; } //biquard滤波 sample_t biquad(biquad_state *state, sample_t data) { sample_t result = 0; result = state->a0 * data + state->a1 * state->x1 + state->a2 * state->x2 - state->a3 * state->y1 - state->a4 * state->y2; state->x2 = state->x1; state->x1 = data; state->y2 = state->y1; state->y1 = result; return result; }
int main(int argc, char **argv) { biquad_state *stat = (biquad_state *) malloc(sizeof(biquad_state)); int numbers = 1024; float fs = 1024; sample_t data[numbers], filter_data[numbers]; float fc = 50; float q_value = 0.7071; int type = BIQUAD_LOWPASS; filter_init(stat, type, fs, fc, q_value); for (int i = 0; i <numbers; ++i) { data[i] = 0.5 * (sin(2 * PI * 40 * i / fs) + cos(2 * PI * 150 * i / fs + PI / 4)); } for (int i = 0; i <numbers; ++i) { filter_data[i] = biquad(stat, data[i]); } free(stat); }