Octave:FFT相位谱不正确

3

我用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) 返回的是5.998(6度),而不是60度。我做错了什么?我的期望是错误的吗?


这个 -> https://www.mathworks.com/matlabcentral/answers/1139#answer_1625 看起来是同样问题的答案! - Sardar Usama
2个回答

4
在您的示例中,如果您生成频率轴:(抱歉,我这里没有Octave,所以只能使用Python - 我确信在Octave中是相同的):
faxis = (np.arange(0, t.size) / t.size) * fs

你会发现faxis [200](Python的索引从0开始,相当于Octave的201索引)为199.80019980019981。你以为你在请求200Hz处的相位,但实际上不是,你在请求199.8 Hz 的相位。

(这是因为你的向量包括1.0-那一个额外的样本略微减少了频谱间距!我认为@Sardar_Usama在他们的评论中发布的链接不正确-它与正弦波没有结束在完整周期无关,因为这种方法应该可以使用不完整的周期解决。)

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

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°?
好吧,回想一下欧拉公式表明sin(x) = (exp(i * x) - exp(-i * x)) / 2i。分母中的i意味着FFT恢复的相位不会是60°,即使输入正弦波的相位为60°。相反,FFT频率的相位将是60 - 90度,因为-90°=angle(1/i) = angle(-i)。所以这实际上是正确的答案!要恢复正弦波的相位,您需要在FFT频率的相位上加上90°。
因此,总结起来,您需要解决两个问题:
  1. 确保你正在查看正确的频率区间。对于一个 N-点FFT(没有 fftshift),区间为 [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之间的区别!

1
如果不是因为出错,今天我不会学到这么多东西。 :-). 顺便说一句,我只是将原程序中的样本数量减少了1个 [0到1-1/fs],然后得到了-30。这与欧拉推导相匹配。非常感谢。 - Raj

0

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

 sig_fft_phase(201)
 ans = -30.000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接