diff options
-rwxr-xr-x | doc/build_draft.sh | 7 | ||||
-rw-r--r-- | doc/draft-ietf-codec-opus.xml | 38 | ||||
-rw-r--r-- | doc/opus_compare.m | 79 |
3 files changed, 121 insertions, 3 deletions
diff --git a/doc/build_draft.sh b/doc/build_draft.sh index 2f2878e0..0508408f 100755 --- a/doc/build_draft.sh +++ b/doc/build_draft.sh @@ -17,4 +17,11 @@ tar czvf opus_source.tar.gz opus_source cat opus_source.tar.gz| base64 -w 66 | sed 's/^/###/' > doc/opus_source.base64 cd doc +echo '<figure>' > opus_compare_escaped.m +echo '<artwork>' >> opus_compare_escaped.m +echo '<![CDATA[' >> opus_compare_escaped.m +cat opus_compare.m >> opus_compare_escaped.m +echo ']]>' >> opus_compare_escaped.m +echo '</artwork>' >> opus_compare_escaped.m +echo '</figure>' >> opus_compare_escaped.m xml2rfc draft-ietf-codec-opus.xml diff --git a/doc/draft-ietf-codec-opus.xml b/doc/draft-ietf-codec-opus.xml index 2c767e08..4e2a808e 100644 --- a/doc/draft-ietf-codec-opus.xml +++ b/doc/draft-ietf-codec-opus.xml @@ -1226,7 +1226,7 @@ Each CELT frame can be encoded in a different number of octets, making it possib </section> -<section title="Codec Decoder"> +<section title="Opus Decoder"> <t> Opus decoder block diagram. </t> @@ -1556,6 +1556,26 @@ in celt_decode_lost() (mdct.c). </section> +<section title="Conformance"> + +<t> +It is the intention to allow the greatest possible choice of freedom in +implementing the specification. For this reason, outside of a few exceptions +noted in this section, conformance is defined through the reference +implementation of the decoder provided in Appendix <xref target="ref-implementation"></xref>. +Although this document includes an English description of the codec, should +the description contradict the source code of the reference implementation, +the latter shall take precedence. +</t> + +<t> +Compliance with this specification means that a decoder's output MUST be +<spanx style="emph">close enough</spanx> to the output of the reference +implementation. This is measured using the opus_compare.m tool provided in +Appendix <xref target="opus-compare"></xref>. +</t> +</section> + <section anchor="security" title="Security Considerations"> <t> @@ -1569,8 +1589,14 @@ audio stream must not cause the encoder to misbehave because this would allow an attacker to attack transcoding gateways. </t> <t> -In its current version, the Opus codec likely does NOT meet these -security considerations, so it should be used with caution. +The reference implementation contains no known buffer overflow or cases where +a specially crafter packet or audio segment could cause a significant increase +in CPU load. However, on certain CPU architectures where denormalized +floating-point operations result and handled through exceptions, it is possible +for some audio content (e.g. silence or near-silence) to cause such an increase +in CPU load. For such architectures, it is RECOMMENDED to add very small +floating-point offsets to prevent significant numbers of denormalized +operations. No such issue exists for the fixed-point reference implementation. </t> </section> @@ -1790,6 +1816,12 @@ tar xzvf opus_source.tar.gz </section> +<section anchor="opus-compare" title="opus_compare.m"> +<t> +<?rfc include="opus_compare_escaped.m"?> +</t> +</section> + </back> </rfc> diff --git a/doc/opus_compare.m b/doc/opus_compare.m new file mode 100644 index 00000000..72739aaf --- /dev/null +++ b/doc/opus_compare.m @@ -0,0 +1,79 @@ +%% 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 + + + |