简体   繁体   English

八度:FFT相位谱不正确

[英]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: 总而言之,您需要修复两件事:

  1. make sure you're looking at the right frequency bin. 确保你正在查看正确的频率仓。 For an 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。
  2. Understand that, although you have a sine wave, as far as the FFT is concerned, it gets two complex exponentials, at +200 and -200 Hz, and with amplitudes 1/(2i) and -1/(2i). 要明白,尽管你有一个正弦波,但就FFT而言,它有两个复指数,分别为+200和-200Hz,振幅为1 /(2i)和-1 /(2i)。 That imaginary value in the denominators shifts the phase you expect by -90° and +90° respectively. 分母中的虚拟值将您期望的相位分别移动-90°和+ 90°。
    • If you happened to have used 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM