#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);
}
|