我用c#编写吉他调音器。使用NAudio库,我可以实时计算麦克风数据的FFT。当我想象它时,FFT运行良好,但是当我尝试提取基频时,我得到的结果远非我应该拥有的结果。 我想这与我在我的傅立叶数据中研究峰值的相当简单的方法有关:
//fft_size=size of the array containing the processed FFT
//Xs is the frequency axis of my computed FFT (double array)
//Ys is the amplitude axis of my computed FFT (double array)
int pk=0;
for (int p = 0; p < fft_size; p++)
{
if (Ys[p] > Ys[pk])
{
pk = p;
}
}
labelfrequency.Text=Xs[pk].ToString();
然后频率显示在窗体
上答案 0 :(得分:2)
不幸的是,由于两个原因,基频检测(通常称为&#34;音调检测&#34;)比仅进行FFT要困难一些。首先,FFT通常太粗糙(由于离散化),为您提供实际频率。因此,您需要进行一些后处理,以便从离散FFT数据中找到实际峰值。这并不难。其次,有时难以选择正确的峰值。通常,基频的峰值比其中一个泛音的峰值弱得多。
无需绝望。音调检测有很多工作,在wikipedia article中列举。 YIN是一个有效且相当简单的算法的例子,它可以处理上面列出的两个问题。 Web上有很多YIN实现。使用此算法时可能需要小心,因为您可能遇到知识产权问题。该算法可能已获得专利。
作为旁注,我们一直在研究小提琴等的音高检测,并且我们在低能量期间(在弓形运动开始时和声音消散时)难以进行音高检测。在这些情况下,我一直在考虑使用深度学习来梳理音高......
祝你的项目好运!
答案 1 :(得分:0)
峰值FFT幅度不起作用。 FFT峰值幅度频率和音调之间存在很大差异。
音高是一种心理声学现象,只与傅里叶分解中最大的正弦分量松散相关。这对于吉他声音尤其重要,其中音调声音可能具有弱的或缺失的基频分量,以及更强的泛音。因此,使用裸FFT幅度将使吉他调谐器非常差且不可靠。
即使基本音高由FFT幅度峰值表示,它也可能部分地位于FFT结果区间之间,对于短FFT中的极低音符,FFT结果区间可以间隔得比半音的距离更远或更远。 。因此,峰值箱中心频率将偏离实际音调频率,以&#34;美分&#34;音高测量精度。
相反,您需要尝试使用众多音高检测/估算算法中的一种(在以下系列中:加权自相关,ASDF,AMDF,倒谱分析,谐波产品频谱,YAPT / YIN,训练DNN等) ,也许也可以使用高质量的插值。