我必须对两个音频文件进行互相关以证明它们是相似的。
我对两个音频文件进行了FFT,并将它们的功率谱值放在单独的阵列中。

我应该如何进一步使它们相互关联并证明它们相似?有更好的方法吗?任何基本想法对我学习和应用它都将有所帮助。

评论

给定两个随机信号向量的互相关。如何在MATLAB中实现反向以获得两个向量。约翰·穆赫赫

#1 楼

互相关和卷积密切相关。简而言之,要对FFT进行卷积,请对输入信号进行零填充(对零进行填充)(在末尾添加零,以使至少一半的波形为“空白”)
对两个信号进行FFT
将结果相乘(逐元素相乘)
进行逆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的幂)。 :https://stackoverflow.com/a/1768140/125507

这将为您提供互相关函数,该函数用于衡量相似度与偏移量。为了获得波彼此“对齐”的偏移量,相关函数中将出现一个峰值:



峰值的x值是偏移量,可以是负数也可以是正数。

我只看到这用于查找两个波之间的偏移量。您可以通过在峰上使用抛物线/二次插值来获得更精确的偏移量估计值(优于样品的分辨率)。

要获得-1和1之间的相似度值(负值)表示一个信号随着另一个信号的增加而减小的值),您需要根据输入的长度,FFT的长度,特定的FFT实现的缩放比例等来缩放幅度。波与自身的自相关将给出您将获得最大可能匹配的值。

请注意,这仅适用于形状相同的波浪。如果它们是在不同的硬件上采样的,或者添加了一些噪声,但是仍然具有相同的形状,则此比较将起作用,但是,如果通过滤波或相移改变了波形,则听起来可能相同,但会也没有关联。

评论


$ \ begingroup $
零填充至少应为N = size(a)+ size(b)-1,最好取整为2的幂。要获得-1和1之间的值,请除以范数(a) * norm(b),它给出给定滞后时间(即模N的圆移位)在N空间中两个向量之间的夹角的余弦值。在极端滞后时,没有太多重叠的样本(在极端极端处只有一个),因此除以norm(a)* norm(b)会将这些相关偏向0(即显示它们在N空间中的相对正交性) 。
$ \ endgroup $
–太阳神
10-10-30在1:41

$ \ begingroup $
我认为说明中可能有错误。难道不应该将FFT逐项相乘就得到信号卷积的FFT,而不是互相关的FFT吗?据我了解,要获得互相关的FFT,在进行iFFT之前,有必要在逐项乘法中使用FFT矢量之一的复共轭。
$ \ endgroup $
– Dilip Sarwate
2011年11月30日20:36

$ \ begingroup $
“为什么在硬件上很难逆转时间?”在许多情况下,数据会存储在脉动阵列中,以期望计算是本地的,即,存储在第i个单元格中的$ x [i] $仅与其最近的邻居$ x [\ pm i]交互$。将$ x [i] $发送到单元#$(Ni)$,并发送$ x [Ni] $到单元#$ i $,这样做对于所有$ i $都会增加布线成本,布线延迟(从而降低了可达到的最大值时钟频率),并且由于所有导线必须彼此交叉,因此会引起布线问题。如果可能,应避免使用它,在这种情况下,这是可以避免的。
$ \ endgroup $
– Dilip Sarwate
2011年11月30日在22:05



$ \ begingroup $
@Leo按元素乘法。 n×1数组x n×1数组= n×1数组我在答案中称此为“逐样本”。
$ \ endgroup $
– Endolith
2014年1月22日20:34



$ \ begingroup $
@ Stephen305如果您使用mode ='full',他们应该做同样的事情
$ \ endgroup $
– Endolith
20-11-18在20:22

#2 楼

关联是在一个数字中表示两个时间序列(在您的情况下为音频样本)的相似性的一种方式。它是协方差的一种变体,其实现方式如下:

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系列就完成了。 (或者,如果您找到足够的相关性,则停止)当然还有更多的相关性。您必须实现标准偏差,并且必须执行一些内存管理并实现时移功能。如果所有音频样本的长度都相等,则可以不对协方差进行归一化,而是继续计算互协方差。

与您先前的问题很酷的联系:傅立叶分析只是对交叉协方差。您无需计算一个时间序列并计算与另一个信号的协方差,而可以计算一个信号与多个具有不同频率的(共)正弦波之间的协方差。都是基于相同的原理。

评论


$ \ begingroup $
您提到0是无相关性,而1是总相关性。我只想指出-1是完全负相关的。与之类似,-1表示样本1与样本2相反。如果在X,Y图上考虑它,则它是一条具有正斜率的线与一条具有负斜率的线。并且,当您接近0时,该行就会“陷落”。
$ \ endgroup $
– Kellenjb
2010-10-29 13:23

$ \ begingroup $
@kellenjb,是的,但是我可能会说一下,您可能感兴趣的相关幅度。1或-1表示信号直接相互影响。
$ \ endgroup $
– Kortuk
2010-10-29 14:52

#3 楼

在信号处理中,互相关(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个时滞的无偏估计)。

要获得最大的统计显着性,应在计算相关之前除去均值(DC偏差)。这称为交叉协方差(在MATLAB中为xcov):

x2 = x - mean(x)
y2 = y - mean(y)
phi_xy = ifft(fft(x2,N) * conj(fft(y2,N))) / (norm(x2) * norm(y2))


评论


$ \ begingroup $
这是否意味着数组的最终大小应为2 * size(a)+ size(b)-1或2 * size(b)+ size(a)-1?但无论哪种情况,两个填充数组的大小都不同。用太多的零填充的结果是什么?
$ \ endgroup $
– RobertKJ
11年11月29日在1:20

$ \ begingroup $
@RobertK互相关数组的长度至少应为a和b的长度之和(负1),如eryksun在回答中所说。为简单起见,通常将长度取为较长向量的长度的两倍(有时四舍五入到下一个较大的2元幂,以便使用高效的FFT)。当客户迟来决定他也想要较长向量的自相关时,该选择会有所帮助。填充太多零的结果之一是额外的计算,但是可以通过更高效的FFT实现加以改善。
$ \ endgroup $
– Dilip Sarwate
2011年11月30日20:54



$ \ begingroup $
@RobertKJ:您沿a滑动b,每班次输出一个,一个样本的最小重叠量。产生大小(a)的正滞后和大小(b)-1的负滞后。使用N点DFT乘积的逆变换,索引0到size(a)-1为正滞后,索引N-size(b)+1到N-1为负滞后。
$ \ endgroup $
–太阳神
2011年11月30日23:56

#4 楼

如果您使用的是Matlab,请尝试使用互相关函数:
c= xcorr(x,y)

这是Matlab文档:

xcorr估算随机过程的互相关序列。自相关是一种特殊情况。
...
c = xcorr(x,y)返回长度为2 * N-1的向量的互相关序列,其中xy是长度为N的向量(N > 1)。如果xy的长度不相同,则将较短的向量零填充到较长的向量的长度中。
相关性http://www.mathworks.com/help/tool/toolbox/signal/ref/eqn1263487323。 gif


评论


$ \ begingroup $
链接似乎已断开。
$ \ endgroup $
–丹尼尔(Danijel)
17年10月3日在7:00

#5 楼

一种比较音频文件的快速简便的方法。
将音频文件,复制并复制到两个立体声通道中,并排粘贴,将一个立体声轨道上的相位反转,将两个轨道对齐在缩放模式下,请确保两个文件在开始时具有相同的振幅,然后播放,如果完全静音,则两个文件都相同,如果有差异,您会清楚地听到它!

#6 楼

正如这里大多数人所写,应该使用相关性。

只需考虑两个因素: br />如果有时间换算,则可以使用动态时间规整。


#7 楼

找出差异的最简单方法IMO是在时域中减去两个音频信号。如果它们相等,则每个时间点的结果将为零。如果它们不相等,则它们之间的差异将在相减后保留,您可以直接收听。快速测量它们之间的相似度是该差异的RMS值。例如,这通常是在音频混合和母带制作中完成的,以收听MP3与WAV文件的差异。 (将一个信号的相位反相并相加与相减相同。这是在DAW软件中完成此操作时使用的方法。)它们必须在时间上完全对准才能起作用。如果不是,则可以开发一种算法来对齐它们,例如检测前十个峰值,计算峰值的平均偏移量和移动一个信号。您提议的信号频谱忽略了一些时域信息。例如,反向播放的音频在向前播放时将具有相同的频谱。因此,两个非常不同的音频信号可能具有完全相同的频谱。