【问题标题】:Extract fundamental frequency from FFT从 FFT 中提取基频
【发布时间】:2018-08-17 00:25:01
【问题描述】:

我正在用 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();

然后在windows窗体上显示频率

【问题讨论】:

  • 可能需要比这更相关的代码... fft_size - 这是原始数据缓冲区的大小吗?还是 FFT 处理的数组大小?您使用什么数据类型?什么是pk?等等......请用更多信息编辑您的问题
  • 你是说你没有找到正确的 FFT 峰值索引?
  • @PaulF 是的,当我播放正弦波时,返回的值远非正确。我知道问题不是来自我的 FFT,因为我可以将其可视化

标签: c# signal-processing fft naudio


【解决方案1】:

不幸的是,基频检测(通常称为“音高检测”)比仅进行 FFT 更难,原因有两个。首先,FFT 通常过于粗糙(由于离散化),无法为您提供实际频率。因此,您需要进行一些后处理才能从离散 FFT 数据中找到实际峰值。这并不难做到。其次,有时很难选择正确的峰值。通常,基频的峰值比泛音之一的峰值要弱得多。

无需绝望。音高检测有很多工作,在这个wikipedia article中列举了。 YIN 是一个有效且相当简单的算法示例,可以处理上面列出的两个问题。网上有很多 YIN 的实现。使用此算法时可能需要小心,因为您可能会遇到知识产权问题。该算法可能已获得专利。

顺便说一句,我们一直致力于小提琴等的音高检测,但在低能量期间(在弓运动开始和声音消散时)检测音高有困难。我什至一直在考虑在这些情况下使用深度学习来梳理球场......

祝你的项目好运!

【讨论】:

    【解决方案2】:

    峰值 FFT 幅度不起作用。 FFT峰值幅度频率和音高之间存在很大差异。

    音高是一种心理声学现象,仅与傅里叶分解的最大正弦分量松散相关。这对于吉他声音尤其重要,因为在吉他的声音中,基频分量可能较弱或缺失,而泛音较强。因此,使用简单的 FFT 幅度将使吉他调音器变得非常糟糕且不可靠。

    即使基本音高由 FFT 幅度峰值表示,它也可能最终部分位于 FFT 结果箱之间,对于短 FFT 中的非常低的音符,这些箱之间的间隔可能比半个半音更远或更远.因此,就“音分”音高测量精度而言,峰值 bin 中心频率将远离实际音高频率。

    相反,您需要尝试使用多种音高检测/估计算法中的一种(在以下系列中:加权自相关、ASDF、AMDF、倒谱分析、谐波积谱、YAPT/YIN、训练的 DNN 等) ,也许还可以使用高质量的插值。

    【讨论】:

      猜你喜欢
      • 2014-03-22
      • 2013-01-13
      • 2013-04-01
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      • 2012-05-18
      • 2012-01-09
      相关资源
      最近更新 更多