bod*_*ous 7 signal-processing fft pitch-detection
关于FFT和音调检测,Stackoverflow及其他方面已经进行了无数次讨论.
人们普遍认为,虽然快速,但对于许多应用来说,FFT并不是非常准确,但它并不经常解释原因.
我想解释一下为什么会出现这种情况的理解,希望比我更聪明的人能够纠正我并填补我无法做到的空白.
FFT将输入数据从时域转换到频域.
最初,我们从一系列数据开始,如果我们要绘制在图表上,将在Y轴上的给定时间点具有声音的幅度,并且沿X轴具有时间.这是在时域.
FFT将这些时间点的振幅值转换为不同频率的振幅.
从FFT输出的数据的数量是SAME作为数据输入的数量
如果我们输入10个时间点的幅度(10个样本),FFT将输出这些样本中10个不同频率的幅度(在乘以虚数和实数的sqrt之后).
哪些频率由以下因素决定:
我们将FFT的输出称为bin,通过将采样率除以FFT中的采样数来计算每个bin的宽度:
bin width = Sample Rate(Hz)/FFT Length (n samples)
Run Code Online (Sandbox Code Playgroud)
有了一些真正的价值,那可能是:
bin_width = 44100/512 = 86.132
因此,我们的FFT有512个区间(记住它的数据与输出数据相同),每个区域的频率为86.132 Hz.
因此,对于给定的bin,我们可以计算它代表的频率:
Bin Freq (Hz) = Bin number (n) * bin width (Hz)
Run Code Online (Sandbox Code Playgroud)
使用上面的值,FFT输出中的第3个bin表示258.398Hz的幅度:
Bin Freq (Hz) = 3 * 86.132 = 258.396Hz
Run Code Online (Sandbox Code Playgroud)
这意味着对于给定的采样率和缓冲区大小,FFT输出不能比±86.132Hz更精确.
如果您需要更高的精度(例如1Hz),则必须降低采样率或增加缓冲区大小(或两者).
desired bin width: 1Hz = 44100 / 44100 # A buffer size of 44100 would work in this instance
Run Code Online (Sandbox Code Playgroud)
随着缓冲区大小越来越接近采样率,延迟问题变得更加严重.
FFT Results per second = Sample Rate / Buffer Size = 44100/44100 = 1 FFT per second
Run Code Online (Sandbox Code Playgroud)
(每秒44100个样本,填充44100个样本缓冲区=每秒1个完整缓冲区).
我意识到FFT不仅仅是计算基频(具有最高振幅的箱子),而且到目前为止我对Pitch Detection中FFT的理解是否正确?
有没有办法在不牺牲延迟的情况下提高FFT的准确性?
除了 @HartmutPfitzinger 推荐零填充和插值的好答案之外,值得指出的是,从限时信号提取的傅立叶变换中获得的信息存在重要的基本限制。
考虑零填充的极限情况 - 例如,获取单个样本,然后将其填充到 1 秒持续时间,以便进行分辨率为 1 Hz 的傅里叶变换。很明显,非常短的信号片段根本不包含有关周期性的信息。直观上,我们需要一个比所讨论的周期更长的片段,以便能够判断信号是否真的在该周期重复。
如果我们对周期信号的形状有限制,我们可以做得更好。例如,如果我们只寻找单个正弦曲线(即,我们知道我们的信号是 s(t) = A*cos(w*t + phi)),那么我们可以求解未知的幅度 A、频率 w 和相位phi 使用少至三个 s(t) 样本。然而,我们很少看到完全符合该公式的信号。至少我们预计会增加噪声,但大多数情况下我们会产生大量谐波,即未知的非正弦周期波形。
如果您尝试实现上面建议的插值峰值选取和/或零填充,然后查看当您缩短信号摘录时获得的结果(同时保持 FFT 长度相同),您将看到不确定性(错误)随着片段变短而增长 - 当片段短于您要测量的周期长度的两倍左右时,您可能会得到无用的结果。
这说明了一个有点违反直觉但非常基本的限制:很难根据短于 T 秒的观察来确定信号的频率是否优于 1/T Hz。这有时被称为不确定性原理,在数学上它与量子力学中的海森堡不确定性原理相同。
最后,我用来提高离散傅立叶变换分辨率的另一项技术是瞬时频率,如下所述:
Toshihiko Abe、Takao Kobayashi、Satoshi Imai:基于瞬时频率的噪声环境中的稳健基音估计和谐波增强。ICSLP 1996(您可以在线找到 PDF,我的链接限额已用完)。
频率只是相位对时间的导数;事实证明,您可以使用“按部分求导”,通过使用不同的窗函数(一个是另一个的导数)组合两个 FFT 的实部和虚部,直接计算每个 FFT 箱中的瞬时频率。有关 Matlab 实现,请参阅
http://labrosa.ee.columbia.edu/matlab/chroma-ansyn/ifgram.m
或者在Python中:
https://github.com/bmcfee/librosa/blob/master/librosa/core.py#L343
| 归档时间: |
|
| 查看次数: |
1685 次 |
| 最近记录: |