我正在用C语言实现FIR低通滤波器。音频来自 Zynq Zedboard,并且是实时的。如果我运行该应用程序,我会得到很多噪音。但我不知道信号是如何失真的。我是否需要音频缓冲区来保存处理后的样本?还是我只有蹩脚的代码?我分析了代码中的几乎所有元素,但无法理解它......
这是函数调用
#define FILTER_LEN_LP 44
int32_t coeffsLPF[ FILTER_LEN_LP ] =
{
87, 76, 106, 143, 185, 234, 289, 349,
414, 483, 555, 628, 701, 773, 842, 907,
966, 1017, 1060, 1093, 1115, 1126, 1126,
1115, 1093, 1060, 1017, 966, 907, 842, 773,
701, 628, 555, 483, 414, 349, 289, 234, 185,
143, 106, 76, 87
};
void low_pass_filter(){
int k = 0;
int filter_length = FILTER_LEN_LP;
int32_t *coeffp; // pointer to coefficients
int32_t in_left;
while (!XUartPs_IsReceiveData(UART_BASEADDR)) {
int32_t out_left;
int32_t acc; // accumulator
in_left = Xil_In32(I2S_DATA_RX_L_REG);
//printf("%drn", in_left);
coeffp = coeffsLPF;
acc = 1 << 14 ;
for ( k = 0; k < filter_length; k++ )
{
acc += (int32_t)(*coeffp++) * (int32_t)(in_left);
}
//printf("%drn", acc);
//printf("rn");
// saturate the result
// 32768^2
if ( acc > 1073741823)
{
acc = 1073741823;
} else if ( acc < -1073741824 ){
acc = -1073741824;
}
out_left = (int32_t) (acc >> 13);
//xil_printf("%dnr", out_left);
//in_right = Xil_In32(I2S_DATA_RX_R_REG);
Xil_Out32(I2S_DATA_TX_L_REG, out_left);
//Xil_Out32(I2S_DATA_TX_R_REG, in_right);
}
// break
if(XUartPs_ReadReg(UART_BASEADDR, XUARTPS_FIFO_OFFSET) == 'q') menu();
else low_pass_filter();
}
FIR 滤波器的公式为:
y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2]...
要计算一个输出,您需要最后 44 个输入样本,并将其与滤波器系数相乘和累加。我的建议是使用大小为 44 的环形缓冲区来存储输入样本。分配一个环形缓冲区并将其初始化为零。
ring_buffer[FILTER_LEN_LP] = {0};
rb_index = 0;
,然后使用以下示例代码存储输入示例并计算输出。
ring_buffer[rb_idx] = Xil_In32(I2S_DATA_RX_L_REG);
rb_idx = (rb_idx + 1) % filter_length;
for (k=0; k<filter_length; k++) {
acc += (int32_t)(*coeffp++) * (int32_t)(ring_buffer[(k+rb_idx)%filter_length]);
}