Octave:Incorrect FFT相位谱

Octave:Incorrect FFT phase spectrum

我用 Octave 编写的一个小程序没有产生所需的相位谱。不过幅度图很完美。

 f = 200;
 fs = 1000;
 phase = pi/3; 
 t = 0: 1/fs: 1;
 sig = sin((2*pi*f*t) + phase);
 sig_fft = fft(sig);

 sig_fft_phase = angle(sig_fft) * 180/pi;

 sig_fft_phase(201)

sig_fft_phase(201) returns 5.998(6 度)而不是 60 度。我究竟做错了什么?我的期望不正确吗?

在您的示例中,如果您生成频率轴:(抱歉,我这里没有 Octave,所以 Python 必须这样做——我 确定 在 Octave 中也是一样的):

faxis = (np.arange(0, t.size) / t.size) * fs

你会看到 faxis[200](Python 是 0 索引,相当于 Octave 的 201 索引)是 199.80019980019981。你认为你要求的是 200 Hz 的相位,但你不是,你要求的是 199.8 Hz 的相位。

(发生这种情况是因为您的 t 向量包含 1.0——一个额外的样本会稍微减小光谱间距!我 认为 link @Sardar_Usama 在他们的评论中发布是正确的——它与正弦曲线没有在一个完整的循环中结束这一事实无关,因为这种方法 应该 不完整周期。)

解决方案:将 1001 长 sig 向量零填充到 2000 个样本。然后,使用新的 faxis 频率向量,faxis[400](Octave 的第 401 个索引)恰好对应于 200 Hz:

In [54]: sig_fft = fft.fft(sig, 2000);

In [55]: faxis = np.arange(0, sig_fft.size) / sig_fft.size * fs

In [56]: faxis[400]
Out[56]: 200.0

In [57]: np.angle(sig_fft[400]) * 180 / np.pi
Out[57]: -29.950454729683386

但是哦不,发生了什么事?这表示角度是-30°?

嗯,回想一下 Euler’s formulasin(x) = (exp(i * x) - exp(-i * x)) / 2i。分母中的 i 意味着 FFT 恢复的相位不会是 60°,即使输入正弦波具有 60° 的相位。相反,FFT bin 的相位将为 60 - 90 度,因为 -90° = angle(1/i) = angle(-i)。所以这实际上是正确的答案!要恢复正弦波的相位,您需要将 FFT bin 的相位增加 90°。

总而言之,您需要解决两件事:

  1. 确保您查看的是正确的频点。对于 N 点 FFT(没有 fftshift),bin 为 [0 : N - 1] / N * fs。上面,我们只是使用了一个 N=2000 点的 FFT 来确保代表 200 Hz。
  2. 请理解,尽管您有一个正弦波,但就 FFT 而言,它会得到两个复指数,分别为 +200 和 -200 Hz,振幅为 1/(2i) 和 -1/( 2i).分母中的虚数值将您期望的相位分别移动 -90° 和 +90°。
    • 如果你正好用了cos,一个余弦波,对于sig,你就不会运行进入这个数学障碍了,所以付出以后注意sin和cos的区别!

改为t=0:1/fs:1-1/fs;然后

 sig_fft_phase(201)
 ans = -30.000