2016-10-01 87 views
3

我用倍频程编写的小程序不能产生所需的相位谱。幅度图是完美的。倍频程:FFT相位谱不正确

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度。我究竟做错了什么?我的期望不正确?

+0

这 - > https://www.mathworks.com/matlabcentral/answers/1139#answer_1625似乎是一种解决同样的问题! –

回答

4

在你的榜样,如果生成的频率轴(对不起,我没有倍频这里,所以Python将不得不这样做 - 我确保它在八度相同):

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

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

(这是因为你的t载体包括1.0是一个额外的样品稍微降低了频谱间隔!我认为张贴在他们的评论的链接@Sardar_Usama是正确的,它没有任何关系的事实该正弦曲线并没有结束对一个完整的周期,因为这种方法不完全循环应该工作)

的溶液:零垫1001长sig矢量到2000个样品。然后,用新的faxis频率向量,faxis[400](八度的第401位的指数)恰好对应于200赫兹:

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 formula说的是sin(x) = (exp(i * x) - exp(-i * x))/2i。分母中的i表示即使输入正弦波具有60°相位,由FFT恢复的相位也不会是60°。相反,由于-90°= angle(1/i) = angle(-i),FFT仓的相位将为60 - 90度。所以这实际上是正确的答案!要恢复正弦波的相位,您需要将90°添加到FFT bin的相位。

所以总结一下,你需要解决两件事情:

  1. 确保你正在寻找正确的频点。对于N点FFT(并且没有fftshift),分箱是[0 : N - 1]/N * fs。上面,我们只使用了一个N = 2000点FFT来确保表示200 Hz。要知道,虽然你有一个正弦波,但就FFT而言,它有两个复指数,分别为+200和-200 Hz,幅值为1 /(2i)和-1 /(2i) 。分母中的这个虚数值将您期望的相位分别改变-90°和+ 90°。
    • 如果你碰巧使用了cos,余弦波,为sig,你就不会碰到这样的数学障碍,因此今后要注意区别正弦和余弦之间!
+1

如果不是罪,我今天就不会学到这么多东西。 :-)。顺便说一下,我简单地将原始程序中的样本数减少了1 [0-1-1/fs],得到了-30。它与欧拉推导相匹配。非常感谢。 – Raj

0

变化t=0:1/fs:1-1/fs;然后

sig_fft_phase(201) 
ans = -30.000