为什么用FFT在信号中四舍五入频率值?

发布于 2021-01-29 18:22:37

所以,我试图找出如何在实践中使用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)。我做错什么了我该怎么修?

关注者
0
被浏览
53
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    实际上,如果帧持续’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。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看