shithub: opus

Download patch

ref: 3499e78bd5a93edcef80f6cbd88e7fc1e1666d9b
parent: 8adff0bb31989deb616ca72d16fc3e791ed91b10
author: Koen Vos <koenvos74@gmail.com>
date: Mon Aug 10 08:22:25 EDT 2015

Fix for flutter with FEC

The bug was caused by an improper feedback of the per-frame bitrate, causing
the bitrate to jump up and down from frame to frame, within a packet.
The patch avoids this, and also gives a slight improvement in general for
multi-frame packets, even without FEC.

Signed-off-by: Jean-Marc Valin <jmvalin@jmvalin.ca>

--- a/silk/control_SNR.c
+++ b/silk/control_SNR.c
@@ -70,11 +70,6 @@
                 break;
             }
         }
-
-        /* Reduce coding quality whenever LBRR is enabled, to free up some bits */
-        if( psEncC->LBRR_enabled ) {
-            psEncC->SNR_dB_Q7 = silk_SMLABB( psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST( -0.25, 7 ) );
-        }
     }
 
     return ret;
--- a/silk/control_codec.c
+++ b/silk/control_codec.c
@@ -397,9 +397,10 @@
     const opus_int32            TargetRate_bps      /* I                        */
 )
 {
-    opus_int   ret = SILK_NO_ERROR;
+    opus_int   LBRR_in_previous_packet, ret = SILK_NO_ERROR;
     opus_int32 LBRR_rate_thres_bps;
 
+    LBRR_in_previous_packet = psEncC->LBRR_enabled;
     psEncC->LBRR_enabled = 0;
     if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
         if( psEncC->fs_kHz == 8 ) {
@@ -413,8 +414,13 @@
 
         if( TargetRate_bps > LBRR_rate_thres_bps ) {
             /* Set gain increase for coding LBRR excitation */
+            if( LBRR_in_previous_packet == 0 ) {
+                /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
+                psEncC->LBRR_GainIncreases = 7;
+            } else {
+                psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
+            }
             psEncC->LBRR_enabled = 1;
-            psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
         }
     }
 
--- a/silk/enc_API.c
+++ b/silk/enc_API.c
@@ -376,6 +376,8 @@
                 for( n = 0; n < encControl->nChannelsInternal; n++ ) {
                     silk_memset( psEnc->state_Fxx[ n ].sCmn.LBRR_flags, 0, sizeof( psEnc->state_Fxx[ n ].sCmn.LBRR_flags ) );
                 }
+
+                psEnc->nBitsUsedLBRR = ec_tell( psRangeEnc );
             }
 
             silk_HP_variable_cutoff( psEnc->state_Fxx );
@@ -382,12 +384,12 @@
 
             /* Total target bits for packet */
             nBits = silk_DIV32_16( silk_MUL( encControl->bitRate, encControl->payloadSize_ms ), 1000 );
-            /* Subtract half of the bits already used */
+            /* Subtract bits used for LBRR */
             if( !prefillFlag ) {
-                nBits -= ec_tell( psRangeEnc ) >> 1;
+                nBits -= psEnc->nBitsUsedLBRR;
             }
             /* Divide by number of uncoded frames left in packet */
-            nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket - psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded );
+            nBits = silk_DIV32_16( nBits, psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket );
             /* Convert to bits/second */
             if( encControl->payloadSize_ms == 10 ) {
                 TargetRate_bps = silk_SMULBB( nBits, 100 );
@@ -394,8 +396,13 @@
             } else {
                 TargetRate_bps = silk_SMULBB( nBits, 50 );
             }
-            /* Subtract fraction of bits in excess of target in previous packets */
+            /* Subtract fraction of bits in excess of target in previous frames and packets */
             TargetRate_bps -= silk_DIV32_16( silk_MUL( psEnc->nBitsExceeded, 1000 ), BITRESERVOIR_DECAY_TIME_MS );
+            if( !prefillFlag && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded > 0 ) {
+                /* Compare actual vs target bits so far in this packet */
+                opus_int32 bitsBalance = ec_tell( psRangeEnc ) - psEnc->nBitsUsedLBRR - nBits * psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
+                TargetRate_bps -= silk_DIV32_16( silk_MUL( bitsBalance, 1000 ), BITRESERVOIR_DECAY_TIME_MS );
+            }
             /* Never exceed input bitrate */
             TargetRate_bps = silk_LIMIT( TargetRate_bps, encControl->bitRate, 5000 );
 
--- a/silk/fixed/structs_FIX.h
+++ b/silk/fixed/structs_FIX.h
@@ -116,6 +116,7 @@
 typedef struct {
     silk_encoder_state_FIX      state_Fxx[ ENCODER_NUM_CHANNELS ];
     stereo_enc_state            sStereo;
+    opus_int32                  nBitsUsedLBRR;
     opus_int32                  nBitsExceeded;
     opus_int                    nChannelsAPI;
     opus_int                    nChannelsInternal;
--- a/silk/float/structs_FLP.h
+++ b/silk/float/structs_FLP.h
@@ -115,6 +115,7 @@
 typedef struct {
     silk_encoder_state_FLP      state_Fxx[ ENCODER_NUM_CHANNELS ];
     stereo_enc_state            sStereo;
+    opus_int32                  nBitsUsedLBRR;
     opus_int32                  nBitsExceeded;
     opus_int                    nChannelsAPI;
     opus_int                    nChannelsInternal;