高阶 Ambisonics 信号的比较

Comparison of Higher Order Ambisonics Signals

我正在使用 matlab 进行一个项目,我必须比较两个(高阶)Ambisonics 脉冲响应。我计算了 FFT 并绘制了两个信号随频率的平滑能量:

它们似乎是相关的,但我想找到一个值来估计相似度。我不能使用函数 xcorr 因为我的信号是 Nx25 而不是 Nx1.

假设ab是我的信号,都是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 将允许我将一个频道与另一个频道进行比较。我需要做的是将信号作为一个整体进行比较,因为每个通道都有对信号很重要的空间信息。因此,将一个频道与另一个频道进行比较不会让我得出关于相似性的确切陈述。

非常感谢您就如何比较这些信号提供帮助和建议。

比较信号的方法有很多种。让我们首先区分两个主要选项:(1)应该在每个时间点比较信号,不移动,或者(2)应该以 time-invariant 方式比较信号,允许相对于另一个。


案例 (2) 通常归结为 cross-correlation 函数,例如由 xcorr 计算得出。该函数的最大值表示在使相关性最大化的时移下的相关性。也就是说,我们及时移动一个信号以找到它与另一个信号最大相关的位置,然后量化该相关性。可以这样计算:

sim = max(ifft(fft(a).*conj(fft(b))));

以上计算了ab每个通道独立的相关性,为每个通道产生一个值。由于要比较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,以及一长串等等。其中一些计算起来微不足道,有些则更复杂。但即使是最复杂的一个,您也可以使用两个 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);

returns a 的每个通道的值。同样,您可以取最大值或最小值,或计算前面讨论的任何其他统计数据。