实时音调检测

时间:2009-08-30 15:17:18

标签: audio signal-processing fft pitch pitch-tracking

我正在尝试对用户唱歌进行实时音高检测,但我遇到了很多问题。我已经尝试了很多方法,包括FFT(FFT Problem (Returns random results))和自相关(Autocorrelation pitch detection returns random results with mic input),但我似乎无法获得任何方法来提供良好的结果。任何人都可以建议一种实时音高跟踪方法或如何改进我已有的方法?我似乎找不到任何用于实时音高检测的好的C / C ++方法。

谢谢,

尼尔。

编辑:请注意,我已经检查过麦克风输入数据是否正确,并且当使用正弦波时,结果或多或少是正确的音高。

编辑:对不起,这已经晚了,但是此刻,我通过从结果数组和每个索引中取出值,并在X轴上绘制索引和在Y轴上绘制值来显示自动相关(两者都是除了100000或其他东西,我使用OpenGL),将数据插入VST主机并使用VST插件不是我的选择。目前,它看起来像一些随机点。我正确地做了,或者你能不能指点我做一些代码,或者帮助我理解如何可视化原始音频数据和自相关数据。

12 个答案:

答案 0 :(得分:31)

退一步......为了实现这一目标,你必须找出一种方法来绘制这个过程的中间步骤。你要做的不是特别难,但它容易出错。削波,开窗,接线不良,走样,直流偏移,读取错误的通道,奇怪的FFT频率轴,阻抗不匹配,帧大小错误......谁知道。但是,如果您可以绘制原始数据,然后绘制FFT,那么一切都将变得清晰。

答案 1 :(得分:19)

我找到了几个实时音高跟踪的开源实现

还有一些音高跟踪器可能不是专为实时设计的,但可能对我所知的所有方式都可用,也可用作比较实时跟踪器的参考: / p>

答案 2 :(得分:7)

我知道这个答案不会让每个人都开心,但这里就是这样。

这个东西很难,很难。首先阅读尽可能多的关于FFT,自相关,小波的教程。虽然我仍在努力学习DSP,但我确实从以下方面获得了一些见解。

https://www.coursera.org/course/audio课程目前尚未投放,但视频仍然可用。

http://miracle.otago.ac.nz/tartini/papers/Philip_McLeod_PhD.pdf关于音高识别算法开发的论文。

http://dsp.stackexchange.com一个致力于数字信号处理的整个网站。

如果像我一样你没有做足够的数学来完全遵循教程,不要放弃,因为一些图表和例子仍然帮助我理解发生了什么。

接下来是测试数据和测试。给自己写一个库,生成用于检查算法的测试文件。

1)超级简单的纯正弦波发生器。所以说你正在寻找写YAT(Yet Another Tuner)然后使用你的正弦发生器创建一系列440Hz左右的文件,比如420-460Hz不同的增量,看看你的代码是多么敏感和准确。它可以解决到5Hz,1Hz,更精细吗?

2)然后升级正弦波发生器,使其在信号中增加一系列较弱的谐波。

3)接下来是谐波的真实世界变化。因此,对于大多数弦乐器而言,您会看到一系列谐波是基频F0的简单倍数,对于单簧管和长笛等乐器,由于空气在腔室中的行为方式,偶数谐波将会丢失或非常弱。对于某些仪器,F0缺失但可以根据其他谐波的分布来确定。 F0是人耳所认为的音高。

4)通过以不规则的方式上下移动谐波峰值频率来引起一些故意的失真

关键在于,如果您正在创建具有已知结果的文件,那么更容易验证您正在构建的内容是否正常工作,当然还有错误。

还有许多包含声音样本的“图书馆”。 来自上述Coursera系列的https://freesound.orghttp://theremin.music.uiowa.edu/MIS.html

接下来请注意,您的麦克风并不完美,除非您花了数千美元,否则它的频率响应范围会相当不同。特别是如果您使用低音符然后便宜的麦克风,阅读PC或手机中的内置麦克风,则会在80-100Hz左右开始显着降低音量。对于相当好的外部设备,你可能会降到30-40Hz。去找麦克风上的数据。

您还可以通过扬声器播放音调然后使用您喜欢的麦克风录制来检查会发生什么。但当然,现在我们讨论的是两组频率响应曲线。

在性能方面,有许多免费提供的库,但要注意各种许可模式。

最重要的是,在你的第一次尝试后不要放弃。祝你好运。

答案 3 :(得分:5)

我在几年前做过的项目中有类似麦克风输入的问题 - 原来是由于DC偏移。

请确保在尝试使用FFT或使用其他任何方法之前删除任何偏差。

您也可能遇到头上空间或裁剪问题。

图表是诊断大多数音频问题的最佳方式。

答案 4 :(得分:5)

这里是我设计的一个不寻常的两阶段算法的C ++源代码,它可以在播放时对复音 MP3文件进行实时音高检测视窗。这个免费应用程序( PitchScope Player ,可在网上获得)经常用于在MP3录制时检测吉他或萨克斯独奏的音符。该算法被设计为在MP3音乐文件中的任何给定时刻检测最主要的音调(音符)。在MP3录音期间的任何给定时刻,最主要音高(音符)的显着变化准确地推断音符开始。

当在钢琴上按下单个琴键时,我们听到的不仅仅是声音振动的一个频率,而是在不同数学相关频率下发生的多个声音振动的复合。这种不同频率的振动合成元素被称为谐波或部分。例如,如果我们按下钢琴上的中间C键,复合波的各个频率将以261.6 Hz开始作为基频,523 Hz将是2次谐波,785 Hz将是3次谐波,1046 Hz将是第四谐波等。后面的谐波是基频的整数倍,261.6 Hz(例如:2 x 261.6 = 523,3 x 261.6 = 785,4 x 261.6 = 1046)。在底部链接,是在吉他独奏的复音MP3录制过程中发生的实际谐波的快照。

我使用具有对数频率间隔的改进DFT变换来代替FFT,通过查找具有峰值电平的频率来首先检测这些可能的谐波(参见下图)。由于我为修改后的Log DFT收集数据的方式,我不必对信号应用窗口函数,也不必添加和重叠。我创建了DFT,因此它的频道以对数方式定位,以便直接与吉他,萨克斯管等音符创建谐波的频率对齐。

现在已退休,我决定在名为 PitchScope Player 的免费演示应用程序中发布我的音高检测引擎的源代码。 PitchScope Player可在网上获得,您可以下载Windows的可执行文件,以便在您选择的mp3文件上查看我的算法。下面链接到GitHub.com将引导您到我的完整源代码,您可以在其中查看我如何使用自定义对数DFT变换检测谐波,然后查找其频率满足正确整数关系的部分(谐波),该关系定义了& #39;音调'

我的音高检测算法实际上是一个两阶段过程:a)首先检测 ScalePitch (' ScalePitch'有12个可能的音高值:{E,F,F# ,G,G#,A,A#,B,C,C#,D,D#})b)并且在确定ScalePitch之后,通过检查4个可能的Octave的所有谐波来计算 Octave -Candidate notes。该算法旨在检测复音MP3文件中任何给定时刻的最主要音高(音符)。这通常对应于乐器独奏的音符。那些对我的两阶段音高检测算法的C ++源代码感兴趣的人可能想要从GitHub.com的SPitchCalc.cpp文件中的Estimate_ScalePitch()函数开始。 https://github.com/CreativeDetectors/PitchScope_Player

以下是对数DFT(由我的C ++软件创建)在复音mp3录音中进行3秒钟吉他独奏的图像。它显示了在演奏独奏时吉他上各个音符的谐波是如何出现的。对于此对数DFT上的每个音符,我们可以看到它的多个谐波垂直延伸,因为每个谐波将具有相同的时间宽度。在确定音符的八度音符之后,我们知道基音的频率。

enter image description here

答案 5 :(得分:2)

查看aubio和开源库,其中包括一些最先进的音高跟踪方法。

答案 6 :(得分:2)

看看这个示例应用程序:

http://www.codeproject.com/KB/audio-video/SoundCatcher.aspx

我意识到应用程序是在C#中,你需要C ++,我意识到这是.Net / Windows,你在Mac上...但我认为他的FFT实现可能是一个起始参考点。尝试比较你的FFT实现。 (他是Cooley-Tukey的FFT的迭代,广度优先版本)。它们相似吗?

此外,您所描述的“随机”行为可能是因为您正在直接获取声卡返回的数据,而无需正确组合字节数组中的值。您是否要求您的声卡采样16位值,然后给它一个字节数组来存储值?如果是这样,请记住返回数组中的两个连续字节组成一个16位音频样本。

答案 7 :(得分:2)

http://code.google.com/p/freqazoid/提供了实时实时检测器的Java代码。

它在运行2008年后实时Java的任何计算机上运行良好。该项目已被撤销,任何有兴趣的团体都可以接收。如果您想了解更多详情,请与我联系。

答案 8 :(得分:1)

我在这里问了一个类似的问题:

C/C++/Obj-C Real-time algorithm to ascertain Note (not Pitch) from Vocal Input

编辑:

Performous包含用于实时音高检测的C ++模块

Yin音高跟踪算法

答案 9 :(得分:0)

你能适应乐器调音器的任何东西吗?我令人愉快的紧凑型吉他调音器能够很好地检测琴弦的音高。我看到这个引用piano tuner,它在某种程度上解释了算法。

答案 10 :(得分:0)

以下是一些实现音高检测的开源库:

  • WORLD:语音分析/合成工具包。如果您的源信号是语音,这尤其适用。
  • aubio:音频特征提取库。实现许多音高检测算法。
  • Pitch detection:用C ++实现的音高检测算法的集合。
  • dywapitchtrack:一种高质量的音高检测算法。
  • YIN:在单个C ++源文件中YIN算法的另一种实现方式。

答案 11 :(得分:0)

您可以使用 TarsosDSP 进行实时音高检测,无论是歌手的声音 https://github.com/JorenSix/TarsosDSP 以防万一有人还没有听说过:-)