ref: 6f6e8b39842a7d175e89f47e4d37ad5de8143ad2
dir: /tools/opus_compare.m/
%% 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