自相关的思想是提供给定滞后下信号与其自身之间相似度的度量。有几种方法可以解决此问题,但是出于音高/速度检测的目的,您可以将其视为搜索过程。换句话说,您逐步地逐个信号地进行信号,并在参考窗口和滞后窗口之间进行关联。“滞后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的两个循环的图,然后是整个序列的循环自相关的图:
供参考,以下是相应的音频:
当然,在中间与循环点相对应的位置有一个不错的尖峰,但它来自处理相当长的一段。最重要的是,如果它不是一个精确的副本(例如,如果有仪器的话),那么尖峰将不那么干净。自相关在速度检测中绝对有用,但是对于复杂的源材料而言,自相关可能并不足够。例如,即使您发现尖峰,如何知道它是完整小节,四分音符,半音符还是其他?在这种情况下,很明显这是一个完整的衡量标准,但事实并非总是如此。我建议您在较简单的信号上使用交流电,直到内部工作情况变得清晰为止,然后再问另一个有关速度检测的问题(因为这是一个“更大”的问题)