我正在使用matlab开展一个项目,我必须比较两个(高阶)Ambisonics脉冲响应。我计算了FFT并绘制了两个信号在频率上的平滑能量:
它们似乎是相关的,但我想找到一个估算相似性的值。我无法使用xcorr
函数,因为我的信号是N
x25而不是N
x1。
假设a
和b
是我的信号,两者都是8000x25矩阵:
fs = 48e3;
fft1 = fft(a);
fft2 = fft(b);
l1 = length(a);
l2 = length(b);
% calculating frequencies
f = fs*(0:(l1/2))/l1;
% calculating single sided spectrum for both signals
P1 = 10*log10(abs(fft1).^2);
P1 = P1(1:l1/2+1);
P1(2:end-1) = 2*P1(2:end-1);
P2 = 10*log10(abs(fft2).^2);
P2 = P2(1:l2/2+1);
P2(2:end-1) = 2*P2(2:end-1);
% plotting both spectra
figure; plot(f,smooth(P1,150)); hold on; plot(f,smooth(P2,150)); grid on
所以每次我有25个值(让我们说每个值代表我信号的一个通道)。所以xcorr
允许我将一个频道与另一个频道进行比较。我需要做的是将信号作为整个实体进行比较,因为每个通道都有对信号很重要的空间信息。因此,将一个频道与另一个频道进行比较不会让我得到关于相似性的确切陈述。
感谢您提供有关如何比较这些信号的帮助和建议。
答案 0 :(得分:1)
有很多方法可以比较信号。让我们首先区分两个主要选项:(1)信号应该在每个时间点进行比较,不要移位,或者(2)信号应该以时间不变的方式进行比较,允许信号相对于另一个进行比较
案例(2)通常归结为互相关函数,例如由xcorr
计算。该函数的最大值表示在最大化相关性的时移下的相关性。也就是说,我们及时移动一个信号以找到与另一个信号最大相关的位置,然后量化该相关性。它可以按如下方式计算:
sim = max(ifft(fft(a).*conj(fft(b))));
以上独立计算a
和b
的每个频道的相关性,为每个频道生成一个值。由于您要将a
的所有频道与b
的所有频道进行比较,因此您需要设置矩阵。一种简单的方法是在MATLAB中使用新的隐式单例扩展:
b = reshape(b,[],1,25);
sim = max(ifft(fft(a).*conj(fft(b))));
sim = squeeze(sim);
以上产生25x25的相关矩阵。如果你得到一个计算它的错误,你可能有一个旧版本的MATLAB。这个更丑陋的代码做同样的事情:
b = reshape(b,[],1,25);
sim = max(ifft(bsxfun(@times,fft(a),conj(fft(b)))));
sim = squeeze(sim);
案例(1)更有趣,因为除了相关性之外还有更多选项:(根)均方误差,平均绝对误差,rank correlation,mutual information, total correlation,以及一长串的etceteras。其中一些是微不足道的计算,一些更复杂。但即使是最复杂的一个,您可以使用两个for
循环计算所有通道组合:
sim = zeros(25,25);
for ii = 1:25
for jj = 1:25
sim(ii,jj) = similarity_function(a(:,ii),b(:,jj)); % whatever you want to fill in here!
end
end
这在很大程度上取决于信号的特性,哪种测量最有用。如果你对像均方根误差这样简单的东西感兴趣,可以使用隐式单例扩展再次计算每一对:
b = reshape(b,[],1,25);
sim = sqrt(mean((a-b).^2));
sim = squeeze(sim);
最后,我们需要将成对通道比较的25x25矩阵缩减为单个度量。同样,有不同的选择。一种可能性是简单地查看两个最相似的通道,或两个最不相似的通道:
max(sim(:))
min(sim(:))
或者我们可以采取一些与所有组合相关的统计数据:
mean(sim(:))
median(sim(:))
sum(sim(:))
sqrt(mean(sim(:).^2));
另一种选择是找到b
中与a
中每个频道最匹配的频道:
sim = min(sim,[],2);
这将为a
的每个频道返回一个值。同样,您可以采用最大值或最小值,或计算前面讨论的任何其他统计量。