opus_compare.m 1.9 KB

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