《数字信号处理》如何合理选择FFT的采样率、采样点数,实现更精确的频谱计算
一、前言
1.1、知识前提
为了不影响阅读,在看这篇博客之前,读者最好需要具备以下知识基础:
(1)连续信号和离散信号的基本认识。
(2)离散信号时域和频域的认识。
(3)(ZT、DTFT、DFS)DFT、FFT的基本了解。
(4)影响FFT结果的几个因素:混叠现象、截断效应、频谱泄露谱间干扰、栅栏效应 有一个基本了解。
这样读者才能更好地明白本篇博客的目的是什么。
1.2、概念简单介绍
(1)频谱混叠:
FFT是对有限长信号作变换,有限长信号频谱无限宽,所以有限长信号经过离散采样后,频谱进行了以采样频率为周期的周期延拓,导致频谱叠在了一起。
解决办法:
提高采样频率
f
s
f_s
fs或者在采样前用低通滤波器将最大频率
f
m
a
x
f_{max}
fmax限制在采样频率
f
s
f_s
fs的一半以内。
(2)截断效应:
FFT是对有限长信号作变换,理想信号应该是无限长,也就是说,FFT处理时默认为信号加上了矩形窗,矩形窗的频谱是
S
a
Sa
Sa函数,包含主瓣和第
N
N
N副瓣。
截断效应会导致频谱泄露和谱间干扰
解决办法:
增加采样点数
N
N
N,或添加副瓣更小的窗函数,如海宁窗、汉明窗等。
(3)栅栏效应:
我们都知道,FFT结果是离散值,如1kHz、2kHz…如果信号频率为1.5kHz,则在FFT结果中则体现不出来。就像透过栅栏来看原始真实的频谱,只能看到等间隔的离散的点。
解决办法:
通过合理选择采样频率,可以使信号频率值刚好落在 “栅栏点” 上,也就可以精确测量出频谱值。或者对信号后面进行补0,采用阶数更高的FFT(如从64点FFT改为1024点FFT)。
窗函数时域图
窗函数频域图
窗函数频域图(dB)
二、举例介绍
来自《数字信号处理》 史林 赵树杰 编著
问题描述
连续时间信号 x a ( t ) = x 1 ( t ) + x 2 ( t ) + x 3 ( t ) = c o s ( 8 π t ) + c o s ( 16 π t ) + c o s ( 20 π t ) x_a(t)=x_1(t)+x_2(t)+x_3(t)=cos(8\pi t)+cos(16\pi t)+cos(20\pi t) xa(t)=x1(t)+x2(t)+x3(t)=cos(8πt)+cos(16πt)+cos(20πt),用FFT对x_a(t)进行频谱分析。问采样率 f a f_a fa和采样点数 N N N如何选择,才能精确求出 x 1 ( t ) 、 x 2 ( t ) 、 x 3 ( t ) x_1(t)、x_2(t)、x_3(t) x1(t)、x2(t)、x3(t)的中心频率?
我们需要在保证精确求出 x 1 ( t ) 、 x 2 ( t ) 、 x 3 ( t ) x_1(t)、x_2(t)、x_3(t) x1(t)、x2(t)、x3(t)的中心频率前提下尽可能减小采样率 f a f_a fa和采样点数 N N N。
Step1
分析可知,该模拟信号频率包含4、8、10Hz分量。首先根据采样定理, f s > 2 f m a x = 20 H z 。 f_s>2f_{max}=20Hz。 fs>2fmax=20Hz。
Step2
为了防止栅栏效应,
f
s
f_s
fs取2的整数次幂,32Hz。
结论:当采样率为2的整数次幂时,FFT结果频率点将全部都是整数!
最终FFT结果中,频率点值为
f
s
/
N
∗
k
=
32
/
32
∗
k
=
k
f_s/N*k=32/32*k=k
fs/N∗k=32/32∗k=k(假如作32点FFT变换)
Step3
为了防止峰值混叠,FFT结果的最小分辨率应大于等于10-8=2Hz。
由公式:
N
>
=
f
s
/
Δ
f
N>=f_s/\Delta f
N>=fs/Δf,可得
N
>
=
32
/
2
=
16
。
N>=32/2=16。
N>=32/2=16。所以当
N
N
N取16时,FFT结果的频率分辨率为2Hz,刚好能区分8和10Hz分量。
Step4
为防止截断效应,应保证采样时间刚好是要观察信号周期的整数倍。这里我们分析一下是否符合要求:
采样时间为
N
/
f
s
=
16
/
32
=
0.5
s
N/f_s=16/32=0.5s
N/fs=16/32=0.5s,三个信号的周期分别是
0.25
、
0.125
、
0.1
s
0.25、0.125、0.1s
0.25、0.125、0.1s,符合要求,故不存在截断效应。
用MATLAB仿真
可以看到,FFT幅度谱分辨率是2Hz,刚好测量到了三个频率值。程序如下:
% 参数设置
fs = 32; % 采样频率 (Hz)
T = 1/fs; % 采样间隔 (s)
N_original = 16; % 原始采样点数
N_fft = 16; % FFT点数
t_original = (0:N_original-1) * T;
x_original = cos(8*pi*t_original) + cos(16*pi*t_original) + cos(20*pi*t_original);
x_padded = [x_original, zeros(1, N_fft - N_original)];
X = fft(x_padded);
f = (0:N_fft-1) * (fs / N_fft);
% 绘制结果
figure;
subplot(2,1,1);
stem(t_original, x_original);
title('原始采样信号');
xlabel('时间 (s)');
ylabel('幅度');
subplot(2,1,2);
stem(f, abs(X) / max(abs(X))); % 使用max(abs(X))进行简单归一化以便可视化
title('16点FFT幅度谱');
xlabel('频率 (Hz)');
ylabel('归一化幅度');
xlim([0 fs/2]); % 通常我们只关心0到采样频率一半的范围内的频率分量
三、注意点
FFT精度问题
注意,FFT是DFT的快速算法,我们用FFT求出来的是离散傅里叶变换,离散傅里叶变换实际上是对真实频谱的等间隔采样,FFT阶数越高,采样点越密,则FFT结果越接近真实频谱。
也就是说,假如我们作FFT结果感觉精度不够,可以在信号后面补0,直到满足2的下一个整数次幂,这样FFT结果精度会翻一倍,但相应地计算量会增加到2倍多。