32

我正在寻找从声音信号中提取音高。

IRC 上的某个人刚刚向我解释了采用双 FFT 是如何实现这一点的。具体来说:

  1. 采取 FFT
  2. 取绝对值平方的对数(可以通过查找表完成)
  3. 再做一次 FFT
  4. 取绝对值

我正在尝试使用 vDSP

我无法理解我之前怎么没有遇到过这种技术。我做了很多狩猎和提问;几个星期的价值。更重要的是,我不明白为什么我没有想到它。

我正在尝试使用 vDSP 库来实现这一点。它看起来好像具有处理所有这些任务的功能。

但是,我想知道最终结果的准确性。

我以前使用过一种技术,该技术可以搜索单个 FFT 的频率区间以获得局部最大值。当它遇到一个时,它会使用一种巧妙的技术(自上次 FFT 以来的相位变化)来更准确地将实际峰值放置在 bin 内。

我担心我在这里介绍的这种技术会失去这种精度。

我想该技术可以在第二次 FFT 之后使用,以准确地获得基础。但看起来信息在第 2 步中丢失了。

由于这是一个潜在的棘手过程,有经验的人可以看看我在做什么并检查它的完整性吗?

另外,我听说有一种替代技术涉及在相邻的 bin 上拟合二次方。这是否具有可比性的准确性?如果是这样,我会喜欢它,因为它不涉及记住 bin 阶段。

所以,问题:

  • 这种方法有意义吗?可以改进吗?
  • 我有点担心“对数方”组件;似乎有一个 vDSP 函数可以做到这一点:vDSP_vdbcon。但是,没有迹象表明它预先计算了一个日志表——我认为它没有,因为 FFT 函数需要调用一个显式的预先计算函数并将其传递给它。而这个功能没有。
  • 是否存在拾取谐波的危险?
  • 有没有什么巧妙的方法可以让 vDSP 拉出最大值,最大的优先?
  • 谁能指出我对这种技术的一些研究或文献?

  • 主要问题:它是否足够准确?精度可以提高吗?一位专家刚刚告诉我,准确性确实不够。这是行的尽头吗?

圆周率

PS 当我想创建标签时我很生气,但不能。:| 我已经向维护者建议跟踪尝试的标签,但我确定我被忽略了。我们需要 vDSP、加速框架、倒谱分析的标签

4

5 回答 5

80

好,我们来一一道来:

我正在寻找从声音信号中提取音高。

虽然我不是专家并且接受过最少的正式培训,但我想我知道这个问题的最佳答案。在过去的几年里,我做了很多搜索、阅读和实验。我的共识是,就准确性、复杂性、噪声鲁棒性和速度之间的权衡而言,自相关方法是迄今为止最好的音高检测器。除非您有一些非常具体的情况,否则我几乎总是建议使用自相关。稍后再详细介绍,让我回答您的其他问题。

您描述的是“倒谱分析”,这是一种主要用于从语音中提取音高的方法。倒谱分析完全依赖于信号泛音的丰富程度和强度。例如,如果你要通过倒谱分析传递一个纯正弦波,你会得到可怕的结果。然而,对于复杂信号的语音,存在大量泛音。(顺便说一下,泛音是信号的元素,它以基频的倍数振荡,即我们感知的音高)。倒谱分析在检测缺少基频的语音方面可以很稳健。也就是说,假设您绘制了函数罪(4x)+罪(6x)+罪(8x)+罪(10x)。如果你看一下,很明显它与函数 sin(2x) 具有相同的频率。但是,如果您对该函数应用傅立叶分析,则对应于 sin(2x) 的 bin 的量级为零。因此,该信号被认为具有“缺失的基频”,因为它不包含我们认为的频率的正弦曲线。因此,简单地选择傅立叶变换上的最大峰值对这个信号不起作用。

我以前使用过一种技术,该技术可以搜索单个 FFT 的频率区间以获得局部最大值。当它遇到一个时,它会使用一种巧妙的技术(自上次 FFT 以来的相位变化)来更准确地将实际峰值放置在 bin 内。

您所描述的是相位声码器技术,可以更准确地测量给定部分的频率。但是,如果您使用的信号缺少基频分量或基频分量较弱,那么挑选出最​​大分档的基本技术会给您带来麻烦。

我担心我在这里介绍的这种技术会失去这种精度。

首先,请记住相位声码器技术只能更准确地测量单个分音的频率。它忽略了较高部分中包含的关于基频的信息。其次,给定一个不错的 FFT 大小,您可以使用峰值插值获得非常好的精度。这里的其他人已将您指向抛物线插值。我也建议这样做。

如果您在 44100 Hz 处以大约 440 Hz 的间距对 4098 个样本数据块的 FFT 进行抛物线插值,这将意味着它将位于第 40 个(430.66 Hz)和第 41 个(441.430664064)bin 之间。假设这篇论文在一般情况下大致正确,它说抛物线插值将分辨率提高了一个数量级以上。这使得分辨率至少为 1 Hz,这是人类听觉的阈值。事实上,如果你使用理想的高斯窗,抛物线插值在峰值处是精确的(没错,精确。但是请记住,你永远不能使用真正的高斯窗,因为它在两个方向上永远延伸。)如果你是仍然担心获得更高的精度,您可以随时填充 FFT。这意味着在转换之前将零添加到 FFT 的末尾。结果表明,这相当于“sinc 插值”,它是频率受限信号的理想插值函数。

我想该技术可以在第二次 FFT 之后使用,以准确地获得基础。但看起来信息在第 2 步中丢失了。

那是对的。相位声码器技术依赖于连续帧连接并具有特定相位关系的事实。然而,连续帧的 FFT 的对数幅度在相位方面并没有显示出相同的关系,因此在第二个 FFT 中使用这种变换是没有用的。

  • 这种方法有意义吗?可以改进吗?

是的,是的,我将在最后详细说明我对自相关的改进。

  • 我有点担心 对数方分量;似乎有一个 vDSP 函数可以做到这一点:vDSP_vdbcon 然而,没有迹象表明它预先计算了一个日志表——我认为它没有,因为 FFT 函数需要调用并传递一个显式的预计算函数进去。而这个功能没有。

我不知道 vDSP 库的细节,抱歉。

  • 是否存在拾取谐波的危险?

在您原来的相位声码器峰值拾取技术中?是的。用倒谱法?不,不是真的,重点是它考虑了所有的谐波来获得它的频率估计。例如,假设我们的频率是 1。我们的泛音是 2,3,4,5,6,7,8,9 等 我们必须去掉所有的奇次谐波,即留下 2,4,6, 8等,在基频开始与其泛音之一混淆之前将其删除。

  • 有没有什么巧妙的方法可以让 vDSP 拉出最大值,最大的优先?

不知道 vDSP,但在一般情况下,您通常只需遍历所有这些并跟踪最大的。

  • 谁能指出我对这种技术的一些研究或文献?

我在评论中给你的链接 P. 看起来不错。

此外,网站以理论和实践的方式对 DSP 主题提供了令人难以置信的深入和广泛的解释,包括各种音高提取、操作等。(是指向网站索引的更一般的链接)。我总是发现自己回到了它。有时如果你跳到它的中间可能会有点不知所措,但你总是可以按照每一个解释回到基本的构建块。

现在是自相关。基本上,该技术是这样的:您获取(窗口)信号并对其进行不同数量的时间延迟。找到与您的原始信号最匹配的数量。那是基本时期。它有很多理论意义。您正在寻找信号的重复部分。

在实践中,与所有这些时间延迟的信号副本进行相关是很慢的。它通常以这种方式实现(这在数学上是等效的):

零填充它以使其原始长度加倍。以 FFT 为例。然后用它们的平方幅度替换所有系数,除了你设置为 0 的第一个系数。现在进行 IFFT。将每个元素除以第一个元素。这为您提供了自相关。在数学上,您正在使用循环卷积定理(查找它),并使用零填充将线性卷积问题转换为循环卷积问题,这可以有效地解决。

但是,要小心选择峰值。对于非常小的延迟,信号会很好地匹配自身,因为它是连续的。(我的意思是,如果你将它延迟为零,它与自身完全相关)相反,在第一次过零之后选择最大的峰值。您可以像使用其他技术一样对自相关函数进行抛物线插值,以获得更准确的值。

这本身将为您提供所有标准的非常好的音高检测但是,您有时可能会遇到音高减半和音高加倍的问题。基本上问题在于,如果一个信号每 1 秒重复一次,那么它也每两秒重复一次。同样,如果它具有非常强的泛音,您可能会得到音高减半。因此,最大的峰可能并不总是您想要的。这个问题的一个解决方案是 Phillip McLeod 的 MPM 算法。这个想法是这样的:

与其选择最大的峰,不如选择第一个足够大的峰以供考虑。您如何确定一个峰值是否足够大以供考虑?如果它至少与 A* 一样高,则为最大峰值,其中 A 是某个常数。Phillip 建议我认为 A 的值在 0.9 左右。实际上,他编写的程序 Tartini 允许您实时比较几种不同的音高检测算法。我强烈建议下载并试用它(它实现了倒谱、直接自相关和 MPM):(如果您在构建时遇到问题,请尝试此处的说明。

我应该注意的最后一件事是关于窗口。一般来说,任何平滑的窗口都可以。汉宁窗,汉明窗等希望你应该知道如何开窗。如果您想要更准确的时间测量,我还建议您进行重叠窗口。

顺便说一句,自相关的一个很酷的特性是,如果频率通过您正在测量的窗口部分呈线性变化,它将在窗口中心为您提供正确的频率。

还有一件事:我所描述的称为有自相关函数。这是因为对于更高的时滞,原始信号和时滞版本之间的重叠变得越来越少。例如,如果您查看已延迟 N-1 个样本的大小为 N 的窗口,您会看到只有一个样本重叠。所以这个延迟的相关性显然会非常接近于零。您可以通过将自相关函数的每个值除以样本重叠数得到它来补偿这一点。这称为无偏自相关。但是,一般来说,这样做会得到更糟糕的结果,因为自相关的较高延迟值非常嘈杂,因为它们仅基于少数样本,因此减少它们的权重是有意义的。

如果您正在寻找更多信息,一如既往,谷歌是您的朋友。好的搜索词:自相关、基音检测、基音跟踪、基音提取、基音估计、倒谱等。

于 2011-08-27T00:16:59.983 回答
8

这是对用于音高确定的倒谱的简要分析。

首先让我们检查一个合成信号。

下图显示了合成稳态 E2 音符的倒谱,使用典型的近直流分量合成,基波频率为 82.4 Hz,8 个谐波为 82.4 Hz 的整数倍。合成正弦曲线被编程为生成 4096 个样本。

观察 12.36 处的显着非 DC 峰值。倒谱宽度为 1024(第二个 FFT 的输出),因此峰值对应于 1024/12.36 = 82.8 Hz,非常接近真正的基频 82.4 Hz。

合成 E2 音符的倒谱

现在让我们检查一个真实的声学信号。

下图显示了真实原声吉他 E2 音符的倒谱。信号在第一次 FFT 之前没有加窗。观察 542.9 处显着的非 DC 峰值。倒谱宽度为 32768(第二个 FFT 的输出),因此峰值对应于 32768/542.9 = 60.4 Hz,与真正的基频 82.4 Hz 相去甚远。

原声吉他 E2 音符的倒谱,未加窗

下图显示了相同真实原声吉他 E2 音符的倒谱,但这次信号在第一次 FFT 之前进行了 Hann 加窗。观察 268.46 处显着的非 DC 峰值。倒谱宽度为 32768(第二个 FFT 的输出),因此峰值对应于 32768/268.46 = 122.1 Hz,这比真正的基频 82.4 Hz 更远。

原声吉他 E2 音符的倒谱,Hann 窗口化

用于此分析的原声吉他的 E2 音符是在录音室条件下使用高质量麦克风以 44.1 KHz 采样的,它基本上包含零背景噪音,没有其他乐器或声音,也没有后处理。

这说明了在实际声学信号中使用倒谱分析来确定音高的重大挑战。

参考:

真实音频信号数据、合成信号生成、绘图、FFT 和倒谱分析在此处完成:乐器倒谱

于 2013-02-13T08:02:10.783 回答
5

您对新的技术感兴趣的现有技术有什么问题?如果这是目标,我认为倒谱不会给你更准确的音高。然而,它会帮助你处理压制的基本面。我想你可以使用倒谱让你接近,然后回到第一个 FFT(我会保持其原始形式),然后将你的狡猾技术应用于倒谱引导你到的垃圾箱。

至于二次拟合,Ted Knowlton 在这篇论文中提到了它,它最近在另一个 SO question 中提出,但我从未使用过它。

我应该补充一点,至少如 Knowlton 参考文献中所述的二次拟合技术取决于在第一个 FFT 上使用矩形窗口。正如Paul R在您的另一个问题中解释的那样,如果您正在进行音频处理,您应该在第一个 FFT 上使用 Hann 或 Hamming 窗口。所以我猜一个整体算法可能看起来像:

  • 取时域缓冲区x,做一个窗口拷贝w
  • Sx = FFT(x),Sw = FFT(w)
  • c = Log of square magnitude of Sw
  • Cx = FFT(c)
  • 估计基波(也许是谐波)使用Cx
  • 用于Sw对基波(或高次谐波)箱进行巧妙的相位技巧
  • 和/或用于Sx围绕基波(或高次谐波)进行二次箱拟合

(or higher harmonic)如果您确实有抑制的基本面,则该注释适用。

我在您的另一个问题中提到了这一点,但是是什么让您认为日志需要查找表?为什么不直接调用 log 函数呢?我想两个 FFT (O(n*logn)) 所花费的时间使你可以做的任何其他处理相形见绌。

于 2011-01-03T12:00:35.180 回答
4

倒谱分析是同态处理的一种形式,在 Oppenheim & Schafer 的“离散时间信号处理”一书中进行了解释。它曾经被认为对于从形成包络中分离激励器频率很有用(也许仍然是,不知道)。当给定相当长的固定数据窗口时,它似乎工作得更好。

但是倒谱分析并不意味着频率估计的准确性。这实际上是一种有损的分析形式。但它可能有助于从一系列谐波中找到基频,其中基频频谱分量可能相对较弱甚至缺失。

相位声码器分析(不那么狡猾,因为该技术可能已经存在了半个世纪)在给定峰值的频率估计方面更好,假设您选择了正确的峰值(不一定是最强的峰值),峰值频谱是固定的两个 fft 帧,并且基本没有完全从频谱中丢失。

如果窗口函数的变换类似于抛物线,则二次或抛物线插值可能是一个很好的选择。Sinc 插值在矩形窗口中效果更好。

于 2011-01-04T02:06:30.537 回答
3

除了 Jeremy Salwen 的帖子之外,还应阅读此答案,并回答有关文献的问题。

首先,重要的是要考虑信号的周期性。对于给定的分析窗口,信号是否更接近全周期信号。

有关术语和数学的详细说明,请参阅此处https://en.wikipedia.org/wiki/Almost_periodic_function#Quasiperiodic_signals_in_audio_and_music_synthesis

简短的回答是,如果对于给定的分析窗口,信号是完全周期性的,或者如果信号是准周期性的并且分析窗口足够小以实现周期性,那么自相关就足以完成任务。满足这些条件的信号示例如下:

  • 纯正弦音
  • 具有长延音和稳定音高(无颤音)的弦乐器,在延音部分尤其如此,但在瞬变方面则不然。
  • 吹得足够长的气管乐器。

不满足这些条件的信号示例如下:

  • 敲击声
  • 用每个音符演奏的弦乐器或气管乐器只保持很短的时间,或在很短的时间内改变
  • 复杂的音乐,或基本上以不同音高演奏的多种乐器的组合。

对于使用自相关的音高检测,有一个关于如何在 Praat 中实现的教程:

  • http://www.pinguinorodriguez.cl/blog/pitch-in-praat/ Pitch in Praat 简要说明 Praat 的音高检测算法。这描述了名为“ac”的算法。
  • www.fon.hum.uva.nl/paul/praat.html 对采样声音的基频和谐波噪声比进行准确的短期分析。保罗·博尔斯马。IFA 诉讼 17:97-110。

该论文详细描述了使用无偏自相关(Jeremy Salwen 使用的术语)进行音高检测,还表明它在音高检测方面优于有偏自相关。尽管它指出自相关结果仅在窗口大小的一半内显着,但您不需要计算后半部分。

通过使用锥形窗口对信号进行窗口化然后进行自相关来完成有偏的自相关。这减少了对音高检测有害的低频调制(缓慢时间尺度上的幅度变化)的影响,因为否则具有较大幅度的部分将给出较大的自相关系数,这将是优选的。

Boersma 论文中使用的算法可以描述为 5 个步骤:

  1. 从将要加窗的信号中移除 DC (x - x_avg)
  2. 使用锥度函数对信号进行窗口化(他认为使用 Hann 窗口或更好的高斯窗口)
  3. 自相关信号
  4. 将自相关函数除以所用窗口的自相关。
  5. 峰值拾取(类似于以前的算法)

需要注意的是,窗口的两端都将趋于零,并且窗口的自相关也将趋于零。这就是为什么无偏自相关的后半部分是无用的,它是在窗口末端附近除以零。

接下来是 YIN: - De Cheveigné、Alain 和 Hideki Kawahara。“YIN,语音和音乐的基频估计器。” 美国声学学会杂志 111.4 (2002): 1917-1930。

据我了解,YIN 论文还提供证据表明使用锥形窗口会对音高检测精度产生不利影响。有趣的是,它更喜欢不使用任何锥形窗口函数(它说明锥形窗口不会对结果带来任何改进,反而会使结果复杂化。)

最后是 Philip McLeod 的 SNAC 和 WSNAC(已由 Jeremy Salwen 链接):

  • Philip McLeod,用于音乐分析的快速、准确的音高检测工具,博士论文,奥塔哥大学计算机科学系,2008 年。
  • 麦克劳德。P,威维尔。G,“寻找音高的更聪明的方法”,Proc。国际计算机音乐会议,西班牙巴塞罗那,2005 年 9 月 5-9 日,第 138-141 页。
  • 麦克劳德。P,威维尔。G,“音乐音高的可视化”,PROC。Computer Graphics International,日本东京,2003 年 7 月 9-11 日,第 300-303 页。

它们可以在 Miracle.otago.ac.nz/tartini/papers.html 上找到

我没有深入了解它,但是提到它作为一种方法来减少与 Boersma 使用的方法不同的有偏自相关的锥形窗口的不利影响。(请注意,我没有遇到任何关于 MPM 的信息,所以我不能说什么)

最后一个建议是,如果您正在制作乐器调谐器,与自相关相比,更容易且结果更好的方法是使用具有预定频率的纯正弦信号的互相关。

杰里米·萨尔文:

也就是说,假设您绘制了函数 sin(4x)+sin(6x)+sin(8x)+sin(10x)。如果你看一下,很明显它与函数 sin(2x) 具有相同的频率。但是,如果您对该函数应用傅立叶分析,则对应于 sin(2x) 的 bin 的量级为零。因此,该信号被认为具有“缺失的基频”,因为它不包含我们认为的频率的正弦曲线。

我想争辩说,尽管给定的信号在 ω=2 处是周期性的,但它与函数 sin(2x) 具有相同的频率不同。正如傅立叶分析将表明分量 sin(2x) 的大小为零。这与信号的音高、频率和基频之间存在关系有关,但它们不同且不可互换。重要的是要记住,音高是一种主观测量,它取决于人类感知它的人。它看起来好像与 sin(2x) 具有相同的频率,这就是我们在视觉上感知它的方式。同样的效果也同样发生在音高和音频感知上。立即想到的例子是节拍,即当有两个频率接近但不同的正弦曲线时听到的感知音高。

于 2014-02-13T06:29:42.757 回答