27

我正在尝试对用户唱歌进行实时音高检测,但遇到了很多问题。我尝试了很多方法,包括 FFT(FFT 问题(返回随机结果))和自相关(自相关音高检测返回带有麦克风输入的随机结果),但我似乎无法获得任何方法来给出好的结果。谁能建议一种实时音高跟踪的方法或如何改进我已有的方法?我似乎找不到任何用于实时音高检测的好的 C/C++ 方法。

谢谢,

尼尔。

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

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

4

12 回答 12

35

退后一步...要使此工作正常进行,您必须找到一种方法来绘制此过程的中间步骤。您尝试做的事情并不是特别难,但它容易出错且很繁琐。削波、开窗、接线不良、混叠、直流偏移、读取错误的通道、奇怪的 FFT 频率轴、阻抗不匹配、帧大小错误……谁知道呢。但如果你可以绘制原始数据,然后绘制 FFT,一切都会变得清晰。

于 2009-08-30T19:16:57.660 回答
21

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

  • dywapitchtrack使用基于小波的算法

  • “Realtime C# Pitch Tracker”使用修改后的自相关方法,现已从 Codeplex 中移除 - 尝试在 GitHub 上搜索

  • aubio(由 piem 提到;有几种算法可用)

还有一些音高跟踪器可能不是为实时设计的,但据我所知可能以这种方式使用,并且也可以作为参考来比较您的实时跟踪器:

于 2011-09-09T03:10:45.453 回答
10

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

这东西很难,非常难。首先阅读尽可能多的关于 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)通过以不规则的方式上下移动谐波峰值频率来引发一些故意的失真

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

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

接下来请注意,您的麦克风并不完美,除非您花费数千美元购买它,否则它将具有相当可变的频率响应范围。特别是如果您使用的是低音,那么便宜的麦克风,阅读您的 PC 或手机中的内置麦克风,从 80-100Hz 左右开始会有显着的衰减。对于相当好的外部设备,您可能会降至 30-40Hz。去找你麦克风上的数据。

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

在性能方面,有许多免费可用的库,但请注意各种许可模型。

最重要的是不要在你的前几次尝试后放弃。祝你好运。

于 2015-01-24T00:46:11.337 回答
7

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

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

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

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

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

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

在此处输入图像描述

于 2016-07-30T18:38:54.177 回答
5

在几年前我做的一个项目中,我在麦克风输入方面遇到了类似的问题——结果证明是由于直流偏移造成的。

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

您也可能遇到净空或削波问题。

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

于 2009-08-30T16:22:53.610 回答
2

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

于 2009-12-10T17:43:55.500 回答
2

看看这个示例应用程序:

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

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

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

于 2010-09-02T02:33:32.277 回答
2

实时真实检测器的 Java 代码可在http://code.google.com/p/freqazoid/ 获得

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

于 2012-01-16T20:04:00.303 回答
1

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

C/C++/Obj-C 实时算法从人声输入中确定音符(不是音高)

编辑:

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

Also Yin Pitch-Tracking 算法

于 2010-11-19T01:11:38.573 回答
1

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

于 2021-01-11T22:35:40.440 回答
0

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

于 2009-08-30T15:50:38.370 回答
0

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

  • WORLD:语音分析/合成工具包。如果您的源信号是语音,这尤其适用。
  • aubio:音频特征提取库。实现了许多音高检测算法。
  • 音高检测:一组用 C++ 实现的音高检测算法。
  • dywapitchtrack:一种高质量的音高检测算法。
  • YIN:单个 C++ 源文件中 YIN 算法的另一种实现。
于 2020-02-24T17:59:09.013 回答