在你的榜樣,如果生成的頻率軸(對不起,我沒有倍頻這裏,所以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的相位。
所以總結一下,你需要解決兩件事情:
- 確保你正在尋找正確的頻點。對於
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
,你就不會碰到這樣的數學障礙,因此今後要注意區別正弦和餘弦之間!
這 - > https://www.mathworks.com/matlabcentral/answers/1139#answer_1625似乎是一種解決同樣的問題! –