二阶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);
}        

  

  

posted @ 2020-12-02 17:44  繁华如梦个人笔记  阅读(2521)  评论(0编辑  收藏  举报