从潜在谐波确定基频的算法

时间:2011-01-17 18:42:09

标签: algorithm signal-processing estimation pitch

我试图从声源中提取基频。也许是有人在麦克风上唱A3,所以我想要检测~110Hz

我的方法是:

  • FFT 1024浮动
  • 使用每个箱子的相位来准确地确定其精确频率
  • 确定峰值(通常为50左右)
  • 用最响亮的第一个命令他们

(峰值[0] .power = 1063.343750,.freq = 2032.715088
(峰值[1] .power = 1047.764893,.freq = 3070.605225
(峰值[2] .power = 1014.986877,.fr​​eq = 5925.878418
(峰值[3] .power = 1011.707825,.freq = 6963.769043
(峰值[4] .power = 1009.152954,.freq = 4022.363037
(峰值[5] .power = 995.199585,.freq = 4974.120605
(峰值[6] .power = 987.243713,.freq = 8087.792480
(峰值[7] .power = 533.514832,.freq = 908.691833

  • (MARKER1)以最响亮的方式开始,并将其与所有剩余的峰值相匹配,所以如果我有N个峰值,此时我将有N-1个峰值对
  • 检查每个峰值对的谐度;即它与某个分数a / b有多接近,即我们能找到b <20的a / b,使得| peakA.freq / peakB.freq - a / b | &LT; 0.01(这将匹配到20日的谐波)
  • 我们现在有一个精确的峰值列表,这些峰值被认为是彼此谐波的

    Harmonic PeakPair:(0,1)= 2/3,误差:0.00468 =&gt; f0 @ 1019.946289
      Harmonic PeakPair:(0,2)= 1/3,误差:0.00969 =&gt; f0 @ 2004.003906
      Harmonic PeakPair:(0,3)= 2/7,误差:0.00618 =&gt; f0 @ 1005.590820
      Harmonic PeakPair:(0,4)= 1/2,误差:0.00535 =&gt; f0 @ 2021.948242
      Harmonic PeakPair:(0,5)= 2/5,误差:0.00866 =&gt; f0 @ 1005.590820
      Harmonic PeakPair:(0,6)= 1/4,误差:0.00133 =&gt; f0 @ 2027.331543
      Harmonic PeakPair:(0,7)= 9/4,误差:0.01303 =&gt; f0 @ 226.515106

我的问题是:如何设计一种能够正确识别上述基波的算法~1000Hz?

绝不保证在~1000处的值集中度高于~2000或~3000等。甚至不能保证任何入口〜1000。我们可以有~5000 x一个条目,~4000 x三个条目,~3000 x 2条目,以及漂浮的几个虚假值,如上面列表中的226.

我想我可以再次重复这个程序,淘汰与列表其余部分不“谐波”的建议基础。这至少可以摆脱伪造的价值......

可能我甚至没有问正确的问题。也许这整个方法很糟糕。但我认为选择最强的峰值并提取与该峰值相关的一组谐波是有意义的。

理论上应该产生一定比例的负载,比如说原始最强峰值是三次谐波,那么这组峰值应该包含3/1 3/2 3/3 3/4 3/5 3/6 3 / 7等......虽然有些可能会丢失。

实际上我觉得它总是要么是基础的,要么是具有最大力量的一次谐波。但我不知道我是否可以依靠这个...

这么多因素,让我头脑发热。我提前为这样一个混乱的问题道歉。希望我可以在死后收拾它。

3 个答案:

答案 0 :(得分:8)

Cepstum(或倒谱分析)和谐波产品谱是两种经过充分研究的算法,用于估计泛音系列的激励频率。

如果泛音序列间隔适当,则倒谱(FFT峰值的对数的FFT)可用于估计频率间隔的周期,然后可用于估计频率。

谐波产品谱基本上通过用多个低整数比率抽取光谱并将它们重叠来比较光谱峰值与它们自身的第n个多个副本。

答案 1 :(得分:2)

您可以通过以下链接查看有关语音识别的文章。

文章:Phase Space Point Disribution Parameter for Speech Recognition(全文需要订阅)

答案 2 :(得分:1)

我已经改写了这个问题,并在此提供了答案:How to take in a set of numbers like {301,102,99,202,198,103} and throw out ~100?

我看过几种方法,这比我发现的任何其他方法都简洁得多。我已对它进行了测试,效果非常好。