Improving rate control for low bitrate
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Thu, 17 May 2018 00:05:47 +0000 (20:05 -0400)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Thu, 17 May 2018 21:09:28 +0000 (17:09 -0400)
Using a finer table for the rate to SNR curves in silk_control_SNR().
It's now possible to have an SNR that reaches 0, so we can lower bitrate
down to ~5 kbps for narrowband and 5.5 kbps for wideband.

silk/control_SNR.c
silk/define.h
silk/tables.h
silk/tables_other.c

index 464c1ac..9a6db27 100644 (file)
@@ -32,44 +32,82 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "main.h"
 #include "tuning_parameters.h"
 
+/* These tables hold SNR values divided by 21 (so they fit in 8 bits)
+   for different target bitrates spaced at 400 bps interval. The first
+   10 values are omitted (0-4 kb/s) because they're all zeros.
+   These tables were obtained by running different SNRs through the
+   encoder and measuring the active bitrate. */
+static const unsigned char silk_TargetRate_NB_21[117 - 10] = {
+                                              0, 15, 39, 52, 61, 68,
+     74, 79, 84, 88, 92, 95, 99,102,105,108,111,114,117,119,122,124,
+    126,129,131,133,135,137,139,142,143,145,147,149,151,153,155,157,
+    158,160,162,163,165,167,168,170,171,173,174,176,177,179,180,182,
+    183,185,186,187,189,190,192,193,194,196,197,199,200,201,203,204,
+    205,207,208,209,211,212,213,215,216,217,219,220,221,223,224,225,
+    227,228,230,231,232,234,235,236,238,239,241,242,243,245,246,248,
+    249,250,252,253,255
+};
+
+static const unsigned char silk_TargetRate_MB_21[165 - 10] = {
+                                              0,  0, 28, 43, 52, 59,
+     65, 70, 74, 78, 81, 85, 87, 90, 93, 95, 98,100,102,105,107,109,
+    111,113,115,116,118,120,122,123,125,127,128,130,131,133,134,136,
+    137,138,140,141,143,144,145,147,148,149,151,152,153,154,156,157,
+    158,159,160,162,163,164,165,166,167,168,169,171,172,173,174,175,
+    176,177,178,179,180,181,182,183,184,185,186,187,188,188,189,190,
+    191,192,193,194,195,196,197,198,199,200,201,202,203,203,204,205,
+    206,207,208,209,210,211,212,213,214,214,215,216,217,218,219,220,
+    221,222,223,224,224,225,226,227,228,229,230,231,232,233,234,235,
+    236,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,
+    251,252,253,254,255
+};
+
+static const unsigned char silk_TargetRate_WB_21[201 - 10] = {
+                                              0,  0,  0,  8, 29, 41,
+     49, 56, 62, 66, 70, 74, 77, 80, 83, 86, 88, 91, 93, 95, 97, 99,
+    101,103,105,107,108,110,112,113,115,116,118,119,121,122,123,125,
+    126,127,129,130,131,132,134,135,136,137,138,140,141,142,143,144,
+    145,146,147,148,149,150,151,152,153,154,156,157,158,159,159,160,
+    161,162,163,164,165,166,167,168,169,170,171,171,172,173,174,175,
+    176,177,177,178,179,180,181,181,182,183,184,185,185,186,187,188,
+    189,189,190,191,192,192,193,194,195,195,196,197,198,198,199,200,
+    200,201,202,203,203,204,205,206,206,207,208,209,209,210,211,211,
+    212,213,214,214,215,216,216,217,218,219,219,220,221,221,222,223,
+    224,224,225,226,226,227,228,229,229,230,231,232,232,233,234,234,
+    235,236,237,237,238,239,240,240,241,242,243,243,244,245,246,246,
+    247,248,249,249,250,251,252,253,255
+};
+
 /* Control SNR of redidual quantizer */
 opus_int silk_control_SNR(
     silk_encoder_state          *psEncC,                        /* I/O  Pointer to Silk encoder state               */
     opus_int32                  TargetRate_bps                  /* I    Target max bitrate (bps)                    */
 )
 {
-    opus_int k, ret = SILK_NO_ERROR;
-    opus_int32 frac_Q6;
-    const opus_int32 *rateTable;
-
-    /* Set bitrate/coding quality */
-    TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
-    if( TargetRate_bps != psEncC->TargetRate_bps ) {
-        psEncC->TargetRate_bps = TargetRate_bps;
-
-        /* If new TargetRate_bps, translate to SNR_dB value */
-        if( psEncC->fs_kHz == 8 ) {
-            rateTable = silk_TargetRate_table_NB;
-        } else if( psEncC->fs_kHz == 12 ) {
-            rateTable = silk_TargetRate_table_MB;
-        } else {
-            rateTable = silk_TargetRate_table_WB;
-        }
+    int id;
+    int bound;
+    const unsigned char *snr_table;
 
-        /* Reduce bitrate for 10 ms modes in these calculations */
-        if( psEncC->nb_subfr == 2 ) {
-            TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;
-        }
-
-        /* Find bitrate interval in table and interpolate */
-        for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {
-            if( TargetRate_bps <= rateTable[ k ] ) {
-                frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), rateTable[ k ] - rateTable[ k - 1 ] );
-                psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] );
-                break;
-            }
-        }
+    psEncC->TargetRate_bps = TargetRate_bps;
+    if( psEncC->nb_subfr == 2 ) {
+        TargetRate_bps -= 2000 + psEncC->fs_kHz/16;
     }
-
-    return ret;
+    if( psEncC->fs_kHz == 8 ) {
+        bound = sizeof(silk_TargetRate_NB_21);
+        snr_table = silk_TargetRate_NB_21;
+    } else if( psEncC->fs_kHz == 12 ) {
+        bound = sizeof(silk_TargetRate_MB_21);
+        snr_table = silk_TargetRate_MB_21;
+    } else {
+        bound = sizeof(silk_TargetRate_WB_21);
+        snr_table = silk_TargetRate_WB_21;
+    }
+    id = (TargetRate_bps+200)/400;
+    id = silk_min(id - 10, bound-1);
+    if( id <= 0 ) {
+        psEncC->SNR_dB_Q7 = 0;
+    } else {
+        psEncC->SNR_dB_Q7 = snr_table[id]*21;
+    }
+    return SILK_NO_ERROR;
 }
index 22fd720..247cb0b 100644 (file)
@@ -46,7 +46,6 @@ extern "C"
 /* Limits on bitrate */
 #define MIN_TARGET_RATE_BPS                     5000
 #define MAX_TARGET_RATE_BPS                     80000
-#define TARGET_RATE_TAB_SZ                      8
 
 /* LBRR thresholds */
 #define LBRR_NB_MIN_RATE_BPS                    12000
index 8b0380e..95230c4 100644 (file)
@@ -97,12 +97,6 @@ extern const opus_uint8  silk_NLSF_interpolation_factor_iCDF[ 5 ];
 extern const silk_NLSF_CB_struct silk_NLSF_CB_WB;                                                   /* 1040 */
 extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB;                                                /* 728 */
 
-/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */
-extern const opus_int32  silk_TargetRate_table_NB[  TARGET_RATE_TAB_SZ ];                           /*  32 */
-extern const opus_int32  silk_TargetRate_table_MB[  TARGET_RATE_TAB_SZ ];                           /*  32 */
-extern const opus_int32  silk_TargetRate_table_WB[  TARGET_RATE_TAB_SZ ];                           /*  32 */
-extern const opus_int16  silk_SNR_table_Q1[         TARGET_RATE_TAB_SZ ];                           /*  32 */
-
 /* Quantization offsets */
 extern const opus_int16  silk_Quantization_Offsets_Q10[ 2 ][ 2 ];                                   /*   8 */
 
index 398686b..e34d907 100644 (file)
@@ -38,20 +38,6 @@ extern "C"
 {
 #endif
 
-/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */
-const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = {
-    0,      8000,   9400,   11500,  13500,  17500,  25000,  MAX_TARGET_RATE_BPS
-};
-const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = {
-    0,      9000,   12000,  14500,  18500,  24500,  35500,  MAX_TARGET_RATE_BPS
-};
-const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = {
-    0,      10500,  14000,  17000,  21500,  28500,  42000,  MAX_TARGET_RATE_BPS
-};
-const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = {
-    18,     29,     38,     40,     46,     52,     62,     84
-};
-
 /* Tables for stereo predictor coding */
 const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = {
     -13732, -10050, -8266, -7526, -6500, -5000, -2950,  -820,