我正在使用fft制作音高检测程序。为了获得音高,我需要找到明显高于本底噪声的最低频率。
所有结果都在一个数组中。每个位置都是一个频率。我不知道如何找到峰值。
我正在用C#编程。
以下是大胆的频率分析的屏幕截图。
答案 0 :(得分:2)
如果您对绝对值的概念有所期待会更容易,但我建议:
在糟糕的情况下,信号可能只是噪音水平的2或3倍。如果信号更好,你可以使用2xnoise的阈值。
编辑后,查看图片:
你应该从左边开始,找到一个局部最大值。看起来你可以使用30 dB阈值和10 bin窗口等。
答案 1 :(得分:2)
找到最低峰值将不能可靠地用于估算音高,因为此频率有时完全丢失,或者在本底噪声中降低。为了获得更好的可靠性,请尝试另一种算法:自相关(AMDF,ASDF滞后),倒谱(FFT对数FFT),谐波积谱,状态空间密度及其变量,使用神经网络,遗传算法或决策矩阵来决定替代音高假设(RAPT,YAAPT,et.al。)。
添加了:
也就是说,您可以猜测频率,计算频谱幅度的平均值和标准偏差,例如,围绕您的猜测的2:1频率范围,并查看是否存在明显高于平均值的峰值(2西格玛?)。冲洗并重复一些频率猜测,并查看哪一个或最低的几个具有与平均值相比最高的峰值。使用那个峰值。
答案 2 :(得分:2)
我不会试图找到最低峰值,而是寻找一个基频,它可以最大化前5个整数倍所捕获的光谱能量。请注意,每个峰值都是最低峰值的整数倍。这是倒谱法的一种破解。不要判断:)。
N.B。从您的图中,我假设1024个采样窗口和44.1kHZ采样率。这产生的频率粒度仅为44.1kHz / 1024 = 43Hz。给定44.1kHz音频,我建议使用更长的分析窗口~50 ms或2048个样本。这将产生~21 Hz的更精细的频率粒度。
假设一个大小为2048的Matlab矢量'psd'具有PSD值。
% 50 Hz (Dude) -> 50Hz/44100Hz * 2048 -> ~2 Lower Lim
% 300 Hz (Baby) -> 300Hz/44100Hz * 2048 -> ~14 Upper Lim
lower_lim = 2;
upper_lim = 14
for fund_cand = lower_lim:1:upper_lim
i_first_five_multiples = [1:1:5]*fund_cand;
sum_energy = sum(psd(i_first_five_multiples));
end
我会找到最大化sum_energy值的频率。