混淆绘制 FFT 幅度时的频率轴是如何产生的

Confusion on how the frequency axis when plotting the FFT magnitude is created

此代码采用信号的 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)));

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

但是我似乎对频率轴的定义方式感到困惑。具体来说,为什么我们特地把[-0.5 0.5]的区间乘以Fs,得到[-3000 3000]的区间呢?可以是 [-0.25 0.25].

之所以范围在[-Fs/2,Fs/2]之间是因为Fs/2Nyquist frequency。这是具有可视化能力的最大可能频率,也是最终出现在您的频率分解中的频率。我也不同意您对范围 "could be between [-0.25,0.25]" 的评论。这与奈奎斯特频率的定义相反。

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

Fs = 2*BW

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

BW = Fs / 2; 

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


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

f = i * Fs / N, for i = 0, 1, 2, ..., N-1

N 是您的 FFT 中的总点数,即 512。您最初将其设为 length(y),但这是不正确的...所以这可能就是您的原因在检查频率轴时有一个混乱的来源。您可以通过引用用户 Paul R's wonderful post here: How do I obtain the frequencies of each value in an FFT?

来了解为什么会出现这种情况

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

freqaxis=Fs*(linspace(-0.5,0.5, 513); %// Change
freqaxis(end) = []; %// Change

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

freqaxis = linspace(-Fs/2, Fs/2, 513);
freqaxis(end) = [];

我个人讨厌使用 length,我更喜欢 numel


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

您看到有一些轻微的不准确,主要是由于您指定的 bin 数量(即 512)。如果您增加 bin 的总数,您将看到每个峰值处的频率将变得更加准确。