2016-10-01 37 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