Answers:
互相关和卷积密切相关。简而言之,要对FFT 进行卷积,您需要
conv(a, b) = ifft(fft(a_and_zeros) * fft(b_and_zeros))
您需要进行零填充,因为FFT方法实际上是圆形互相关的,这意味着信号在两端回绕。因此,您添加足够的零以消除重叠,以模拟从零到无穷大的信号。
为了获得互相关而不是卷积,您需要在执行FFT之前对其中一个信号进行时间反转,或者对FFT之后的其中一个信号进行复共轭:
corr(a, b) = ifft(fft(a_and_zeros) * fft(b_and_zeros[reversed]))
corr(a, b) = ifft(fft(a_and_zeros) * conj(fft(b_and_zeros)))
使用您的硬件/软件比较容易。对于自相关(信号与自身之间的互相关),最好进行复共轭,因为这样一来,您只需计算一次FFT。
如果信号是真实的,则可以使用真实的FFT(RFFT / IRFFT),并且仅计算一半频谱即可节省一半的计算时间。
另外,您还可以通过填充较大的大小来节省计算时间,以优化FFT的大小(例如,对于FFTPACK 为5平滑数,对于FFTW为13平滑数,或者对于简单的硬件实现为2的幂)。
这是Python中与蛮力相关相比的FFT相关示例:https : //stackoverflow.com/a/1768140/125507
这将为您提供互相关函数,该函数用于衡量相似度与偏移量。为了获得波彼此“对齐”的偏移量,相关函数中将出现一个峰值:
峰值的x值是偏移量,可以是负值或正值。
我只看到这用于查找两个波之间的偏移。通过在峰上使用抛物线/二次插值,您可以得到更精确的偏移量估算值(优于样品的分辨率)。
要获得介于-1和1之间的相似度值(负值表示其中一个信号随着另一个信号的增加而减小),您需要根据输入的长度,FFT的长度,特定的FFT实现方式来缩放幅度。波形与其自身的自相关将为您提供最大可能匹配的值。
请注意,这仅适用于具有相同形状的波浪。如果它们是在不同的硬件上采样的,或者添加了一些噪声,但仍然具有相同的形状,则此比较将起作用,但是,如果波形已通过滤波或相移进行了更改,则它们听起来可能相同,但会获胜也没有关联。
关联是在一个数字中表示两个时间序列(在您的情况下为音频样本)的相似性的一种方式。它是协方差的一种适应,其实现方式如下:
period = 1/sampleFrequency;
covariance=0;
for (iSample = 0; iSample<nSamples; iSample++)
covariance += (timeSeries_1(iSample)*timeSeries_2(iSample))/period;
//Dividing by `period` might not even be necessary
相关性是协方差的归一化版本,即协方差除以两个时间序列的标准偏差的乘积。当没有相关性时(完全不相似),相关性将产生0;对于整体相关性(完全相似),相关性将产生1。
您可以想象两个声音样本可能相似但不同步。这就是交叉相关性的来源。您可以计算时间序列之间的相关性,在这些时间序列中,其中一个偏移一个样本:
for (iShift=0; iShift<nSamples; iShift++)
xcorr(iShift) = corr(timeSeries_1, timeSeries_2_shifted_one_sample);
然后找出corr
系列中的最大值,就可以完成。(或者,如果您发现足够的相关性,则停止)当然还有更多的相关性。您必须实现标准偏差,并且必须执行一些内存管理并实现时移功能。如果所有音频样本的长度都相等,则可能不对协方差进行归一化而继续计算交叉协方差。
与您先前的问题有一个很酷的联系:傅立叶分析只是交叉协方差的一种适应。无需移动一个时间序列并计算与另一个信号的协方差,而是计算一个信号与多个具有不同频率的(共)正弦波之间的协方差。这都是基于相同的原理。
在信号处理中,互相关(MATLAB中的xcorr)是一种卷积运算,其中两个序列之一相反。由于时间反转对应于频域中的复杂共轭,因此可以使用DFT如下计算互相关:
R_xy = ifft(fft(x,N) * conj(fft(y,N)))
其中N = size(x)+ size(y)-1(最好取整为2的幂)是DFT的长度。
DFT的乘法等效于时间上的循环卷积。对两个向量进行零填充至长度N可以防止y的循环移位分量与x重叠,这使得结果与x的线性卷积和y的时间倒置相同。
滞后1是y的右循环,而滞后-1是左循环。互相关只是所有滞后的点积序列。基于标准的fft排序,它们将位于可以按以下方式访问的数组中。索引0到size(x)-1为正滞后。索引N-size(y)+1到N-1是相反顺序的负延迟。(在Python中,可以使用R_xy [-1]之类的负索引方便地访问负滞后。)
您可以将零填充的x和y视为N维向量。对于给定的滞后,x和y的点积为|x|*|y|*cos(theta)
。x和y的范数对于圆形移位是恒定的,因此将它们除以仅留下角度theta的变化余弦。如果x和y(对于给定的滞后)在N空间中正交,则相关性为0(即theta = 90度)。如果它们是共线性的,则该值为1(正相关)或-1(负相关,即theta = 180度)。这导致归一化为互相关的互相关:
R_xy = ifft(fft(x,N) * conj(fft(y,N))) / (norm(x) * norm(y))
可以通过重新计算仅重叠部分的范数来实现无偏,但是您也可以在时域中进行整个计算。此外,您还将看到标准化的不同版本。有时,互相关不是通过归一化为统一的,而是通过M(有偏)进行归一化的,其中M = max(size(x),size(y))或M- | m |。(第m个时滞的无偏估计)。
为了获得最大的统计显着性,应在计算相关性之前去除均值(直流偏置)。这称为交叉协方差(MATLAB中的xcov):
x2 = x - mean(x)
y2 = y - mean(y)
phi_xy = ifft(fft(x2,N) * conj(fft(y2,N))) / (norm(x2) * norm(y2))
2*size (a) + size(b) - 1
或2*size (b) + size (a) - 1
?但是无论哪种情况,两个填充数组的大小都不同。用太多的零填充的结果是什么?
b
沿着滑动a
,每个班次一个输出,一个样本的最小重叠。产生size(a)
正向滞后和size(b) - 1
负向滞后。使用N点DFT乘积的逆变换,索引0
through size(a)-1
为正滞后,索引N-size(b)+1
through N-1
为负滞后。
如果您使用的是Matlab,请尝试使用互相关函数:
c= xcorr(x,y)
xcorr
估计随机过程的互相关序列。自相关被作为特殊情况处理。...
c = xcorr(x,y)
返回长度为2 * N-1的向量中的互相关序列,其中x
和y
是长度N
向量(N > 1
)。如果x
和y
的长度不同,则将较短的向量零填充到较长向量的长度上。相关性http://www.mathworks.com/help/toolbox/signal/ref/eqn1263487323.gif
找出差异的最简单方法是IMO,即在时域中减去两个音频信号。如果它们相等,则每个时间点的结果将为零。如果它们不相等,则它们之间的差异将在相减后保留,您可以直接收听。快速测量它们之间的相似度是该差异的RMS值。例如,这通常是在音频混合和母带制作中完成的,以收听MP3与WAV文件的差异。(将一个信号的相位反相并相加与相减相同。这是在DAW软件中完成此操作时所使用的方法。)它们必须在时间上完全对准才能起作用。如果不是,则可以开发一种算法来对齐它们,例如检测前十个峰,计算峰的平均偏移量以及移动一个信号。
像您建议的那样,转换到频域并比较信号的功率谱会忽略一些时域信息。例如,反向播放的音频在向前播放时将具有相同的频谱。因此,两个截然不同的音频信号可能具有完全相同的频谱。