80 lines
1.9 KiB
Matlab
80 lines
1.9 KiB
Matlab
%% Tests bit-stream compliance for the Opus codec
|
|
%% x: Signal from the Opus reference implementation (float or fixed)
|
|
%% y: Signal from the decoder under test
|
|
%% stereo: 0 for mono, 1 for stereo
|
|
function [err, NMR] = opus_compare(x, y, stereo)
|
|
|
|
% Bands on which we compute the pseudo-NMR (Bark-derived CELT bands)
|
|
b = 2*[0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100];
|
|
d = diff(b);
|
|
|
|
% Per-band SNR threshold
|
|
T = 50-.7*[1:21];
|
|
|
|
% Noise floor
|
|
N = 10 .^ ((10-0.6*[1:21])/10);
|
|
|
|
% Error signal
|
|
e=x-y;
|
|
|
|
%Add a +/- 1 dead zone on the error
|
|
e = e - min(1, max(-1, e));
|
|
|
|
% Compute spectrum of original and error
|
|
if (stereo)
|
|
X=(abs(specgram(x(1:2:end),480))+abs(specgram(x(2:2:end),480)))/2;
|
|
E=(abs(specgram(e(1:2:end),480))+abs(specgram(e(2:2:end),480)))/2;
|
|
else
|
|
X=abs(specgram(x,480));
|
|
E=abs(specgram(e,480));
|
|
endif
|
|
|
|
% Group energy per band
|
|
for k=1:21
|
|
Xb(k,:) = sum(X(b(k)+1:b(k+1),:).^2)/d(k)+1;
|
|
Eb(k,:) = sum(E(b(k)+1:b(k+1),:).^2)/d(k)+1;
|
|
end
|
|
|
|
% Frequency masking (low to high) with 10 dB/Bark slope
|
|
Xb = filter(1, [1, -.1], Xb);
|
|
% Frequency masking (high to low) with 15 dB/Bark slope
|
|
Xb(end:-1:1,:) = filter(1, [1, -.03], Xb(end:-1:1,:));
|
|
|
|
% Temporal masking with 5 dB/5 ms slope
|
|
Xb = filter(1, [1, -.3], Xb')';
|
|
|
|
% NMR threshold
|
|
T0 = ones(length(Eb), 1)*(10.^((T)/10));
|
|
|
|
% Time-frequency SNR
|
|
NMR = (Xb./Eb)';
|
|
|
|
%Picking only errors in the 90th percentile
|
|
tmp = Eb(:);
|
|
thresh = sort(tmp)(round(.90*length(tmp)));
|
|
weight = Eb'>thresh;
|
|
|
|
printf("Average pseudo-NMR: %3.2f dB\n", mean(mean(10*log10(NMR))));
|
|
|
|
if (sum(sum(weight))<1)
|
|
printf("Mismatch level: below noise floor\n");
|
|
err = -100;
|
|
else
|
|
M = (T0./NMR) .* weight;
|
|
|
|
err = 10*log10(sum(sum(M)) / sum(sum(weight)));
|
|
|
|
printf("Weighted mismatch: %3.2f dB\n", err);
|
|
endif
|
|
|
|
printf("\n");
|
|
|
|
if (err < 0)
|
|
printf("**Decoder PASSES test (mismatch < 0 dB)\n");
|
|
else
|
|
printf("**Decoder FAILS test (mismatch >= 0 dB)\n");
|
|
endif
|
|
|
|
|
|
|