语音信号处理二十七——FIR滤波器设计(窗函数法)


前言

在之前的文章中,已经介绍了如何实现一个数字IIR滤波器,本篇文章将会介绍如何实现一个FIR滤波器,包括它的设计过程、设计方法,其中将会详细介绍设计方法中的窗函数法。并且在文章的最后,将会真实的实现一个高通的FIR滤波器。

本篇文章将会大量引用之前文章的知识,包括DTFT的逆变换、DTFT的性质、相频响应的特点、Z变换的有理函数、频谱加窗的影响、IIR滤波器设计指标等等。不过不用担心,本篇文章会将这些知识进行整理并且会在对应处附上之前文章的链接,以方便读者阅读。

|版本声明:山河君,未经博主允许,禁止转载


一、FIR滤波器的设计

1.FIR滤波器的传递函数

音频进阶学习十三——Z变换二(有理z变换、稳定性与反变换)中,我们知道传递函数其实为系统的冲激响应的Z变换: H ( z ) = Y ( z ) / X ( z ) H(z)=Y(z)/X(z) H(z)=Y(z)/X(z),而对于IIR滤波器来说,通过差分方程写成有理分式,分子为输入信号,分母为输出信号,写成:
H ( z ) = Y ( z ) X ( z ) = ∑ k = 0 M b k z M 1 − ∑ k = 0 N a k z N H(z)=\frac{Y(z)}{X(z)}=\frac{\sum_{k=0}^Mb_kz^M}{1-\sum_{k=0}^Na_kz^N} H(z)=X(z)Y(z)=1k=0NakzNk=0MbkzM
而对于FIR滤波器,不存在反馈结构,且为有限长的,即:
y [ n ] = ∑ k = 0 M h [ k ] x [ n − k ] y[n]=\sum_{k=0}^Mh[k]x[n-k] y[n]=k=0Mh[k]x[nk]
对其求Z变换为:
Y ( z ) = X ( z ) ∑ k = 0 M h [ k ] Y(z)=X(z)\sum_{k=0}^Mh[k] Y(z)=X(z)k=0Mh[k]
所以FIR滤波器的传递函数写为有理分式为:
H ( z ) = ∑ k = 0 M h [ k ] = Y ( z ) X ( z ) H(z)=\sum_{k=0}^Mh[k]=\frac{Y(z)}{X(z)} H(z)=k=0Mh[k]=X(z)Y(z)
对比IIR滤波器的传递函数,实际上就是缺了分母那一项,即在Z平面上只存在零点的极点,因此一定是因果稳定的。

2.FIR滤波器的特点

在之前的文章中,零零散散的介绍过FIR滤波器,这里来对其做一个总结,FIR滤波器存在以下的特点:

  • 单位冲激响应 h [ n ] h[n] h[n]是有限长的
  • 使用Z变换表示系统函数形式为: H ( z ) = ∑ k = 0 M b k z − k H(z)=\sum_{k=0}^M b_kz^{-k} H(z)=k=0Mbkzk
  • 在Z平面上只有0点存在极点,因此系统一定因果稳定
  • 可以实现严格的线性相位
  • 可以设计任意频率特性的滤波器
  • 可以使用FFT算法来提高计算率

3.FIR滤波器设计过程

整体的设计FIR滤波器设计过程如下:
在这里插入图片描述

  • 确定滤波器指标,和音频进阶学习二十四——IIR滤波器设计方法中滤波器设计要求一样:
    • 滤波器类型:低通、高通、带通、带阻
    • 采样频率 f s f_s fs
    • 通带截止频率 f p f_p fp和 阻带截止频率 f s f_s fs
    • 通带波动和阻带衰减
    • 过渡带宽度
  • 确定设计方法:
    • 窗函数法:
      • 基本原理:通过理想滤波器的频率响应计算其时域脉冲响应(通常是无限长的),然后截取有限的部分并乘以窗函数,以减少频谱泄露。
      • 优点:计算简单,适合嵌入式系统
      • 缺点:频率特性难以精确控制,通常需要较长的滤波器长度以提高性能
    • 频率采样法:已知频率响应
      • 基本原理:直接在频域上指定滤波器的频率响应 H ( f ) H(f) H(f),然后通过逆DFT计算时域系数 h [ n ] h[n] h[n]
      • 优点:适用于设计具有特定频率特性的滤波器
      • 缺点:处理非等间隔频率响应时,容易引起振铃效应
    • Parks-McClellan(切比雪夫逼近法):
      • 基本原理:采用 Remez 交换算法,使得滤波器在通带和阻带的最大误差最小化(等波纹特性)
      • 优点:能够在给定阶数下优化滤波器的性能,过渡带最窄
      • 缺点:计算较复杂
    • 最小均方误差法:
      • 基本原理:在频域中最小化设计滤波器的误差,使得设计的FIR滤波器逼近理想滤波器
      • 优点:适用于需要较好幅度逼近的滤波器
      • 缺点:对过渡带的控制不如切比雪夫法
  • 滤波器阶数
    滤波器阶数 M M M决定了 FIR 滤波器的性能。如果使用窗函数法,可以通过经验公式估算阶数。
  • 滤波器系数:
    最终的滤波器脉冲响应

3.IIR滤波器和FIR滤波器的对比

音频进阶学习十四——滤波器的种类和实现方式总中,就已经介绍了IIR滤波器和FIR滤波器的区别。由于在前两篇文章中以及实际设计过IIR滤波器,这里再结合实现原理做一个总结:

  • IIR滤波器:采用逼近模拟滤波器的方法设计,所以存在以下特点
    • 相同的滤波器指标,阶数低、计算量小,适合资源受限场景
    • 存在相位响应非线性,可能会导致信号畸变
    • 适合DSP、MCU,相位不那么重要的场合
  • FIR滤波器:根据滤波器指标直接设计,所以存在以下特点
    • 可以设计成严格线性相位(保持波形不失真),对系数精度不敏感,易于实现
    • 相同的滤波器指标阶数高、计算量大,存储需要更多的空间
    • 适合CPU、GPU,在多通道系统中保持延时一致性

二、理想FIR滤波器

1.FIR滤波器线性相位的意义

  • FIR滤波器的相位
    从上文可知,对于FIR和IIR滤波器来说,可以拥有同样的设计指标在不同的资源下进行设计实现,而实现的最大区别是在于一个是相位非线性,而FIR滤波器拥有线性相位。
  • 理想滤波器的相位
    而对于理想滤波器而言,期望它的幅频响应恒定,并且是一个零相位系统(对于幅频响应和相频响应深入了解在音频进阶学习十八——幅频响应相同系统、全通系统、最小相位系统文章中)。
  • 数字滤波器的相位
    但实际上的数字滤波器不管是幅频响应还是相频响应都无法做到,而对于相频响应,我们退而求其次,期望它是一个线性相位。 也就是保持波形是一个整体延迟(群延迟为恒定音频进阶学习十七——极点、零点与频率响应

2.理想FIR滤波器

对于一个理想FIR滤波器如同上文:

  • 满足相位为0
  • 满足幅频响应为1

由此,满足相位为0,则它的幅频响应为:
H d ( e j ω ) = ∣ H d ( e j ω ) ∣ H_d(e^{j\omega})=|H_d(e^{j\omega})| Hd(e)=Hd(e)
求其傅里叶逆变换,逆变换公式在音频进阶学习九——离散时间傅里叶变换DTFT文章中:
h d = 1 2 π ∫ − π π H d ( e j ω ) e j ω n d ω h_d=\frac{1}{2\pi}\int_{-\pi}^{\pi}H_d(e^{j\omega})e^{j\omega n}d\omega hd=2π1ππHd(e)ejωndω
对于一个给定的滤波器指标通带截止频率 ω c \omega_c ωc的低通滤波器,如下图:
在这里插入图片描述
满足幅频响应为1,即 H d ( e j ω ) = 1 H_d(e^{j\omega})=1 Hd(e)=1,所以它的逆傅里叶变换为:
h d = 1 2 π ∫ − ω c ω c H d ( e j ω ) e j ω n d ω = 1 2 π ∫ − ω c ω c e j ω n d ω h_d=\frac{1}{2\pi}\int_{-\omega_c}^{\omega_c}H_d(e^{j\omega})e^{j\omega n}d\omega=\frac{1}{2\pi}\int_{-\omega_c}^{\omega_c}e^{j\omega n}d\omega hd=2π1ωcωcHd(e)ejωndω=2π1ωcωcejωndω
音频进阶学习八——傅里叶变换的介绍中,我们给出了根据指数函数的积分得到其函数,再进行欧拉公式转换最终得到:
h d = 1 2 π ∫ − ω c ω c e j ω n d ω = 1 2 π e j ω c n − e − j ω c n j n = sin ⁡ ( ω c n ) ω c n h_d=\frac{1}{2\pi}\int_{-\omega_c}^{\omega_c}e^{j\omega n}d\omega=\frac{1}{2\pi}\frac{e^{j\omega_c n}-e^{-j\omega_c n}}{jn}=\frac{\sin(\omega_cn)}{\omega_cn} hd=2π1ωcωcejωndω=2π1jnejωcnejωcn=ωcnsin(ωcn)
来观察一下这个最终结果,对于 sin ⁡ ( ω c n ) ω c n \frac{\sin(\omega_cn)}{\omega_cn} ωcnsin(ωcn)实际上就是一个 s i n c sinc sinc函数,在音频进阶学习二十三——频谱泄露、加窗以及栅栏效应文章中,我们分析过sinc函数的频谱的图像:
在这里插入图片描述

三、窗函数法

1.冲激响应的截断

对于上文中的FIR滤波器的冲激响应,使用逆傅里叶变换得到最终的形式为sinc函数,毫无疑问此时它的图像是关于纵坐标对称且是无限长的,因此我们需要对其进行截断。

我们知道sinc函数会随着 n n n趋向正无穷和负无穷,它的值越来越小,所以我们取 [ − 2 π / ω c , 2 π / ω c ] [-2\pi/\omega_c,2\pi/\omega_c] [2π/ωc,2π/ωc]之间,此时 h 1 [ n ] h_1[n] h1[n]为截取后的冲激响应序列, w [ n ] w[n] w[n]是一个矩形窗,而M为矩形窗的长度:
{ w [ n ] = 1 , − M / 2 < n < M / 2 w [ n ] = 0 , n = 其他 = > h 1 [ n ] = h d [ n ] w [ n ] = > { h 1 [ n ] = h d [ n ] , − M / 2 < n < M / 2 h 1 [ n ] = 0 , n = 其他 \begin {cases} w[n]=1, \quad -M/2<n<M/2 \\ w[n]=0, \quad n=其他\end {cases}=>h_1[n]=h_d[n]w[n] \\=>\begin {cases} h_1[n]=h_d[n], \quad -M/2<n<M/2 \\ h_1[n]=0, \quad n=其他\end {cases} { w[n]=1,M/2<n<M/2w[n]=0,n=其他=>h1[n]=hd[n]w[n]=>{ h1[n]=hd[n],M/2<n<M/2h1[n]=0n=其他
此时,想要让 h 1 [ n ] h_1[n] h1[n]最终为因果序列(冲激响应只在0时刻以后),我们只需要将其移位 M / 2 M/2 M/2,得到最终的 h [ n ] h[n] h[n],即如下图所示:
在这里插入图片描述

2.线性相位

上文中,我们是将一个理想低通滤波器进行截断时移后,得到了最终的冲激响应序列,那么对于时移带来的影响在音频进阶学习十——DTFT的条件、性质与举例中介绍过,时移后幅频响应是没有发生变化的,但相频响应发生了线性变化:
x [ n ] ⟷ D T F T X ( e j ω ) , x [ n − k ] ⟷ D T F T X ( e j ω ) e − j ω k x[n]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega}),\quad x[n-k]\stackrel{DTFT}{\longleftrightarrow}X(e^{j\omega})e^{-j\omega k} x[n]DTFTX(e),x[nk]DTFTX(e)ejωk
就如下图所示
在这里插入图片描述
即上文中最终得到的FIR滤波器经过移位变成因果的后,它的DTFT变成了
H d ( e j ω ) = ∣ H d ( e j ω ) ∣ = > H d ( e j ω ) = ∣ H d ( e j ω ) ∣ e − j ω M / 2 H_d(e^{j\omega})=|H_d(e^{j\omega})|=>H_d(e^{j\omega})=|H_d(e^{j\omega})|e^{-j\omega M/2} Hd(e)=Hd(e)=>Hd(e)=Hd(e)eM/2
对于矩形窗 w [ n ] w[n] w[n],它的DTFT通过欧拉公式展开最终为:
W ( e j ω ) = ∑ n = 0 M e − j n ω = 1 − e − j ω ( M + 1 ) 1 − e − j ω = sin ⁡ ( ω ( M + 1 ) / 2 ) sin ⁡ ( ω / 2 ) e − j ω M / 2 W(e^{j\omega})=\sum_{n=0}^Me^{-jn\omega}=\frac{1-e^{-j\omega(M+1)}}{1-e^{-j\omega}}=\frac{\sin(\omega(M+1)/2)}{\sin(\omega/2)}e^{-j\omega M/2} W(e)=n=0Mejnω=1e1e(M+1)=sin(ω/2)sin(ω(M+1)/2)eM/2
我们同样可以看到对于矩形窗 w [ n ] w[n] w[n]同样和 H d ( e j ω ) H_d(e^{j\omega}) Hd(e)存在一个相同线性相位

3.系统的频谱图

音频进阶学习十——DTFT的条件、性质与举例中,我们还介绍过,时域相乘等于频域卷积:
x 1 [ n ] x 2 [ n ] ⟷ D T F T 1 2 π ∫ − π π X 1 ( e j θ ) X 2 ( e j ( ω − θ ) ) d θ x_1[n] x_2[n] \stackrel{DTFT}{\longleftrightarrow}\frac{1}{2\pi}\int_{-\pi}^{\pi } X_1(e^{j\theta})X_2(e^{j(\omega-\theta)})d\theta x1[n]x2[n]DTFT2π1ππX1(ejθ)X2(ej(ωθ))dθ
所以上文中对于矩形窗带来的频域卷积为:
H ( e j ω ) = 1 2 π ∫ − π π ( H d ( e j ω ) e − j ω M / 2 ) W ( e j ( ω − θ ) ) d θ H(e^{j\omega})=\frac{1}{2\pi}\int_{-\pi}^{\pi } (H_d(e^{j\omega})e^{-j\omega M/2})W(e^{j(\omega-\theta)})d\theta H(e)=2π1ππ(Hd(e)eM/2)W(ej(ωθ))dθ
而随着 ω \omega ω − π -\pi π π \pi π的积分的过程看起来如下:
在这里插入图片描述
最终得到的FIR滤波器频率响应如同下图,红线是理想滤波器的响应,而蓝线是实际的滤波器响应:
在这里插入图片描述

4.窗口对于频谱的影响

对于主瓣和旁瓣具体释义请参照音频进阶学习二十三——频谱泄露、加窗以及栅栏效应。通过上文最终得到的滤波器频率响应,对其进行分析。

此时我们可以直观的看到:
在这里插入图片描述

  • 通带部分的波动,是由旁瓣造成的
  • 阻带部分的波动,同样是由旁瓣造成的
  • 通带的幅度,是由主瓣和旁瓣一起影响的
  • 主瓣影响了过渡带的宽度
  • 最小值肩峰是主瓣刚刚移出理想截止频率
  • 最大值肩峰是主瓣刚刚到达理想截止频率
H ( e j ω ) H(e^{j\omega}) H(e) 位置 大小
理想截止频率 ± ω c \pm \omega_c ±ωc 1 2 H ( e j 0 ) \frac{1}{2}H(e^{j0}) 21H(ej0)
最小值肩峰 ± ω c ± 2 π M 1 + 1 \pm \omega_c \pm \frac{2\pi}{M_1+1} ±ωc±M1+12π − 0.0895 ( e j 0 ) -0.0895(e^{j0}) 0.0895(ej0)
最大值肩峰 ± ω c ∓ 2 π M 1 + 1 \pm \omega_c \mp \frac{2\pi}{M_1+1} ±ωcM1+12π 1.0895 ( e j 0 ) 1.0895(e^{j0}) 1.0895(ej0)

也就是最终的通带、阻带、过度带的划分如下:
在这里插入图片描述

  • 主瓣和旁瓣决定了通带的大小
  • 主瓣是过渡带的宽度,即 4 π M 1 + 1 \frac{4\pi}{M_1+1} M1+14π
  • 旁瓣决定了通带和阻带的起伏

四、常用的窗

除了矩形窗以外,还可以选择其他窗函数来进行滤波器设计,这里将所有窗的时域图像、频域图像使以及通带、阻带、过渡带使用matlab画出。

下文中窗口包含:Rectangular(矩形窗)、Hamming(汉明窗)、Hann(汉宁窗)、Blackman(布莱克曼窗)、Kaiser(凯泽窗)。

1.各种窗口的时域表达式

  • Rectangular
    w [ n ] = 1 , 0 ≤ n ≤ M − 1 w[n]=1, \quad 0 \leq n \leq M-1 w[n]=1,0nM1
  • Hamming
    w [ n ] = 0.54 − 0.46 cos ⁡ ( 2 π n M − 1 ) , 0 ≤ n ≤ M − 1 w[n]=0.54-0.46\cos(\frac{2\pi n}{M-1}), \quad 0 \leq n \leq M-1 w[n]=0.540.46cos(M12πn),0nM1
  • Hann
    w [ n ] = 0.5 [ 1 − cos ⁡ ( 2 π n M − 1 ) ] = sin ⁡ 2 ( π n M − 1 ) , 0 ≤ n ≤ M − 1 w[n]=0.5[1-\cos(\frac{2\pi n}{M-1})]=\sin^2(\frac{\pi n}{M-1}), \quad 0 \leq n \leq M-1 w[n]=0.5[1cos(M12πn)]=sin2(M1πn),0nM1
  • Blackman
    w [ n ] = 0.42 − 0.5 cos ⁡ ( 2 π n M − 1 ) + 0.08 cos ⁡ ( 4 π n M − 1 ) , 0 ≤ n ≤ M − 1 w[n]=0.42-0.5\cos(\frac{2\pi n}{M-1})+0.08\cos(\frac{4\pi n}{M-1}), \quad 0 \leq n \leq M-1 w[n]=0.420.5cos(M12πn)+0.08cos(M14πn),0nM1
  • Kaiser
    w [ n ] = I 0 [ β 1 − ( 2 n M − 1 − 1 ) 2 ] I 0 ( β ) , 0 ≤ n ≤ M − 1 w[n]=\frac{I_0[\beta\sqrt{1-(\frac{2n}{M-1}-1)^2}]}{I_0(\beta)}, \quad 0 \leq n \leq M-1 w[n]=I0(β)I0[β1(M12n1)2 ],0nM1
    • I 0 I_0 I0是 0 阶修正贝塞尔函数
    • β \beta β控制主瓣宽度和旁瓣高度

2.时域与频域图像

% 窗函数长度
M = 51;
beta = 8.6;

% 窗函数
w_rect = rectwin(M);
w_hamming = hamming(M);
w_hann = hann(M);
w_blackman = blackman(M);
w_kaiser = kaiser(M, beta);

% 创建窗函数名字和数据的 cell 数组
windows = {
    
    w_rect, w_hamming, w_hann, w_blackman, w_kaiser};
labels = {
    
    'Rectangular', 'Hamming', 'Hann', 'Blackman', 'Kaiser (\beta=8.6)'};
colors = {
    
    'b', 'r', 'g', 'm', 'k'};

% 频率响应绘图
figure;
hold on;
for i = 1:length(windows)
    [H, w] = freqz(windows{
    
    i}, 1, 1024);
    H_dB = 20*log10(abs(H)/max(abs(H))); % 归一化幅度(dB)
    plot(w/pi, H_dB, 'DisplayName', labels{
    
    i}, 'LineWidth', 1.5, 'Color', colors{
    
    i});
end
grid on;
xlabel('Normalized Frequency (\times\pi rad/sample)');
ylabel('Magnitude (dB)');
title('Comparison of Window Functions in Frequency Domain');
legend('show');
ylim([-100 5]);
xlim([0 1]);

figure;
for i = 1:length(windows)
    subplot(3,2,i);
    stem(windows{
    
    i});
    title(labels{
    
    i});
    xlabel('n'); ylabel('Amplitude');
end

如下图所示:
在这里插入图片描述

3.通带、阻带、过渡带

% 窗函数长度
M = 51;
beta = 8.6;
N = 1024;

% 窗函数
w_rect = rectwin(M);
w_hamming = hamming(M);
w_hann = hann(M);
w_blackman = blackman(M);
w_kaiser = kaiser(M, beta);

windows = {
    
    w_rect, w_hamming, w_hann, w_blackman, w_kaiser};
labels = {
    
    'Rectangular', 'Hamming', 'Hann', 'Blackman', 'Kaiser (\beta=8.6)'};
colors = {
    
    'b', 'r', 'g', 'm', 'k'};

% 频率响应绘图
figure;
for i = 1:length(windows)
    subplot(3,2,i);
    [H, w] = freqz(windows{
    
    i}, 1, N);
    H_dB = 20*log10(abs(H)/max(abs(H)));
    
    % 通带、过渡带、阻带范围(以矩形窗主瓣近似)
    mainlobe_width = 4 * pi / M;
    omega_c = 0.4 * pi; % 截止频率(理想低通)
    trans_start = omega_c;
    trans_end = omega_c + mainlobe_width;

    % 画频率响应
    plot(w/pi, H_dB, 'Color', colors{
    
    i}, 'LineWidth', 1.5); hold on;
    grid on;

    % 添加通带/过渡带/阻带区域阴影
    yl = [-100, 5];

    % 通带
    area([0 trans_start]/pi, [5 5], yl(1), 'FaceColor', [0.8 1 0.8], 'EdgeColor', 'none', 'FaceAlpha', 0.4);

    % 过渡带
    area([trans_start trans_end]/pi, [5 5], yl(1), 'FaceColor', [1 1 0.6], 'EdgeColor', 'none', 'FaceAlpha', 0.4);

    % 阻带
    area([trans_end pi]/pi, [5 5], yl(1), 'FaceColor', [1 0.8 0.8], 'EdgeColor', 'none', 'FaceAlpha', 0.4);

    title(labels{
    
    i});
    xlabel('Normalized Frequency (\times\pi rad/sample)');
    ylabel('Magnitude (dB)');
    ylim(yl); xlim([0 1]);

    legend(labels{
    
    i}, '通带', '过渡带', '阻带', 'Location', 'southwest');
end

sgtitle('FIR Window Method: Frequency Response and Band Illustration');

在这里插入图片描述

3.对比以上窗口

窗函数 主瓣宽度 旁瓣衰减(抑制) 旁瓣衰减速率 特点 滤波器阶数
Rectangular 4 π / ( M + 1 ) 4\pi/(M+1) 4π/(M+1) 最差(-13 dB) -6 dB/倍频 跳变最陡,但旁瓣大,泄露严重 M ≈ 0.9 Δ f f s M\approx \frac{0.9}{\Delta f}f_s MΔf0.9fs
Hamming 8 π / ( M + 1 ) 8\pi/(M+1) 8π/(M+1) 好(-43 dB) -18 dB/倍频 通用型,通带平稳 M ≈ 3.3 Δ f f s M\approx \frac{3.3}{\Delta f}f_s MΔf3.3fs
Hann 8 π / ( M + 1 ) 8\pi/(M+1) 8π/(M+1) Hamming -31 dB -6 dB/倍频 更平滑一些,但抑制稍弱 M ≈ 3.1 Δ f f s M\approx \frac{3.1}{\Delta f}f_s MΔf3.1fs
Blackman 12 π / ( M + 1 ) 12\pi/(M+1) 12π/(M+1) -58 dB -18 dB/倍频 更好的旁瓣抑制,代价是过渡带变宽 M ≈ 5.5 Δ f f s M\approx \frac{5.5}{\Delta f}f_s MΔf5.5fs
Kaiser ( β = 8.6 ) \beta=8.6) β=8.6) 取决于 β \beta β 取决于 β \beta β(可达 -70 dB) 取决于 β \beta β 最灵活,可根据设计指标调节 β \beta β 取决于 β \beta β

五、FIR滤波器实例

1.滤波器设计

  • 设计一个高通滤波器,指标为通带起始频率为200Hz,阻带截止频率为180Hz
  • 选用汉宁窗
  • 确定滤波器阶数为: N = 3.1 × 1000 / ( 200 − 180 ) ≈ 155 N=3.1 \times 1000/(200-180) \approx 155 N=3.1×1000/(200180)155,选择157为滤波器阶数
  • 求出滤波器系数,matlab代码如下
% 参数
fs = 1000;           % 采样率 Hz
fc = 200;            % 通带起始频率 Hz
N = 157;             % 滤波器长度(奇数,居中对称)
n = 0:N-1;
wc = 2*pi*fc/fs;     % 归一化角频率

% 理想高通滤波器(h_hp = delta(n) - h_lp)
M = (N-1)/2;
h_lp = sin(wc*(n - M)) ./ (pi*(n - M));  % sinc函数
h_lp(M+1) = wc / pi;                     % 处理除以0的位置

h_hp = -h_lp;
h_hp(M+1) = 1 - wc/pi;  % delta(n) - h_lp

% 汉宁窗
w = hann(N)';
h = h_hp .* w;  % 应用窗函数

% 绘制频率响应
[H, f] = freqz(h, 1, 1024, fs);
figure;
plot(f, 20*log10(abs(H)));
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');
title('High-pass Filter (Hann Window, fc=200Hz)');
grid on;

% 生成测试信号:50Hz + 200Hz
t = 0:1/fs:1;
x = sin(2*pi*50*t) + sin(2*pi*200*t);

% 滤波
y = filter(h, 1, x);

% 绘制时域信号
figure;
subplot(3,1,1);
plot(t, x);
title('Original Signal (50Hz + 200Hz)');
xlabel('Time (s)'); ylabel('Amplitude');

subplot(3,1,2);
plot(t, y);
title('Filtered Signal (Should Remove 50Hz)');
xlabel('Time (s)'); ylabel('Amplitude');

% 频谱对比
subplot(3,1,3);
nfft = 1024;
f_axis = linspace(0, fs/2, nfft/2);
X = abs(fft(x, nfft));
Y = abs(fft(y, nfft));
plot(f_axis, X(1:nfft/2), '--', 'DisplayName', 'Original');
hold on;
plot(f_axis, Y(1:nfft/2), 'LineWidth', 1.2, 'DisplayName', 'Filtered');
title('Frequency Spectrum');
xlabel('Frequency (Hz)'); ylabel('Magnitude');
legend; grid on;

2.对于滤波器频谱

实例中,对于50Hz+200Hz的信号,经过滤波器的时域图像和频域对比图像如下:
在这里插入图片描述


总结

这一系列的文章到此就结束了,后面博主还会再分享一些IIR滤波器、FIR滤波器的其他的设计方法,或者是自适应滤波器等等,但是可能会比较零散,所以不会放在这个专栏内了。

反正收藏也不会看,不如点个赞吧!