4. Z变换与频域分析

数字滤波器,说白了就是一段数学运算代码。它把输入的采样点序列,按照你想要的频率特性进行加工。我在刚入行那会儿,总觉得滤波器设计是理论家的活儿,直到第一次在定点DSP上跑IIR滤波器跑出了自激振荡……嗯,从那以后我才真正把这两类滤波器的脾气摸清楚。

今天咱们就聊聊FIR和IIR这对冤家。它们各有各的绝活,也各有各的坑。

从名字看本质:有限 vs 无限

先看名字:FIR(Finite Impulse Response)——有限冲激响应。IIR(Infinite Impulse Response)——无限冲激响应。

什么意思?你给滤波器输入一个单位冲激(就一个1,后面全是0),看它的输出:

  • FIR:输出在有限个采样点后归零。因为它的结构里没有反馈,只有前馈。
  • IIR:输出理论上会一直振荡下去,永不归零。因为它有反馈,输出会绕回来影响自己。

你想想看,一个没有反馈,一个有反馈。这个差异决定了它们几乎所有的特性。

核心差异一句话:FIR是“非递归”结构,IIR是“递归”结构。递归意味着极点,极点意味着可能不稳定。

FIR滤波器:稳,但慢

FIR的差分方程长这样:

y[n] = b0·x[n] + b1·x[n-1] + b2·x[n-2] + ... + bN·x[n-N]

没有y[n-1]、y[n-2]这些项。输出只取决于当前和过去的输入。

FIR的优点

  • 绝对稳定:所有极点都在原点,不存在稳定性问题。你随便给系数,它都不会炸。
  • 线性相位:这是FIR最大的王牌。所有频率分量的延迟时间相同,波形形状不变。通信系统中的匹配滤波器、均衡器,非FIR不可。
  • 实现简单:就是乘累加,没有反馈环路,定点实现时不用担心溢出振荡。

FIR的缺点

  • 阶数高:要获得陡峭的过渡带,你需要很高的阶数。比如一个-60dB阻带衰减、过渡带只有0.1π的FIR,阶数可能轻松上百。
  • 延迟大:阶数越高,群延迟越大。实时性要求高的场景,这是个硬伤。
  • 计算量大:每个输出点要做N+1次乘法和N次加法。N=100时,每秒48k采样率,那就是480万次乘累加。

我的经验:在音频均衡器里,我一般只用FIR做线性相位滤波。但如果你需要低延迟的实时效果器,比如吉他失真前的带通,我会毫不犹豫选IIR。

IIR滤波器:快,但娇气

IIR的差分方程带反馈项:

y[n] = b0·x[n] + b1·x[n-1] + ... + bM·x[n-M] - a1·y[n-1] - a2·y[n-2] - ... - aN·y[n-N]

注意那个负号。反馈系数a决定了滤波器的极点位置。

IIR的优点

  • 阶数低:同样的过渡带和阻带衰减,IIR的阶数可能只有FIR的十分之一。一个4阶的切比雪夫IIR,效果可能顶得上一个40阶的FIR。
  • 延迟小:阶数低,群延迟就小。适合实时控制、生物医学信号处理。
  • 计算量小:每个输出点只需要几次乘累加。在低端MCU上也能跑。

IIR的缺点

  • 可能不稳定:极点一旦落在单位圆外,滤波器就炸了。定点实现时,系数量化可能把极点推出圆外。
  • 非线性相位:不同频率的延迟不一样,波形会失真。音频处理中,IIR的相位失真人耳能听出来。
  • 定点实现麻烦:反馈环路容易产生极限环振荡。我曾经在一个16位定点DSP上实现IIR陷波器,结果输入为零时输出还在小幅度振荡……排查了两天才发现是系数舍入导致的。

避坑指南:我曾经在一个产品里用IIR做50Hz工频陷波。仿真时好好的,一上硬件就自激。后来发现是ADC的直流偏置让滤波器状态变量饱和了。解决办法:先做高通滤除直流,再用双精度累加器。

FIR vs IIR:一张表说清楚

对比项 FIR IIR
结构 非递归(无反馈) 递归(有反馈)
稳定性 绝对稳定 可能不稳定
相位特性 可做到严格线性相位 非线性相位
阶数需求 高(通常50~200阶) 低(通常2~10阶)
计算量 大 小
延迟 大(等于阶数/2个采样周期) 小
设计方法 窗函数法、频率采样法、Parks-McClellan 巴特沃斯、切比雪夫、椭圆、贝塞尔
典型应用 通信、音频、图像处理 实时控制、生物医学、语音

设计方法:怎么把指标变成系数?

FIR设计——窗函数法

这是最直观的方法。步骤很简单:

  1. 先确定理想滤波器的频率响应,做逆傅里叶变换得到无限长的冲激响应。
  2. 用窗函数(汉明窗、布莱克曼窗、凯泽窗)截断到有限长度。
  3. 截断后的序列就是FIR系数。

窗函数的选择决定了过渡带宽度和阻带衰减。我个人习惯用凯泽窗,因为它有一个可调的β参数,可以在过渡带和衰减之间做权衡。

// 用凯泽窗设计低通FIR滤波器
// 采样率 48kHz,截止频率 10kHz,阶数 64
// β = 5.0 对应约 -50dB 阻带衰减

float beta = 5.0f;
float fc = 10000.0f / 48000.0f;  // 归一化截止频率
int N = 64;
float h[N+1];

for (int n = 0; n <= N; n++) {
    // 理想低通冲激响应
    if (n == N/2)
        h[n] = 2 * fc;
    else
        h[n] = sin(2 * M_PI * fc * (n - N/2)) / (M_PI * (n - N/2));
    
    // 乘以凯泽窗
    h[n] *= kaiser(n, N, beta);
}

IIR设计——从模拟到数字

IIR设计通常走这条路:先设计模拟滤波器(巴特沃斯、切比雪夫),再用双线性变换法映射到数字域。

为什么用双线性变换?因为它能保证映射后稳定——s平面的左半平面映射到z平面的单位圆内。但代价是频率会扭曲,需要做预畸变校正。

// 双线性变换的核心步骤
// 模拟截止频率 Ωc -> 数字截止频率 ωc
// 预畸变:Ωc = (2/T) * tan(ωc/2)

float fs = 48000.0f;
float fc = 1000.0f;  // 数字截止频率
float omega_c = 2 * M_PI * fc / fs;
float Omega_c = (2.0f / (1.0f/fs)) * tan(omega_c / 2.0f);

// 然后用Omega_c设计模拟巴特沃斯滤波器
// 再通过双线性变换得到数字系数

我的建议:初学者先用MATLAB的fdatool或Python的scipy.signal。把系数算出来,再移植到C代码里。手算IIR系数太容易出错了,我吃过这个亏。

怎么选?三个问题帮你决策

你在项目里到底用FIR还是IIR?问自己三个问题:

  1. 相位重要吗?——如果信号波形必须保持(比如QRS波检测、通信解调),选FIR。
  2. 延迟敏感吗?——如果延迟超过1ms就不能接受(比如助听器、实时控制),选IIR。
  3. 计算资源够吗?——如果MCU只有几十MHz主频、几KB RAM,选IIR。如果用的是FPGA或高性能DSP,FIR随便上。

其实很多时候,你会两者混用。比如前端用IIR做粗略的带通,后端用FIR做精细的整形。我在一个心电监护仪项目里就是这么干的——IIR滤掉工频和基线漂移,FIR做QRS波匹配滤波。

知识体系总览

下面这张图把FIR和IIR的对比、设计流程、选型逻辑串在了一起。你可以把它当作本章的思维导图:

FIR与IIR滤波器知识体系 数字滤波器设计基础:FIR vs IIR 数字滤波器 FIR 有限冲激响应 IIR 无限冲激响应 特性 非递归结构 线性相位 绝对稳定 优缺点 ✓ 稳定、线性相位 ✗ 阶数高、延迟大 ✗ 计算量大 特性 递归结构 非线性相位 可能不稳定 优缺点 ✓ 阶数低、延迟小 ✓ 计算量小 ✗ 相位失真 设计方法 FIR设计 窗函数法 · 频率采样法 · PM算法 IIR设计 模拟原型 → 双线性变换 → 预畸变 选型决策:相位重要?延迟敏感?资源够吗? 核心原则:没有最好的滤波器,只有最合适的滤波器。根据项目约束做权衡。

这张图把FIR和IIR从特性、优缺点、设计方法到选型逻辑串在了一起。你写代码前,先对着这张图想清楚:你的项目到底需要什么?