1%% Tests bit-stream compliance for the Opus codec
2%% x: Signal from the Opus reference implementation (float or fixed)
3%% y: Signal from the decoder under test
4%% stereo: 0 for mono, 1 for stereo
5function [err, NMR] = opus_compare(x, y, stereo)
6
7% Bands on which we compute the pseudo-NMR (Bark-derived CELT bands)
8b = 2*[0,  1,  2,  3,  4,  5,  6,  7,  8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100];
9d = diff(b);
10
11% Per-band SNR threshold
12T = 50-.7*[1:21];
13
14% Noise floor
15N = 10 .^ ((10-0.6*[1:21])/10);
16
17% Error signal
18e=x-y;
19
20%Add a +/- 1 dead zone on the error
21e = e - min(1, max(-1, e));
22
23% Compute spectrum of original and error
24if (stereo)
25  X=(abs(specgram(x(1:2:end),480))+abs(specgram(x(2:2:end),480)))/2;
26  E=(abs(specgram(e(1:2:end),480))+abs(specgram(e(2:2:end),480)))/2;
27else
28  X=abs(specgram(x,480));
29  E=abs(specgram(e,480));
30endif
31
32% Group energy per band
33for k=1:21
34   Xb(k,:) = sum(X(b(k)+1:b(k+1),:).^2)/d(k)+1;
35   Eb(k,:) = sum(E(b(k)+1:b(k+1),:).^2)/d(k)+1;
36end
37
38% Frequency masking (low to high) with 10 dB/Bark slope
39Xb = filter(1, [1, -.1], Xb);
40% Frequency masking (high to low) with 15 dB/Bark slope
41Xb(end:-1:1,:) = filter(1, [1, -.03], Xb(end:-1:1,:));
42
43% Temporal masking with 5 dB/5 ms slope
44Xb = filter(1, [1, -.3], Xb')';
45
46% NMR threshold
47T0 = ones(length(Eb), 1)*(10.^((T)/10));
48
49% Time-frequency SNR
50NMR = (Xb./Eb)';
51
52%Picking only errors in the 90th percentile
53tmp = Eb(:);
54thresh = sort(tmp)(round(.90*length(tmp)));
55weight = Eb'>thresh;
56
57printf("Average pseudo-NMR: %3.2f dB\n", mean(mean(10*log10(NMR))));
58
59if (sum(sum(weight))<1)
60   printf("Mismatch level: below noise floor\n");
61   err = -100;
62else
63   M = (T0./NMR) .* weight;
64
65   err = 10*log10(sum(sum(M)) / sum(sum(weight)));
66
67   printf("Weighted mismatch: %3.2f dB\n", err);
68endif
69
70printf("\n");
71
72if (err < 0)
73   printf("**Decoder PASSES test (mismatch < 0 dB)\n");
74else
75   printf("**Decoder FAILS test (mismatch >= 0 dB)\n");
76endif
77
78
79
80