Correct SILK encoder gain limit
authorMark Harris <mark.hsj@gmail.com>
Thu, 17 Nov 2016 04:03:25 +0000 (20:03 -0800)
committerMark Harris <mark.hsj@gmail.com>
Thu, 17 Nov 2016 04:16:23 +0000 (20:16 -0800)
Ensure that the SILK encoder's log gain is 63, not 64, when encoding
a maximum-value delta gain index of 40.  This matches the decoder
and RFC 6716 4.2.7.4, and prevents an assertion failure in the rare
case that the gain is later independently coded.

silk/gain_quant.c
tests/opus_encode_regressions.c

index 64ccd06..ee65245 100644 (file)
@@ -76,6 +76,7 @@ void silk_gains_quant(
             /* Accumulate deltas */
             if( ind[ k ] > double_step_size_threshold ) {
                 *prev_ind += silk_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold;
+                *prev_ind = silk_min_int( *prev_ind, N_LEVELS_QGAIN - 1 );
             } else {
                 *prev_ind += ind[ k ];
             }
index aad9bf5..2373884 100644 (file)
@@ -983,6 +983,42 @@ static int ec_enc_shrink_assert2(void)
     return 0;
 }
 
+static int silk_gain_assert(void)
+{
+    OpusEncoder *enc;
+    int err;
+    int data_len;
+    unsigned char data[1000];
+    static const short pcm1[160] = { 0 };
+    static const short pcm2[960] =
+    {
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        32767, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 32767
+    };
+
+    enc = opus_encoder_create(8000, 1, OPUS_APPLICATION_AUDIO, &err);
+    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(3));
+    opus_encoder_ctl(enc, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_NARROWBAND));
+    opus_encoder_ctl(enc, OPUS_SET_BITRATE(6000));
+    data_len = opus_encode(enc, pcm1, 160, data, 1000);
+    assert(data_len > 0);
+
+    opus_encoder_ctl(enc, OPUS_SET_VBR(0));
+    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(0));
+    opus_encoder_ctl(enc, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_MEDIUMBAND));
+    opus_encoder_ctl(enc, OPUS_SET_BITRATE(2867));
+    data_len = opus_encode(enc, pcm2, 960, data, 1000);
+    assert(data_len > 0);
+
+    opus_encoder_destroy(enc);
+    return 0;
+}
+
 void regression_test(void)
 {
    fprintf(stderr, "Running simple tests for bugs that have been fixed previously\n");
@@ -992,4 +1028,5 @@ void regression_test(void)
    surround_analysis_uninit();
    ec_enc_shrink_assert();
    ec_enc_shrink_assert2();
+   silk_gain_assert();
 }