音频分析中的自相关

信息处理 算法 声音的 自相关
2022-01-09 06:20:28

我正在阅读Autocorrelation,但我不确定我是否完全理解它是如何工作的以及我应该期待什么输出。我是否认为我应该将信号输入到 AC 功能并具有滑动窗口输入。每个窗口(例如 1024 个样本)将输出一个介于 -1 和 1 之间的系数。该符号仅说明该线是向上还是向下,该值表示相关性有多强。为简单起见,假设我没有重叠,每次只移动窗口 1024 个样本。在 44100 的样本中,我会得到 43 个系数吗?我需要保留所有这些系数吗?

假设我对 200 秒的信号执行此操作,得到 8600 个系数。我将如何使用这些系数来检测重复,进而检测速度?我应该创建某种神经网络来对它们进行分组,还是那是矫枉过正?

谢谢你的帮助。

3个回答

自相关的想法是在给定的滞后处提供信号与其自身之间的相似性度量。有几种方法可以接近它,但出于音高/速度检测的目的,您可以将其视为搜索过程。换句话说,您逐个采样地检查信号,并在您的参考窗口和滞后窗口之间执行相关性。“滞后 0”处的相关性将是全局最大值,因为您将引用与自身的逐字副本进行比较。随着您向前迈进,相关性必然会降低,但在周期性信号的情况下,它会在某个时刻再次开始增加,然后达到局部最大值。“滞后 0”和第一个峰值之间的距离可以让您估计音高/速度。我的方式

在高采样率下计算逐个样本的相关性可能在计算上非常昂贵,因此通常使用基于 FFT 的方法。取感兴趣部分的 FFT,乘以它的复共轭,然后取逆 FFT 将得到循环自相关在代码中(使用numpy):

freqs = numpy.fft.rfft(signal)
autocorr = numpy.fft.irfft(freqs * numpy.conj(freqs))

其效果将是相对于周期性分量(根据定义与自身相似)减少信号中的噪声量(与自身不相关)。在进行逆变换之前重复自相关(即共轭乘法)将进一步降低噪声。考虑一个混合了白噪声的正弦波的例子。下图显示了 440hz 正弦波、被噪声“破坏”的同一正弦波、噪声波的循环自相关和双循环自相关:

自相关

请注意,两个自相关信号的第一个峰值如何恰好位于原始信号的第一个周期的末端。那是您正在寻找的峰值以确定周期性(在这种情况下为音高)。第一个自相关信号仍然有点“摇摆不定”,因此为了进行峰值检测,需要进行某种平滑处理。在频域中进行两次自相关可以完成同样的事情(并且相对较快)。请注意,“摆动”是指放大时信号的外观,而不是图中心出现的下降。循环自相关的后半部分永远是前半部分的镜像,所以这种“下降”是典型的。只是为了清楚算法,下面是代码的样子:

freqs = numpy.fft.rfft(signal)
auto1 = freqs * numpy.conj(freqs)
auto2 = auto1 * numpy.conj(auto1)
result = numpy.fft.irfft(auto2)

您是否需要进行不止一种自相关取决于信号中的噪声量。

当然,这个想法有很多微妙的变化,我不打算在这里全部讨论。我见过的最全面的报道(在音高检测的背景下)是Rabiner 和 Schafer在语音信号的数字处理中。


现在,关于自相关是否足以进行速度检测。答案是肯定的和否定的。您可以获得一些速度信息(取决于源信号),但在所有情况下可能很难理解它的含义。例如,这是一个 breakbeat 的两个循环的图,然后是整个序列的循环自相关图:

断拍自相关

作为参考,这是相应的音频:

果然,在对应于循环点的中间有一个很好的尖峰,但它来自处理相当长的段。最重要的是,如果它不是一个精确的副本(例如,如果有仪器),那个尖峰就不会那么干净了。自相关在速度检测中肯定会很有用,但它本身可能不足以用于复杂的源材料。例如,即使你找到了一个尖峰,你怎么知道它是一个完整的小节,还是四分音符、二分音符或其他什么?在这种情况下,很明显这是一个完整的措施,但情况并非总是如此。我建议在更简单的信号上使用交流电,直到内部工作原理变得清晰,然后再问另一个关于速度检测的问题(因为它“更大”

听起来您想使用自相关来进行节拍检测。您可以这样做,但我建议您对音频进行大量下采样。您正在寻找 1 到 3 Hz(60 bpm 到 180 bpm)之间的信号,因此您不需要或想要 44100 Hz 分辨率。正确计算和归一化的自相关在滞后 0 处为 1.0(信号与自身完全相关)。对于周期性信号,ac 下降到零以下,然后在对应于基频的滞后处回到峰值,在谐波处具有较小的峰值。您必须选择一个合理的范围来搜索该峰。对于噪声,自相关下降并且基本上在零附近的曲线中呈扁平状。根据经验,如果标准化交流中的峰值 > 0.5,则表示有周期性信号。

自相关只是信号与其自身的互相关。计算它的一种简单方法是在原始信号和信号的时间翻转版本之间进行卷积。如果您的信号长度为 1000 个样本,则其自相关具有 1999 (2*N-1) 个非零样本。这些样本中只有 1000 个是唯一的,因为自相关(对于真实信号)总是在时间上对称,即 ac[n] = ac[-n]。

需要将连续信号分解为有限段。这类似于傅立叶变换:从技术上讲,您需要从 -inf 集成到 +inf,但将其分解为段(根据需要进行重叠和/或加窗)也会产生有用的结果。窗口长度、形状和重叠的选择取决于应用。