[英]Octave:Incorrect FFT phase spectrum
A small program that I wrote in octave does not yield desired phase spectrum. 我用八度音程写的一个小程序没有产生所需的相位谱。 The magnitude plot is perfect though. 虽然幅度图很完美。
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 degrees) rather than 60 degrees. sig_fft_phase(201)
返回5.998(6度)而不是60度。 What am I doing wrong? 我究竟做错了什么? Is my expectation incorrect? 我的期望不正确吗?
In your example, if you generate the frequency axis: (sorry, I don't have Octave here, so Python will have to do—I'm sure it's the same in Octave): 在你的例子中,如果你生成频率轴:(抱歉,我这里没有Octave,所以Python必须这样做 - 我确定它在Octave中是相同的):
faxis = (np.arange(0, t.size) / t.size) * fs
you'll see that faxis[200]
(Python is 0-indexed, equivalent to Octave's 201 index) is 199.80019980019981 . 你会看到faxis[200]
(Python是0索引,相当于Octave的201索引)是199.80019980019981 。 You think you're asking for the phase at 200 Hz but you're not, you're asking for the phase of 199.8 Hz. 你认为你要求200赫兹的相位,但你不是,你要求相位为199.8赫兹。
(This happens because your t
vector includes 1.0—that one extra sample slightly decreases the spectral spacing! I don't think the link @Sardar_Usama posted in their comment is correct—it has nothing to do with the fact that the sinusoid doesn't end on a complete cycle, since this approach should work with incomplete cycles.) (这是因为你的t
向量包含1.0 - 一个额外的样本稍微减少了光谱间距!我不认为他们的评论中张贴的链接@Sardar_Usama是正确的 - 它与正弦曲线没有关系的事实无关结束一个完整的循环,因为这种方法应该在不完整的循环中起作用。)
The solution: zero-pad the 1001-long sig
vector to 2000 samples. 解决方案:将1001长的sig
矢量零填充到2000个样本。 Then, with a new faxis
frequency vector, faxis[400]
(Octave's 401st index) corresponds to exactly 200 Hz: 然后,使用新的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
But oh no, what happened? 但是哦,不,发生了什么? This says the angle is -30°? 这说角度是-30°?
Well, recall that Euler's formula says that sin(x) = (exp(i * x) - exp(-i * x)) / 2i
. 好吧,回想起欧拉的公式说sin(x) = (exp(i * x) - exp(-i * x)) / 2i
。 That i
in the denominator means that the phase recovered by the FFT won't be 60°, even though the input sine wave has phase of 60°. 即使输入正弦波的相位为60°,分母中的i
意味着FFT恢复的相位不会是60°。 Instead, the FFT bin's phase will be 60 - 90
degrees, since -90° = angle(1/i) = angle(-i)
. 相反,FFT bin的相位将是60 - 90
度,因为-90°= angle(1/i) = angle(-i)
。 So this is actually the right answer! 所以这实际上是正确的答案! To recover the sine wave's phase, you'd need to add 90° to the phase of the FFT bin. 要恢复正弦波的相位,您需要在FFT bin的相位上添加90°。
So to summarize, you need to fix two things: 总而言之,您需要修复两件事:
N
-point FFT (and no fftshift
), the bins are [0 : N - 1] / N * fs
. 对于N
点FFT(并且没有fftshift
),区间为[0 : N - 1] / N * fs
。 Above, we just used a N=2000 point FFT to ensure that 200 Hz be represented. 上面,我们只使用N = 2000点FFT来确保表示200 Hz。 cos
, a cosine wave, for sig
, you wouldn't have run into this mathematical obstacle 😆, so pay attention to the difference between sin and cos in the future 💪! 如果你碰巧使用cos
,余弦波,对于sig
,你就不会遇到这个数学障碍😆,所以要注意将来sin和cos之间的区别💪! change to t=0:1/fs:1-1/fs;
改为t=0:1/fs:1-1/fs;
then 然后
sig_fft_phase(201)
ans = -30.000
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.