为什么用FFT在信号中四舍五入频率值?
所以,我试图找出如何在实践中使用DFT来检测流行的信号中的频率。我一直在想什么
傅立叶变换和DFT算法是如何工作的,但显然我仍然有路要走。我已经写了一些代码来生成一个信号(自从意图是配合音乐工作,我产生了一个主要的C和弦,因此怪异频率值),然后尝试返回到频率数字。在这里是我的密码吗
sr = 44100 # sample rate
x = np.linspace(0, 1, sr) # one second of signal
tpi = 2 * np.pi
data = np.sin(261.63 * tpi * x) + np.sin(329.63 * tpi * x) + np.sin(392.00 * tpi * x)
freqs = np.fft.fftfreq(sr)
fft = np.fft.fft(data)
idx = np.argsort(np.abs(fft))
fft = fft[idx]
freqs = freqs[idx]
print(freqs[-6:] * sr)
这给了我[-262。262-330. 330-392. 392.]
这和我编码的频率(261.63、329.63和392.0)。我做错什么了我该怎么修?
-
实际上,如果帧持续’T’秒,DFT的频率是’k/T’`
其中k是整数。因此,过采样并不能改善
估计频率的准确性,只要这些频率是
定义为DFT的最大值。相反,考虑到
持续100秒的较长帧将导致DFT频率之间的间隔
0.01Hz,这可能足以产生预期的频率。它
通过估计一个峰值的频率作为它的
与功率密度有关的平均频率
![输入图像描述]
[这里](https://i.stack.imgur.com/tF2tV.png)
图1:即使在应用Tuckey窗口之后,加窗信号的DFT
不是狄拉克的总和:在宇宙的底部仍然有一些光谱泄漏
山峰。在估计频率时,必须考虑这种功率。
另一个问题是帧的长度不是周期的倍数
不管怎样,它可能不是周期性的。然而,DFT是
就像信号是周期性的,但在边缘是不连续的
框架。它会产生被称为频谱泄漏的杂散频率。
开窗是解决这类问题和缓解问题的参考方法
与人工不连续性有关的问题。的确,一扇窗户的价值
在帧边缘附近连续减小到零。[有一个
窗口功能还有很多
窗口功能在中提供
scipy.信号. A
窗口应用为:tuckey_window=signal.tukey(len(data),0.5,True) data=data*tuckey_window
此时,最大震级的频率仍为262,330和392。应用一个窗口只会使峰值更明显:的DFT
加窗信号有三个明显的峰值,每个峰值都有一个中心瓣和旁瓣,取决于窗口的DFT。耳垂
其中一个窗口是对称的:因此中心频率可以计算为峰值的平均频率,与功率密度有关import numpy as np from scipy import signal import scipy sr = 44100 # sample rate x = np.linspace(0, 1, sr) # one second of signal tpi = 2 * np.pi data = np.sin(261.63 * tpi * x) + np.sin(329.63 * tpi * x) + np.sin(392.00 * tpi * x) #a window... tuckey_window=signal.tukey(len(data),0.5,True) data=data*tuckey_window data -= np.mean(data) fft = np.fft.rfft(data, norm="ortho") def abs2(x): return x.real**2 + x.imag**2 fftmag=abs2(fft)[:1000] peaks, _= signal.find_peaks(fftmag, height=np.max(fftmag)*0.1) print "potential frequencies ", peaks #compute the mean frequency of the peak with respect to power density powerpeak=np.zeros(len(peaks)) powerpeaktimefrequency=np.zeros(len(peaks)) for i in range(1000): dist=1000 jnear=0 for j in range(len(peaks)): if dist>np.abs(i-peaks[j]): dist=np.abs(i-peaks[j]) jnear=j powerpeak[jnear]+=fftmag[i] powerpeaktimefrequency[jnear]+=fftmag[i]*i powerpeaktimefrequency=np.divide(powerpeaktimefrequency,powerpeak) print 'corrected frequencies', powerpeaktimefrequency
结果估计频率为261.6359赫兹、329.637赫兹和392.0088赫兹
频率:远优于262、330、392Hz,满足要求对于这种纯无噪声输入信号,精度为0.01Hz。