C++实现IIR数字滤波器(附带源码)
一、项目背景详细介绍
在信号处理领域,滤波器(Filter) 是核心工具之一,用于从信号中去除噪声、提取有用频率分量或平滑时间序列。滤波器可分为两大类:
-
FIR(Finite Impulse Response)有限脉冲响应滤波器
-
IIR(Infinite Impulse Response)无限脉冲响应滤波器
FIR 滤波器的特点是结构稳定、线性相位、实现简单,但阶数高、计算量大;
而 IIR 滤波器具有阶数低、性能强、计算量小的优点,是许多实时信号处理(音频处理、传感器数据滤波、控制系统等)中的主力算法。
为什么要自己实现 IIR 滤波器?
在嵌入式系统或算法验证中,我们往往不能直接依赖 MATLAB / Python SciPy 等高层工具,需要在 C/C++ 环境中实现可嵌入的滤波器。
而理解并实现一套 IIR 数字滤波器框架,不仅可以用于信号处理,还能深入理解差分方程、系统函数、Z 域传递函数 等数字信号处理核心概念。
本项目目标是实现一个可扩展、可配置的 C++ IIR 滤波器类,支持:
-
任意阶 IIR 滤波器;
-
支持典型滤波器设计(低通、高通、带通);
-
支持通过传递函数系数 a、b 实例化;
-
支持实时单点滤波与整段信号滤波;
-
支持双精度浮点计算;
-
输出频率响应与滤波前后信号可视化(可选)。
二、项目需求详细介绍
功能性需求
三、相关技术详细介绍
四、实现思路详细介绍
实现步骤如下:
-
定义 IIRFilter 类
-
存储向量
a_、b_、z_(状态延迟线); -
构造函数传入系数;
-
提供
filterSample()处理单个样本; -
提供
filterSignal()处理整个数组。
-
-
系数设计函数
-
butterworthLowpass(fc, fs, order):计算标准化二阶低通系数; -
butterworthHighpass(fc, fs, order):高通滤波器; -
(可选)带通设计。
-
-
信号测试模块
-
生成带噪正弦波;
-
调用滤波器平滑;
-
保存结果到文件。
-
-
可视化结果
-
用 Python/Matlab 绘图,或输出到
.csv文件。
-
五、完整实现代码
/********************************************************************
* 文件名: iir_filter.cpp
* 功能: C++ 实现 IIR 数字滤波器(含巴特沃斯低通、高通示例)
* 编译: g++ -std=c++17 iir_filter.cpp -O2 -o iir
* 运行: ./iir
* 输出: filter_result.csv (输入信号与输出信号)
********************************************************************/
#include <bits/stdc++.h>
using namespace std;
/**************************************************************
* IIR 滤波器类 - Direct Form II 结构实现
**************************************************************/
class IIRFilter {
private:
vector<double> a_; // 分母系数 (a0=1)
vector<double> b_; // 分子系数
vector<double> z_; // 延迟线状态
public:
// 构造函数
IIRFilter(const vector<double>& b, const vector<double>& a)
: a_(a), b_(b)
{
int order = max(a_.size(), b_.size());
z_.assign(order, 0.0);
}
// 过滤单个样本
double filterSample(double x) {
// Direct Form II Transposed 实现
double w = x - a_[1]*z_[0];
double y = b_[0]*w + b_[1]*z_[0];
// 更新状态
z_[0] = w;
return y;
}
// 过滤整段信号
vector<double> filterSignal(const vector<double>& x) {
vector<double> y(x.size());
for (size_t i=0;i<x.size();++i)
y[i] = filterSample(x[i]);
return y;
}
// 重置状态
void reset() {
fill(z_.begin(), z_.end(), 0.0);
}
};
/**************************************************************
* 一阶巴特沃斯滤波器设计(低通、高通)
* 公式来源:双线性变换法
**************************************************************/
struct FilterCoefficients {
vector<double> b;
vector<double> a;
};
// 一阶低通 Butterworth
FilterCoefficients butterworthLowpass(double fc, double fs) {
double c = 1.0 / tan(M_PI * fc / fs);
double a0 = 1.0 / (1.0 + c);
double a1 = a0;
double b1 = (1.0 - c) / (1.0 + c);
FilterCoefficients coeffs;
coeffs.b = {a0, a1};
coeffs.a = {1.0, -b1};
return coeffs;
}
// 一阶高通 Butterworth
FilterCoefficients butterworthHighpass(double fc, double fs) {
double c = tan(M_PI * fc / fs);
double a0 = 1.0 / (1.0 + c);
double a1 = -a0;
double b1 = (1.0 - c) / (1.0 + c);
FilterCoefficients coeffs;
coeffs.b = {a0, a1};
coeffs.a = {1.0, -b1};
return coeffs;
}
/**************************************************************
* 测试信号生成与滤波测试
**************************************************************/
int main() {
// 采样参数
double fs = 1000.0; // 采样率
double f1 = 50.0; // 信号频率
double f_noise = 200.0; // 噪声频率
int N = 1000;
// 生成带噪信号
vector<double> x(N);
for (int n=0;n<N;++n) {
double t = n / fs;
x[n] = sin(2*M_PI*f1*t) + 0.5*sin(2*M_PI*f_noise*t);
}
// 设计低通滤波器
double fc = 100.0; // 截止频率
auto coeffs = butterworthLowpass(fc, fs);
IIRFilter filter(coeffs.b, coeffs.a);
// 滤波
vector<double> y = filter.filterSignal(x);
// 保存结果
ofstream fout("filter_result.csv");
fout << "n,input,output\n";
for (int i=0;i<N;++i)
fout << i << "," << x[i] << "," << y[i] << "\n";
fout.close();
cout << "滤波完成,结果已保存至 filter_result.csv" << endl;
cout << "可用Python或Excel绘制输入输出波形对比" << endl;
return 0;
}
六、代码详细解读
| 函数名 | 作用说明 |
|---|---|
IIRFilter::filterSample(double x) |
实现单点输入的 Direct Form II 结构 IIR 计算公式。 |
IIRFilter::filterSignal(const vector<double>& x) |
对输入序列逐点调用 filterSample,输出滤波后的信号。 |
IIRFilter::reset() |
清空滤波器状态(延迟线)。 |
butterworthLowpass(fc, fs) |
计算一阶低通滤波器系数。 |
butterworthHighpass(fc, fs) |
计算一阶高通滤波器系数。 |
main() |
生成测试信号、滤波、保存结果。 |
七、项目详细总结
本项目以教学为目标,完整实现了 C++ 版本的 IIR 滤波器,涵盖:
-
IIR 数学原理与差分方程推导;
-
数字实现结构(Direct Form II);
-
一阶巴特沃斯滤波器系数计算;
-
实时与离线滤波接口;
-
可直接运行与验证的测试主程序。
相比 FIR 滤波器,IIR 实现紧凑、计算量少,适用于嵌入式与实时信号处理。
该项目的教学价值在于——你可以:
-
直观理解数字滤波系统的数学模型;
-
掌握系数计算与数值稳定性;
-
将其嵌入音频、传感器或控制系统中。
八、项目常见问题及解答(FAQ)
Q1:为什么输出出现震荡?
A1:可能由于截止频率太高或采样率不够。请确保 fc<fs/2f_c < f_s / 2fc<fs/2,并使用双精度避免数值误差。
Q2:为什么输出信号幅值减小?
A2:滤波器存在幅度衰减特性,低通滤波器会抑制高频成分,从而整体振幅降低。
Q3:如何实现高阶滤波器?
A3:可通过级联多个一阶或二阶滤波器(biquad 结构),或自行扩展 a、b 数组长度。
Q4:是否能实时使用?
A4:完全可以。filterSample() 可在实时采样循环中逐点调用。
Q5:能否直接用于音频滤波?
A5:可以,只需将输入改为音频帧数据,保持采样率一致。
九、扩展方向与性能优化
-
支持二阶节(biquad)结构:
扩展为支持二阶 IIR 滤波器,更稳定并能处理更复杂的频率响应。 -
支持多通道处理:
批量滤波多路信号,可应用于立体声音频。 -
动态参数调节:
运行时可修改截止频率,实现动态滤波(如自适应低通)。 -
支持滤波器设计工具输入:
从 MATLAB / SciPy 导出系数并加载使用。 -
频率响应分析函数:
增加frequencyResponse()方法计算滤波器的幅频/相频响应。 -
使用模板与 SIMD 优化:
针对高性能场景,可引入 SSE/AVX 或模板化设计以优化性能。
更多推荐


所有评论(0)