当前位置: 首页 > 面试题库 >

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

柳仲卿
2023-03-14
问题内容

所以,我试图找出如何在实践中使用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是
就像信号是周期性的,但在边缘是不连续的
框架。它会产生被称为频谱泄漏的杂散频率。
开窗是解决这类问题和缓解问题的参考方法
与人工不连续性有关的问题。的确,一扇窗户的价值
在帧边缘附近连续减小到零。[有一个
窗口html" target="_blank">功能还有很多
窗口功能在中提供
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。



 类似资料:
  • 本节讨论了精度数学的四舍五入特性,ROUND()函数,以及插入DECIMAL列时的四舍五入特性。 ROUND()函数的行为取决于其参量是准确的还是近似的: ·对于准确值数值,ROUND()采用“半值向上舍入”规则:如果小数部分的值为.5或更大,如果是正数,向上取下一个整数,如果是负数,向下取下一个整数(换句话讲,以0为界限执行舍入)。如果小数部分的值小于.5,如果是正数,向下取下一个整数,如果是负

  • 问题内容: 我正在寻找四舍五入的价值 2.3913-> 2.5 4.6667-> 4.5 2.11-> 2 如何在SQL中进行管理? 谢谢 问题答案: 使您到最近的.5

  • 问题内容: 我怎么总是将a舍入为一个,而不舍入它。我知道,但是我希望它总是四舍五入。因此,如果为,则四舍五入为4。 问题答案: 您可以使用方法。 请参阅JavaDoc链接:https ://docs.oracle.com/javase/10/docs/api/java/lang/Math.html#ceil(double ) 从文档: 细胞 返回大于或等于自变量且等于数学整数的最小(最接近负无穷大

  • 我一直在尝试在java中使用bigdecimal进行取整,并遇到了一个java。显示非终止十进制扩展的lang.ArithmeticException错误。 谁能解释一下这个错误的起源吗?因为我对java还很陌生?帮我写代码? 谢谢 变量“d”是我认为产生错误的地方。

  • 如果一个数字有精确的二进制表示,比如(十进制)0.5,难道不应该正确地四舍五入吗? 编辑:该问题发生在3.4.3版本中,但不发生在2.7.6版本中