Makes the encoder more aggressive about meeting the rate target
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Wed, 20 Apr 2016 07:37:32 +0000 (03:37 -0400)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Sun, 17 Jul 2016 19:05:54 +0000 (15:05 -0400)
silk/NSQ.c
silk/NSQ_del_dec.c
silk/float/encode_frame_FLP.c

index 43e3fee..5032b9c 100644 (file)
@@ -226,6 +226,10 @@ void silk_noise_shape_quantizer(
     silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder);
 #endif
 
+    /* We're getting desperate to hit the target -- pretend there's
+       no dithering to make hitting the target more likely. */
+    if (Lambda_Q10 > 3072) offset_Q10 = 0;
+
     for( i = 0; i < length; i++ ) {
         /* Generate dither */
         NSQ->rand_seed = silk_RAND( NSQ->rand_seed );
@@ -287,6 +291,19 @@ void silk_noise_shape_quantizer(
         /* Find two quantization level candidates and measure their rate-distortion */
         q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
         q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
+        if (Lambda_Q10 > 2048) {
+            /* For aggressive RDO, the bias becomes more than one pulse. */
+            int rdo_offset = Lambda_Q10/2 - 512;
+            if (q1_Q10 > rdo_offset) {
+                q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+            } else if (q1_Q10 < -rdo_offset) {
+                q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+            } else if (q1_Q10 < 0) {
+                q1_Q0 = -1;
+            } else {
+                q1_Q0 = 0;
+            }
+        }
         if( q1_Q0 > 0 ) {
             q1_Q10  = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
             q1_Q10  = silk_ADD32( q1_Q10, offset_Q10 );
index ab6feea..c5c7749 100644 (file)
@@ -356,6 +356,9 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
     NSQ_sample_struct  *psSS;
     SAVE_STACK;
 
+    /* We're getting desperate to hit the target -- pretend there's
+       no dithering to make hitting the target more likely. */
+    if (Lambda_Q10 > 3072) offset_Q10 = 0;
     silk_assert( nStatesDelayedDecision > 0 );
     ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
 
@@ -462,6 +465,19 @@ static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
             /* Find two quantization level candidates and measure their rate-distortion */
             q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
             q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
+            if (Lambda_Q10 > 2048) {
+                /* For aggressive RDO, the bias becomes more than one pulse. */
+                int rdo_offset = Lambda_Q10/2 - 512;
+                if (q1_Q10 > rdo_offset) {
+                    q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+                } else if (q1_Q10 < -rdo_offset) {
+                    q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+                } else if (q1_Q10 < 0) {
+                    q1_Q0 = -1;
+                } else {
+                    q1_Q0 = 0;
+                }
+            }
             if( q1_Q0 > 0 ) {
                 q1_Q10  = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
                 q1_Q10  = silk_ADD32( q1_Q10, offset_Q10 );
index 2092a4d..61b9b26 100644 (file)
@@ -223,7 +223,9 @@ opus_int silk_encode_frame_FLP(
             if( nBits > maxBits ) {
                 if( found_lower == 0 && iter >= 2 ) {
                     /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
-                    sEncCtrl.Lambda *= 1.5f;
+                    sEncCtrl.Lambda = silk_max_float(sEncCtrl.Lambda*1.5f, 1.5f);
+                    /* Reducing dithering can help us hit the target. */
+                    psEnc->sCmn.indices.quantOffsetType = 0;
                     found_upper = 0;
                     gainsID_upper = -1;
                 } else {
@@ -252,13 +254,17 @@ opus_int silk_encode_frame_FLP(
 
             if( ( found_lower & found_upper ) == 0 ) {
                 /* Adjust gain according to high-rate rate/distortion curve */
-                opus_int32 gain_factor_Q16;
-                gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
-                gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
                 if( nBits > maxBits ) {
-                    gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
+                    if (gainMult_Q8 < 16384) {
+                        gainMult_Q8 *= 2;
+                    } else {
+                        gainMult_Q8 = 32767;
+                    }
+                } else {
+                    opus_int32 gain_factor_Q16;
+                    gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
+                    gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
                 }
-                gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
             } else {
                 /* Adjust gain by interpolating */
                 gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );