当信号频率恰好落在 fft bin 上时,Numpy FFT 会给出意想不到的结果

Numpy FFT give unexpected result when signal frequency falls exactly on a fft bin

当信号的频率恰好落在 FFT bin 上时,幅度变为 0! 但是如果我稍微偏移信号频率,结果就可以了。

复制代码:

这里信号的频率是30

import numpy as np
import matplotlib.pyplot as plt
N = 1024
Freq = 30
t = np.arange(N)
x = np.sin(2*np.pi*Freq/N*t)
f = np.fft.fft(x)
plt.plot(t, x)
plt.plot(t, f)

我希望输出在第 30 个 bin 中有一个巨大的尖峰,但它是平坦的,如下图所示。

但是,如果只是稍微将频率更改为 30.1 以使其不落在确切的 bin 上,

import numpy as np
import matplotlib.pyplot as plt
N = 1024
Freq = 30.1
t = np.arange(N)
x = np.sin(2*np.pi*Freq/N*t)
f = np.fft.fft(x)
plt.plot(t, x)
plt.plot(t, f)

结果正确如下图:

为什么?这是一个 numpy FFT 实现问题吗?还是标准FFT算法的限制?

f 是复数,我应该使用 abs(f) 进行绘图。 我忘记了 :P

  1. 要得到功率谱,需要取傅里叶系数的大小。绘制傅立叶系数直接舍弃虚部,只绘制实部。
  2. 从技术上讲,x 和 f 不应绘制在同一 x 轴上,因为它们具有不同的含义。
import numpy as np
import matplotlib.pyplot as plt

T = 1 # Total signal duration (s)
N = 1024 # samples over signal duration
Freq = 30 # frequency: (Hz)
t = np.arange(N)/N*T # time array

df = 1.0/T # resolution of angular frequency
f = np.arange(N)*df


x = np.sin(2*np.pi*Freq*t)
xhat = np.fft.fft(x) # Fourier series of x

plt.plot(t, x)
plt.xlabel("t (s)")
plt.ylabel("x")
plt.savefig("fig1.png")

plt.cla()
plt.plot(f, np.abs(xhat))
plt.xlabel("f (Hz)")
plt.ylabel("|fft(x)|")
plt.savefig("fig2.png")