我对两个音频文件进行了FFT,并将它们的功率谱值放在单独的阵列中。
我应该如何进一步使它们相互关联并证明它们相似?有更好的方法吗?任何基本想法对我学习和应用它都将有所帮助。
#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的向量的互相关序列,其中x
和y
是长度为N
的向量(N > 1
)。如果x
和y
的长度不相同,则将较短的向量零填充到较长的向量的长度中。相关性http://www.mathworks.com/help/tool/toolbox/signal/ref/eqn1263487323。 gif
评论
$ \ begingroup $
链接似乎已断开。
$ \ endgroup $
–丹尼尔(Danijel)
17年10月3日在7:00
#5 楼
一种比较音频文件的快速简便的方法。将音频文件,复制并复制到两个立体声通道中,并排粘贴,将一个立体声轨道上的相位反转,将两个轨道对齐在缩放模式下,请确保两个文件在开始时具有相同的振幅,然后播放,如果完全静音,则两个文件都相同,如果有差异,您会清楚地听到它!
#6 楼
正如这里大多数人所写,应该使用相关性。只需考虑两个因素: br />如果有时间换算,则可以使用动态时间规整。
评论
给定两个随机信号向量的互相关。如何在MATLAB中实现反向以获得两个向量。约翰·穆赫赫