You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

为何FFT对不同频率正弦波呈现不同频谱表现?

关于FFT多峰值现象的解释与解决办法

这是FFT入门阶段非常常见的问题,核心原因是栅栏效应频谱泄漏,我来给你拆解清楚:

为什么120Hz只有单一峰值?

FFT的计算依赖一组固定的频率点,这些点由你的采样率(Fs)和采样点数(N)决定,频率分辨率公式为:Δf = Fs/N

只有当信号频率刚好是Δf的整数倍时,FFT才会在对应频率点上呈现单一峰值——你的120Hz信号刚好完美落在了FFT的某个频率点上,所以能量完全集中在该点。

为什么130Hz、140Hz会出现多峰值?

当信号频率不是Δf的整数倍时,会触发两个关键现象:

  • 栅栏效应:FFT的频率点就像一排栅栏,不在栅栏“缝隙”(频率点)上的频率成分无法被直接检测,它的能量会被分摊到相邻的几个频率点上,看起来就像多个峰值。
  • 频谱泄漏:信号的周期与FFT采样窗口不匹配,相当于你截断了完整的信号周期,这会导致原本集中在单一频率的能量扩散到整个频谱,产生旁瓣(那些额外的小峰值)。

实用解决办法

  • 提高频率分辨率:增加采样点数N(比如从现有数值增大到1024或2048),这样Δf会变小,让130Hz、140Hz更接近FFT的频率点,峰值会更集中。
  • 使用窗函数:在FFT前给信号加窗(比如汉宁窗hann(N)、汉明窗hamming(N)),虽然不能完全消除泄漏,但能大幅降低旁瓣幅度,让主峰值更突出。
  • 匹配信号周期与采样窗口:调整采样率Fs或采样点数N,让Fs/N能整除目标频率(比如目标是130Hz时,设置Fs=1300HzN=10,此时Δf=130Hz,刚好匹配)。

Matlab代码示例

你可以跑这段代码直观感受不同场景的差异:

% 模拟你的测试场景
Fs = 600;          % 采样率
N = 5;             % 采样点数,Δf = 600/5 = 120Hz
t = 0:1/Fs:(N-1)/Fs;

% 120Hz信号(完美匹配Δf)
x1 = sin(2*pi*120*t);
Y1 = fft(x1);
f_axis = Fs*(0:(N/2))/N;
figure; plot(f_axis, 2*abs(Y1(1:N/2+1))/N);
title('120Hz信号FFT结果'); xlabel('频率(Hz)'); ylabel('幅值');

% 130Hz信号(不匹配Δf)
x2 = sin(2*pi*130*t);
Y2 = fft(x2);
figure; plot(f_axis, 2*abs(Y2(1:N/2+1))/N);
title('130Hz信号FFT结果'); xlabel('频率(Hz)'); ylabel('幅值');

% 加汉宁窗改善泄漏
x2_windowed = x2 .* hann(N);
Y2_win = fft(x2_windowed);
figure; plot(f_axis, 2*abs(Y2_win(1:N/2+1))/N);
title('加汉宁窗后的130Hz信号FFT'); xlabel('频率(Hz)'); ylabel('幅值');

内容的提问来源于stack exchange,提问作者SAIP

火山引擎 最新活动