Constrains accumulated pitch gain to avoid potential instability.
[opus.git] / silk / control_codec.c
index 829b08f..1f674bd 100644 (file)
@@ -1,28 +1,28 @@
 /***********************************************************************
 Copyright (c) 2006-2011, Skype Limited. All rights reserved.
 Redistribution and use in source and binary forms, with or without
-modification, (subject to the limitations in the disclaimer below)
-are permitted provided that the following conditions are met:
+modification, are permitted provided that the following conditions
+are met:
 - Redistributions of source code must retain the above copyright notice,
 this list of conditions and the following disclaimer.
 - Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the
 documentation and/or other materials provided with the distribution.
-- Neither the name of Skype Limited, nor the names of specific
-contributors, may be used to endorse or promote products derived from
-this software without specific prior written permission.
-NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
-BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
-CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
-BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
-USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/
 
 #ifdef HAVE_CONFIG_H
@@ -35,33 +35,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "main_FLP.h"
 #define silk_encoder_state_Fxx      silk_encoder_state_FLP
 #endif
+#include "stack_alloc.h"
 #include "tuning_parameters.h"
 #include "pitch_est_defines.h"
 
-static const opus_int enc_delay_matrix[3][5] = {
-/*SILK API 8  12  16  24  48 */
-/* 8 */   {5,  0,  3,  4,  8},
-/*12 */   {0,  6,  0,  0,  0},
-/*16 */   {4,  5, 11,  5, 18}
-};
-
-opus_int silk_setup_resamplers(
+static opus_int silk_setup_resamplers(
     silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
     opus_int                        fs_kHz              /* I                        */
 );
 
-opus_int silk_setup_fs(
+static opus_int silk_setup_fs(
     silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
     opus_int                        fs_kHz,             /* I                        */
     opus_int                        PacketSize_ms       /* I                        */
 );
 
-opus_int silk_setup_complexity(
+static opus_int silk_setup_complexity(
     silk_encoder_state              *psEncC,            /* I/O                      */
     opus_int                        Complexity          /* I                        */
 );
 
-static inline opus_int silk_setup_LBRR(
+static OPUS_INLINE opus_int silk_setup_LBRR(
     silk_encoder_state              *psEncC,            /* I/O                      */
     const opus_int32                TargetRate_bps      /* I                        */
 );
@@ -138,62 +132,72 @@ opus_int silk_control_encoder(
     return ret;
 }
 
-opus_int silk_setup_resamplers(
+static opus_int silk_setup_resamplers(
     silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
     opus_int                         fs_kHz              /* I                        */
 )
 {
     opus_int   ret = SILK_NO_ERROR;
-    opus_int32 nSamples_temp;
+    SAVE_STACK;
 
     if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz )
     {
         if( psEnc->sCmn.fs_kHz == 0 ) {
             /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
-            ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000 );
+            ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000, 1 );
         } else {
-            /* Allocate worst case space for temporary upsampling, 8 to 48 kHz, so a factor 6 */
-            opus_int16 x_buf_API_fs_Hz[ ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * MAX_API_FS_KHZ ];
-            silk_resampler_state_struct  temp_resampler_state;
+            VARDECL( opus_int16, x_buf_API_fs_Hz );
+            VARDECL( silk_resampler_state_struct, temp_resampler_state );
 #ifdef FIXED_POINT
             opus_int16 *x_bufFIX = psEnc->x_buf;
 #else
-            opus_int16 x_bufFIX[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];
+            VARDECL( opus_int16, x_bufFIX );
+            opus_int32 new_buf_samples;
 #endif
+            opus_int32 api_buf_samples;
+            opus_int32 old_buf_samples;
+            opus_int32 buf_length_ms;
 
-            nSamples_temp = silk_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz;
+            buf_length_ms = silk_LSHIFT( psEnc->sCmn.nb_subfr * 5, 1 ) + LA_SHAPE_MS;
+            old_buf_samples = buf_length_ms * psEnc->sCmn.fs_kHz;
 
 #ifndef FIXED_POINT
-            silk_float2short_array( x_bufFIX, psEnc->x_buf, nSamples_temp );
+            new_buf_samples = buf_length_ms * fs_kHz;
+            ALLOC( x_bufFIX, silk_max( old_buf_samples, new_buf_samples ),
+                   opus_int16 );
+            silk_float2short_array( x_bufFIX, psEnc->x_buf, old_buf_samples );
 #endif
 
             /* Initialize resampler for temporary resampling of x_buf data to API_fs_Hz */
-            ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz );
+            ALLOC( temp_resampler_state, 1, silk_resampler_state_struct );
+            ret += silk_resampler_init( temp_resampler_state, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ), psEnc->sCmn.API_fs_Hz, 0 );
 
-            /* Temporary resampling of x_buf data to API_fs_Hz */
-            ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp );
+            /* Calculate number of samples to temporarily upsample */
+            api_buf_samples = buf_length_ms * silk_DIV32_16( psEnc->sCmn.API_fs_Hz, 1000 );
 
-            /* Calculate number of samples that has been temporarily upsampled */
-            nSamples_temp = silk_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) );
+            /* Temporary resampling of x_buf data to API_fs_Hz */
+            ALLOC( x_buf_API_fs_Hz, api_buf_samples, opus_int16 );
+            ret += silk_resampler( temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, old_buf_samples );
 
             /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
-            ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ) );
+            ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, silk_SMULBB( fs_kHz, 1000 ), 1 );
 
             /* Correct resampler state by resampling buffered data from API_fs_Hz to fs_kHz */
-            ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, nSamples_temp );
+            ret += silk_resampler( &psEnc->sCmn.resampler_state, x_bufFIX, x_buf_API_fs_Hz, api_buf_samples );
 
 #ifndef FIXED_POINT
-            silk_short2float_array( psEnc->x_buf, x_bufFIX, ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * fs_kHz );
+            silk_short2float_array( psEnc->x_buf, x_bufFIX, new_buf_samples);
 #endif
         }
     }
 
     psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz;
 
+    RESTORE_STACK;
     return ret;
 }
 
-opus_int silk_setup_fs(
+static opus_int silk_setup_fs(
     silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
     opus_int                        fs_kHz,             /* I                        */
     opus_int                        PacketSize_ms       /* I                        */
@@ -234,9 +238,6 @@ opus_int silk_setup_fs(
         psEnc->sCmn.TargetRate_bps = 0;         /* trigger new SNR computation */
     }
 
-    psEnc->sCmn.delay = enc_delay_matrix[rateID(fs_kHz*1000)][rateID(psEnc->sCmn.API_fs_Hz)];
-    silk_assert(psEnc->sCmn.delay <= MAX_ENCODER_DELAY);
-
     /* Set internal sampling frequency */
     silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
     silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
@@ -257,7 +258,7 @@ opus_int silk_setup_fs(
         psEnc->sPrefilt.lagPrev                 = 100;
         psEnc->sShape.LastGainIndex             = 10;
         psEnc->sCmn.sNSQ.lagPrev                = 100;
-        psEnc->sCmn.sNSQ.prev_inv_gain_Q16      = 65536;
+        psEnc->sCmn.sNSQ.prev_gain_Q16          = 65536;
         psEnc->sCmn.prevSignalType              = TYPE_NO_VOICE_ACTIVITY;
 
         psEnc->sCmn.fs_kHz = fs_kHz;
@@ -309,7 +310,7 @@ opus_int silk_setup_fs(
     return ret;
 }
 
-opus_int silk_setup_complexity(
+static opus_int silk_setup_complexity(
     silk_encoder_state              *psEncC,            /* I/O                      */
     opus_int                        Complexity          /* I                        */
 )
@@ -336,7 +337,7 @@ opus_int silk_setup_complexity(
         psEncC->shapingLPCOrder                 = 10;
         psEncC->la_shape                        = 5 * psEncC->fs_kHz;
         psEncC->nStatesDelayedDecision          = 1;
-        psEncC->useInterpolatedNLSFs            = 1;
+        psEncC->useInterpolatedNLSFs            = 0;
         psEncC->LTPQuantLowComplexity           = 0;
         psEncC->NLSF_MSVQ_Survivors             = 4;
         psEncC->warping_Q16                     = 0;
@@ -347,7 +348,7 @@ opus_int silk_setup_complexity(
         psEncC->shapingLPCOrder                 = 12;
         psEncC->la_shape                        = 5 * psEncC->fs_kHz;
         psEncC->nStatesDelayedDecision          = 2;
-        psEncC->useInterpolatedNLSFs            = 0;
+        psEncC->useInterpolatedNLSFs            = 1;
         psEncC->LTPQuantLowComplexity           = 0;
         psEncC->NLSF_MSVQ_Survivors             = 8;
         psEncC->warping_Q16                     = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
@@ -358,7 +359,7 @@ opus_int silk_setup_complexity(
         psEncC->shapingLPCOrder                 = 14;
         psEncC->la_shape                        = 5 * psEncC->fs_kHz;
         psEncC->nStatesDelayedDecision          = 3;
-        psEncC->useInterpolatedNLSFs            = 0;
+        psEncC->useInterpolatedNLSFs            = 1;
         psEncC->LTPQuantLowComplexity           = 0;
         psEncC->NLSF_MSVQ_Survivors             = 16;
         psEncC->warping_Q16                     = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
@@ -391,7 +392,7 @@ opus_int silk_setup_complexity(
     return ret;
 }
 
-static inline opus_int silk_setup_LBRR(
+static OPUS_INLINE opus_int silk_setup_LBRR(
     silk_encoder_state          *psEncC,            /* I/O                      */
     const opus_int32            TargetRate_bps      /* I                        */
 )
@@ -413,7 +414,7 @@ static inline opus_int silk_setup_LBRR(
         if( TargetRate_bps > LBRR_rate_thres_bps ) {
             /* Set gain increase for coding LBRR excitation */
             psEncC->LBRR_enabled = 1;
-            psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
+            psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
         }
     }