绘制 FFT 幅值时频率轴的创建方式令人困惑

Uyg*_*çar 2 matlab signal-processing fft

此代码对信号进行 FFT 并将其绘制在新的频率轴上。

f=600;
Fs=6000;
t=0:1/Fs:0.3;
n=0:1:length(t);
x=cos(2*pi*(400/Fs)*n)+2*sin(2*pi*(1100/Fs)*n);
y=fft(x,512);

freqaxis=Fs*(linspace(-0.5,0.5, length(y)));
subplot(211)
plot(freqaxis,fftshift(abs(y)));
Run Code Online (Sandbox Code Playgroud)

我理解为什么我们使用它,fftshift因为我们希望看到以 0 Hz (DC) 值为中心的信号,这样更便于观察。

在此输入图像描述

然而,我似乎对如何定义频率轴感到困惑。具体来说,为什么我们特别将[-0.5 0.5]的范围乘以Fs并得到 [-3000 3000]范围呢?它可能是[-0.25 0.25]

ray*_*ica 6

范围介于两者之间的原因[-Fs/2,Fs/2]Fs/2奈奎斯特频率。这是能够可视化的最大可能频率,也是最终出现在频率分解中的频率。我也不同意你的评论,其中范围“可能介于”之间。这与奈奎斯特频率的定义相反。[-0.25,0.25]

从信号处理理论中,我们知道我们必须以至少两倍信号带宽进行采样才能正确重建信号。带宽定义为信号中可以看到的最大可能频率分量,也称为奈奎斯特频率。换句话说:

Fs = 2*BW
Run Code Online (Sandbox Code Playgroud)

我们可以可视化频谱和最终带宽/奈奎斯特频率的上限定义为:

BW = Fs / 2; 
Run Code Online (Sandbox Code Playgroud)

因此,由于采样频率为 6000 Hz,这意味着奈奎斯特频率为 3000 Hz,因此可视化范围为[-3000,3000]Hz,这在幅度图中是正确的。


顺便说一句,每个频率的垃圾箱中心都是不正确的。您将 FFT 中的 bin 总数指定为 512,但指定 bin 的方式是相对于信号的总长度而言的。我很惊讶为什么你没有得到语法错误,因为函数的输出fft应该给你 512 点,但你的频率轴变量将是一个大于 512 的数组。无论如何,这是不正确的。每个 bin 的频率i应该是:

f = i * Fs / N, for i = 0, 1, 2, ..., N-1
Run Code Online (Sandbox Code Playgroud)

N是 FFT 中的总点数,即 512。您最初的数据为,但这length(y)是不正确的......所以这可能就是您在检查频率轴时感到困惑的原因。您可以通过引用用户Paul R的精彩帖子来了解为什么会出现这种情况: How do I acquire the rates of every value in an FFT?

请注意,我们仅指定从 0 到 N - 1 的 bin。为了在指定每个频率的 bin 中心时考虑到这一点,您通常在命令中指定一个附加linspace并删除最后一个点:

freqaxis=Fs*(linspace(-0.5,0.5, 513); %// Change
freqaxis(end) = []; %// Change
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你声明的方式freqaxis对我来说有点困惑。这对我来说更具可读性:

freqaxis = linspace(-Fs/2, Fs/2, 513);
freqaxis(end) = [];
Run Code Online (Sandbox Code Playgroud)

我个人讨厌使用length并且更喜欢numel更多。


无论如何,当我运行更正的代码来指定箱中心时,我现在得到了这个图。请注意,我在频谱峰值所在的位置插入了多个数据光标,这些光标对应于您声明的每个余弦的频率(400 Hz 和 1100 Hz):

在此输入图像描述

您会看到存在一些轻微的不准确性,这主要是由于您指定的 bin 数量(即 512)造成的。如果增加箱的总数,您会发现每个峰值的频率都会变得更加准确。