ref: 85ce87ffbe8b30247f62bf2868d28ef75468aec9
parent: 004ef8b9b1771688cd514cdb1c9f466913e3a355
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Wed May 16 16:05:47 EDT 2018
Improving rate control for low bitrate 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.
--- a/silk/control_SNR.c
+++ b/silk/control_SNR.c
@@ -32,6 +32,52 @@
#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 */
@@ -38,38 +84,30 @@
opus_int32 TargetRate_bps /* I Target max bitrate (bps) */
)
{
- opus_int k, ret = SILK_NO_ERROR;
- opus_int32 frac_Q6;
- const opus_int32 *rateTable;
+ int id;
+ int bound;
+ const unsigned char *snr_table;
- /* 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;
- }
-
- /* 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;
}
--- a/silk/define.h
+++ b/silk/define.h
@@ -46,7 +46,6 @@
/* 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
--- a/silk/tables.h
+++ b/silk/tables.h
@@ -97,12 +97,6 @@
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 */
--- a/silk/tables_other.c
+++ b/silk/tables_other.c
@@ -38,20 +38,6 @@
{
#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,