自相关的想法是在给定的滞后处提供信号与其自身之间的相似性度量。有几种方法可以接近它,但出于音高/速度检测的目的,您可以将其视为搜索过程。换句话说,您逐个采样地检查信号,并在您的参考窗口和滞后窗口之间执行相关性。“滞后 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 的两个循环的图,然后是整个序列的循环自相关图:
作为参考,这是相应的音频:
果然,在对应于循环点的中间有一个很好的尖峰,但它来自处理相当长的段。最重要的是,如果它不是一个精确的副本(例如,如果有仪器),那个尖峰就不会那么干净了。自相关在速度检测中肯定会很有用,但它本身可能不足以用于复杂的源材料。例如,即使你找到了一个尖峰,你怎么知道它是一个完整的小节,还是四分音符、二分音符或其他什么?在这种情况下,很明显这是一个完整的措施,但情况并非总是如此。我建议在更简单的信号上使用交流电,直到内部工作原理变得清晰,然后再问另一个关于速度检测的问题(因为它“更大”