SILK fixes following last codec WG meeting
authorKoen Vos <koen.vos@skype.net>
Tue, 13 Dec 2011 19:47:31 +0000 (14:47 -0500)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Tue, 13 Dec 2011 19:47:31 +0000 (14:47 -0500)
decoder:
- fixed incorrect scaling of filter states for the smallest quantization
  step sizes
- NLSF2A now limits the prediction gain of LPC filters

encoder:
- increased damping of LTP coefficients in LTP analysis
- increased white noise fraction in noise shaping LPC analysis
- introduced maximum total prediction gain.  Used by Burg's method to
  exit early if prediction gain is exceeded.  This improves packet
  loss robustness and numerical robustness in Burg's method
- Prefiltered signal is now in int32 Q10 domain, from int16 Q0
- Increased max number of iterations in CBR gain control loop from 5 to 6
- Removed useless code from LTP scaling control
- Optimization: smarter LPC loop unrolling
- Switched default win32 compile mode to be floating-point

resampler:
- made resampler have constant delay of 0.75 ms; removed delay
  compensation from silk code.
- removed obsolete table entries (~850 Bytes)
- increased downsampling filter order from 16 to 18/24/36 (depending on
  frequency ratio)
- reoptimized filter coefficients

71 files changed:
silk/CNG.c
silk/LPC_analysis_filter.c
silk/LPC_inv_pred_gain.c
silk/MacroDebug.h
silk/NLSF2A.c
silk/NLSF_VQ.c
silk/NLSF_decode.c
silk/NLSF_encode.c
silk/NSQ.c
silk/NSQ_del_dec.c
silk/PLC.c
silk/PLC.h
silk/SigProc_FIX.h
silk/VAD.c
silk/control_codec.c
silk/dec_API.c
silk/decode_core.c
silk/decode_parameters.c
silk/decoder_set_fs.c
silk/define.h
silk/enc_API.c
silk/fixed/LTP_analysis_filter_FIX.c
silk/fixed/LTP_scale_ctrl_FIX.c
silk/fixed/burg_modified_FIX.c
silk/fixed/encode_frame_FIX.c
silk/fixed/find_LPC_FIX.c
silk/fixed/find_LTP_FIX.c
silk/fixed/find_pitch_lags_FIX.c
silk/fixed/find_pred_coefs_FIX.c
silk/fixed/main_FIX.h
silk/fixed/noise_shape_analysis_FIX.c
silk/fixed/pitch_analysis_core_FIX.c
silk/fixed/prefilter_FIX.c
silk/fixed/residual_energy16_FIX.c
silk/fixed/schur_FIX.c
silk/fixed/structs_FIX.h
silk/fixed/warped_autocorrelation_FIX.c
silk/float/LPC_inv_pred_gain_FLP.c
silk/float/LTP_scale_ctrl_FLP.c
silk/float/SigProc_FLP.h
silk/float/burg_modified_FLP.c
silk/float/encode_frame_FLP.c
silk/float/find_LPC_FLP.c
silk/float/find_pitch_lags_FLP.c
silk/float/find_pred_coefs_FLP.c
silk/float/main_FLP.h
silk/float/noise_shape_analysis_FLP.c
silk/float/pitch_analysis_core_FLP.c
silk/float/prefilter_FLP.c
silk/float/process_gains_FLP.c
silk/float/structs_FLP.h
silk/float/wrappers_FLP.c
silk/interpolate.c
silk/macros.h
silk/main.h
silk/quant_LTP_gains.c
silk/resampler.c
silk/resampler_down2.c
silk/resampler_private.h
silk/resampler_private_IIR_FIR.c
silk/resampler_private_down_FIR.c
silk/resampler_private_up2_HQ.c
silk/resampler_rom.c
silk/resampler_rom.h
silk/resampler_structs.h
silk/stereo_LR_to_MS.c
silk/stereo_MS_to_LR.c
silk/structs.h
silk/tuning_parameters.h
src/opus_encoder.c
win32/config.h

index d67e872..6885d83 100644 (file)
@@ -54,7 +54,7 @@ static inline void silk_CNG_exc(
         idx = ( opus_int )( silk_RSHIFT( seed, 24 ) & exc_mask );
         silk_assert( idx >= 0 );
         silk_assert( idx <= CNG_BUF_MASK_MAX );
-        residual_Q10[ i ] = ( opus_int16 )silk_SAT16( silk_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ) );
+        residual_Q10[ i ] = (opus_int16)silk_SAT16( silk_SMULWW( exc_buf_Q10[ idx ], Gain_Q16 ) );
     }
     *rand_seed = seed;
 }
@@ -83,7 +83,7 @@ void silk_CNG(
     opus_int                    length                          /* I    Length of residual                          */
 )
 {
-    opus_int   i, j, subfr;
+    opus_int   i, subfr;
     opus_int32 sum_Q6, max_Gain_Q16;
     opus_int16 A_Q12[ MAX_LPC_ORDER ];
     opus_int32 CNG_sig_Q10[ MAX_FRAME_LENGTH + MAX_LPC_ORDER ];
@@ -133,7 +133,7 @@ void silk_CNG(
         /* Generate CNG signal, by synthesis filtering */
         silk_memcpy( CNG_sig_Q10, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
         for( i = 0; i < length; i++ ) {
-            /* Partially unrolled */
+            silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
             sum_Q6 = silk_SMULWB(         CNG_sig_Q10[ MAX_LPC_ORDER + i -  1 ], A_Q12[ 0 ] );
             sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i -  2 ], A_Q12[ 1 ] );
             sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i -  3 ], A_Q12[ 2 ] );
@@ -144,8 +144,13 @@ void silk_CNG(
             sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i -  8 ], A_Q12[ 7 ] );
             sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i -  9 ], A_Q12[ 8 ] );
             sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
-            for( j = 10; j < psDec->LPC_order; j++ ) {
-                sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] );
+            if( psDec->LPC_order == 16 ) {
+                sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
+                sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
+                sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
+                sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
+                sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
+                sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
             }
 
             /* Update states */
index bf5c284..e1a9d91 100644 (file)
@@ -77,7 +77,7 @@ void silk_LPC_analysis_filter(
         out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
 
         /* Saturate output */
-        out[ ix ] = ( opus_int16 )silk_SAT16( out32 );
+        out[ ix ] = (opus_int16)silk_SAT16( out32 );
     }
 
     /* Set first d output samples to zero */
index 249da31..db529d1 100644 (file)
@@ -38,24 +38,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /* Compute inverse of LPC prediction gain, and                          */
 /* test if LPC coefficients are stable (all poles within unit circle)   */
-static opus_int LPC_inverse_pred_gain_QA(                   /* O   Returns 1 if unstable, otherwise 0          */
-    opus_int32           *invGain_Q30,                      /* O   Inverse prediction gain, Q30 energy domain  */
-    opus_int32           A_QA[ 2 ][ SILK_MAX_ORDER_LPC ],   /* I   Prediction coefficients                     */
-    const opus_int       order                              /* I   Prediction order                            */
+static opus_int32 LPC_inverse_pred_gain_QA(                 /* O   Returns inverse prediction gain in energy domain, Q30    */
+    opus_int32           A_QA[ 2 ][ SILK_MAX_ORDER_LPC ],   /* I   Prediction coefficients                                  */
+    const opus_int       order                              /* I   Prediction order                                         */
 )
 {
     opus_int   k, n, mult2Q;
-    opus_int32 rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA;
+    opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA;
     opus_int32 *Aold_QA, *Anew_QA;
 
     Anew_QA = A_QA[ order & 1 ];
 
-    *invGain_Q30 = ( 1 << 30 );
+    invGain_Q30 = 1 << 30;
     for( k = order - 1; k > 0; k-- ) {
         /* Check for stability */
         if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
-            *invGain_Q30 = 0;
-            return 1;
+            return 0;
         }
 
         /* Set RC equal to negated AR coef */
@@ -72,9 +70,9 @@ static opus_int LPC_inverse_pred_gain_QA(                   /* O   Returns 1 if
 
         /* Update inverse gain */
         /* invGain_Q30 range: [ 0 : 2^30 ] */
-        *invGain_Q30 = silk_LSHIFT( silk_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 );
-        silk_assert( *invGain_Q30 >= 0           );
-        silk_assert( *invGain_Q30 <= ( 1 << 30 ) );
+        invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
+        silk_assert( invGain_Q30 >= 0           );
+        silk_assert( invGain_Q30 <= ( 1 << 30 ) );
 
         /* Swap pointers */
         Aold_QA = Anew_QA;
@@ -89,8 +87,7 @@ static opus_int LPC_inverse_pred_gain_QA(                   /* O   Returns 1 if
 
     /* Check for stability */
     if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
-        *invGain_Q30 = 0;
-        return 1;
+        return 0;
     }
 
     /* Set RC equal to negated AR coef */
@@ -101,16 +98,15 @@ static opus_int LPC_inverse_pred_gain_QA(                   /* O   Returns 1 if
 
     /* Update inverse gain */
     /* Range: [ 0 : 2^30 ] */
-    *invGain_Q30 = silk_LSHIFT( silk_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 );
-    silk_assert( *invGain_Q30 >= 0     );
-    silk_assert( *invGain_Q30 <= 1<<30 );
+    invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
+    silk_assert( invGain_Q30 >= 0     );
+    silk_assert( invGain_Q30 <= 1<<30 );
 
-    return 0;
+    return invGain_Q30;
 }
 
 /* For input in Q12 domain */
-opus_int silk_LPC_inverse_pred_gain(                /* O   Returns 1 if unstable, otherwise 0                           */
-    opus_int32                  *invGain_Q30,       /* O   Inverse prediction gain, Q30 energy domain                   */
+opus_int32 silk_LPC_inverse_pred_gain(              /* O   Returns inverse prediction gain in energy domain, Q30        */
     const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
     const opus_int              order               /* I   Prediction order                                             */
 )
@@ -118,30 +114,27 @@ opus_int silk_LPC_inverse_pred_gain(                /* O   Returns 1 if unstable
     opus_int   k;
     opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
     opus_int32 *Anew_QA;
-    opus_int32 DC_resp=0;
+    opus_int32 DC_resp = 0;
 
     Anew_QA = Atmp_QA[ order & 1 ];
 
     /* Increase Q domain of the AR coefficients */
     for( k = 0; k < order; k++ ) {
         DC_resp += (opus_int32)A_Q12[ k ];
-        Anew_QA[ k ] = silk_LSHIFT( (opus_int32)A_Q12[ k ], QA - 12 );
+        Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
     }
     /* If the DC is unstable, we don't even need to do the full calculations */
     if( DC_resp >= 4096 ) {
-       *invGain_Q30 = 0;
-       return 1;
+        return 0;
     }
-    return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order );
+    return LPC_inverse_pred_gain_QA( Atmp_QA, order );
 }
 
 #ifdef FIXED_POINT
 
 /* For input in Q24 domain */
-/* This function is only used by the fixed-point build */
-opus_int silk_LPC_inverse_pred_gain_Q24(            /* O    Returns 1 if unstable, otherwise 0                          */
-    opus_int32                  *invGain_Q30,       /* O    Inverse prediction gain, Q30 energy domain                  */
-    const opus_int32            *A_Q24,             /* I    Prediction coefficients, Q24 [order]                        */
+opus_int32 silk_LPC_inverse_pred_gain_Q24(          /* O    Returns inverse prediction gain in energy domain, Q30       */
+    const opus_int32            *A_Q24,             /* I    Prediction coefficients [order]                             */
     const opus_int              order               /* I    Prediction order                                            */
 )
 {
@@ -153,9 +146,9 @@ opus_int silk_LPC_inverse_pred_gain_Q24(            /* O    Returns 1 if unstabl
 
     /* Increase Q domain of the AR coefficients */
     for( k = 0; k < order; k++ ) {
-        Anew_QA[ k ] = silk_RSHIFT( A_Q24[ k ], 24 - QA );
+        Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA );
     }
 
-    return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order );
+    return LPC_inverse_pred_gain_QA( Atmp_QA, order );
 }
 #endif
index 8adf44e..9d7e1f8 100644 (file)
@@ -91,24 +91,24 @@ static inline opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){
 static inline opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) {
     opus_int16 res;
     res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
-    silk_assert( res == silk_SAT16( ( opus_int32 )a16 + ( opus_int32 )b16 ) );
+    silk_assert( res == silk_SAT16( (opus_int32)a16 + (opus_int32)b16 ) );
     return res;
 }
 
 #undef silk_ADD_SAT32
 static inline opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){
     opus_int32 res;
-    res =    ((((a32) + (b32)) & 0x80000000) == 0 ?                                    \
+    res =    ((((a32) + (b32)) & 0x80000000) == 0 ?                                   \
             ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) :    \
             ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
-    silk_assert( res == silk_SAT32( ( opus_int64 )a32 + ( opus_int64 )b32 ) );
+    silk_assert( res == silk_SAT32( (opus_int64)a32 + (opus_int64)b32 ) );
     return res;
 }
 
 #undef silk_ADD_SAT64
 static inline opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) {
     opus_int64 res;
-    res =    ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ?                                \
+    res =    ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ?                                   \
             ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) :    \
             ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
     if( res != a64 + b64 ) {
@@ -126,24 +126,24 @@ static inline opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) {
 static inline opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) {
     opus_int16 res;
     res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
-    silk_assert( res == silk_SAT16( ( opus_int32 )a16 - ( opus_int32 )b16 ) );
+    silk_assert( res == silk_SAT16( (opus_int32)a16 - (opus_int32)b16 ) );
     return res;
 }
 
 #undef silk_SUB_SAT32
 static inline opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) {
     opus_int32 res;
-    res =     ((((a32)-(b32)) & 0x80000000) == 0 ?                                            \
+    res =     ((((a32)-(b32)) & 0x80000000) == 0 ?                                           \
             (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) :    \
             ((((a32)^0x80000000) & (b32)  & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
-    silk_assert( res == silk_SAT32( ( opus_int64 )a32 - ( opus_int64 )b32 ) );
+    silk_assert( res == silk_SAT32( (opus_int64)a32 - (opus_int64)b32 ) );
     return res;
 }
 
 #undef silk_SUB_SAT64
 static inline opus_int64 silk_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) {
     opus_int64 res;
-    res =    ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ?                                                        \
+    res =    ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ?                                                      \
             (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) :    \
             ((((a64)^0x8000000000000000LL) & (b64)  & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
 
index f2a2693..b10c690 100644 (file)
@@ -83,7 +83,7 @@ void silk_NLSF2A(
     opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
     opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
     opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
-    opus_int32 maxabs, absval, idx=0, sc_Q16, invGain_Q30;
+    opus_int32 maxabs, absval, idx=0, sc_Q16;
 
     silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
     silk_assert( d==10||d==16 );
@@ -162,8 +162,8 @@ void silk_NLSF2A(
         }
     }
 
-    for( i = 1; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
-        if( silk_LPC_inverse_pred_gain( &invGain_Q30, a_Q12, d ) == 1 ) {
+    for( i = 1; i <= MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
+        if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
             /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion   */
             /* on the unscaled coefficients, convert to Q12 and measure again                   */
             silk_bwexpander_32( a32_QA1, d, 65536 - silk_SMULBB( 9 + i, i ) );            /* 10_Q16 = 0.00015 */
@@ -175,7 +175,7 @@ void silk_NLSF2A(
         }
     }
 
-    if( i == MAX_LPC_STABILIZE_ITERATIONS ) {
+    if( i > MAX_LPC_STABILIZE_ITERATIONS ) {
         /* Reached the last iteration, set coefficients to zero */
         for( k = 0; k < d; k++ ) {
             a_Q12[ k ] = 0;
index e547542..4510883 100644 (file)
@@ -51,11 +51,11 @@ void silk_NLSF_VQ(
         sum_error_Q26 = 0;
         for( m = 0; m < LPC_order; m += 2 ) {
             /* Compute weighted squared quantization error for index m */
-            diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], ( opus_int32 )*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
+            diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
             sum_error_Q30 = silk_SMULBB( diff_Q15, diff_Q15 );
 
             /* Compute weighted squared quantization error for index m + 1 */
-            diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], ( opus_int32 )*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
+            diff_Q15 = silk_SUB_LSHIFT32( in_Q15[m + 1], (opus_int32)*pCB_Q8++, 7 ); /* range: [ -32767 : 32767 ]*/
             sum_error_Q30 = silk_SMLABB( sum_error_Q30, diff_Q15, diff_Q15 );
 
             sum_error_Q26 = silk_ADD_RSHIFT32( sum_error_Q26, sum_error_Q30, 4 );
index b1b83ae..124be41 100644 (file)
@@ -77,7 +77,7 @@ void silk_NLSF_decode(
     /* Decode first stage */
     pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
     for( i = 0; i < psNLSF_CB->order; i++ ) {
-        pNLSF_Q15[ i ] = silk_LSHIFT( ( opus_int16 )pCB_element[ i ], 7 );
+        pNLSF_Q15[ i ] = silk_LSHIFT( (opus_int16)pCB_element[ i ], 7 );
     }
 
     /* Unpack entropy table indices and predictor for current CB1 index */
@@ -91,8 +91,8 @@ void silk_NLSF_decode(
 
     /* Apply inverse square-rooted weights and add to output */
     for( i = 0; i < psNLSF_CB->order; i++ ) {
-        W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( ( opus_int32 )W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
-        NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( ( opus_int32 )res_Q10[ i ], 14 ), W_tmp_Q9 ) );
+        W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
+        NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) );
         pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
     }
 
index cc84160..5b20441 100644 (file)
@@ -79,7 +79,7 @@ opus_int32 silk_NLSF_encode(                                    /* O    Returns
         /* Residual after first stage */
         pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
         for( i = 0; i < psNLSF_CB->order; i++ ) {
-            NLSF_tmp_Q15[ i ] = silk_LSHIFT16( ( opus_int16 )pCB_element[ i ], 7 );
+            NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 );
             res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ];
         }
 
@@ -88,13 +88,13 @@ opus_int32 silk_NLSF_encode(                                    /* O    Returns
 
         /* Apply square-rooted weights */
         for( i = 0; i < psNLSF_CB->order; i++ ) {
-            W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( ( opus_int32 )W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
-            res_Q10[ i ] = ( opus_int16 )silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
+            W_tmp_Q9 = silk_SQRT_APPROX( silk_LSHIFT( (opus_int32)W_tmp_QW[ i ], 18 - NLSF_W_Q ) );
+            res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
         }
 
         /* Modify input weights accordingly */
         for( i = 0; i < psNLSF_CB->order; i++ ) {
-            W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( ( opus_int32 )pW_QW[ i ], 5 ), W_tmp_QW[ i ] );
+            W_adj_Q5[ i ] = silk_DIV32_16( silk_LSHIFT( (opus_int32)pW_QW[ i ], 5 ), W_tmp_QW[ i ] );
         }
 
         /* Unpack entropy table indices and predictor for current CB1 index */
@@ -118,7 +118,7 @@ opus_int32 silk_NLSF_encode(                                    /* O    Returns
     /* Find the lowest rate-distortion error */
     silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 );
 
-    NLSFIndices[ 0 ] = ( opus_int8 )tempIndices1[ bestIndex ];
+    NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ];
     silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) );
 
     /* Decode */
index 031b581..7600426 100644 (file)
@@ -34,10 +34,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 static inline void silk_nsq_scale_states(
     const silk_encoder_state *psEncC,           /* I    Encoder State                   */
     silk_nsq_state      *NSQ,                   /* I/O  NSQ state                       */
-    const opus_int16    x[],                    /* I    input in Q0                     */
+    const opus_int32    x_Q10[],                /* I    input in Q0                     */
     opus_int32          x_sc_Q10[],             /* O    input scaled with 1/Gain        */
     const opus_int16    sLTP[],                 /* I    re-whitened LTP state in Q0     */
-    opus_int32          sLTP_Q16[],             /* O    LTP state matching scaled input */
+    opus_int32          sLTP_Q15[],             /* O    LTP state matching scaled input */
     opus_int            subfr,                  /* I    subframe number                 */
     const opus_int      LTP_scale_Q14,          /* I                                    */
     const opus_int32    Gains_Q16[ MAX_NB_SUBFR ], /* I                                 */
@@ -51,7 +51,7 @@ static inline void silk_noise_shape_quantizer(
     const opus_int32    x_sc_Q10[],             /* I                                    */
     opus_int8           pulses[],               /* O                                    */
     opus_int16          xq[],                   /* O                                    */
-    opus_int32          sLTP_Q16[],             /* I/O  LTP state                       */
+    opus_int32          sLTP_Q15[],             /* I/O  LTP state                       */
     const opus_int16    a_Q12[],                /* I    Short term prediction coefs     */
     const opus_int16    b_Q14[],                /* I    Long term prediction coefs      */
     const opus_int16    AR_shp_Q13[],           /* I    Noise shaping AR coefs          */
@@ -71,7 +71,7 @@ void silk_NSQ(
     const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
-    const opus_int16            x[],                                        /* I    Prefiltered input signal        */
+    const opus_int32            x_Q10[],                                    /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
@@ -85,14 +85,14 @@ void silk_NSQ(
     const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
 )
 {
-    opus_int     k, lag, start_idx, LSF_interpolation_flag;
-    const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
-    opus_int16   *pxq;
-    opus_int32   sLTP_Q16[ 2 * MAX_FRAME_LENGTH ];
-    opus_int16   sLTP[     2 * MAX_FRAME_LENGTH ];
-    opus_int32   HarmShapeFIRPacked_Q14;
-    opus_int     offset_Q10;
-    opus_int32   x_sc_Q10[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ];
+    opus_int            k, lag, start_idx, LSF_interpolation_flag;
+    const opus_int16    *A_Q12, *B_Q14, *AR_shp_Q13;
+    opus_int16          *pxq;
+    opus_int32          sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
+    opus_int16          sLTP[     2 * MAX_FRAME_LENGTH ];
+    opus_int32          HarmShapeFIRPacked_Q14;
+    opus_int            offset_Q10;
+    opus_int32          x_sc_Q10[ MAX_SUB_FRAME_LENGTH ];
 
     NSQ->rand_seed = psIndices->Seed;
 
@@ -109,7 +109,7 @@ void silk_NSQ(
         LSF_interpolation_flag = 1;
     }
 
-    /* Setup pointers to start of sub frame */
+    /* Set up pointers to start of sub frame */
     NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
     NSQ->sLTP_buf_idx     = psEncC->ltp_mem_length;
     pxq                   = &NSQ->xq[ psEncC->ltp_mem_length ];
@@ -121,7 +121,7 @@ void silk_NSQ(
         /* Noise shape parameters */
         silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
         HarmShapeFIRPacked_Q14  =                          silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
-        HarmShapeFIRPacked_Q14 |= silk_LSHIFT( ( opus_int32 )silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
+        HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
 
         NSQ->rewhite_flag = 0;
         if( psIndices->signalType == TYPE_VOICED ) {
@@ -142,13 +142,13 @@ void silk_NSQ(
             }
         }
 
-        silk_nsq_scale_states( psEncC, NSQ, x, x_sc_Q10, sLTP, sLTP_Q16, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
+        silk_nsq_scale_states( psEncC, NSQ, x_Q10, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
 
-        silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q16, A_Q12, B_Q14,
+        silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
             AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
             offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder );
 
-        x      += psEncC->subfr_length;
+        x_Q10  += psEncC->subfr_length;
         pulses += psEncC->subfr_length;
         pxq    += psEncC->subfr_length;
     }
@@ -170,7 +170,7 @@ static inline void silk_noise_shape_quantizer(
     const opus_int32    x_sc_Q10[],             /* I                                    */
     opus_int8           pulses[],               /* O                                    */
     opus_int16          xq[],                   /* O                                    */
-    opus_int32          sLTP_Q16[],             /* I/O  LTP state                       */
+    opus_int32          sLTP_Q15[],             /* I/O  LTP state                       */
     const opus_int16    a_Q12[],                /* I    Short term prediction coefs     */
     const opus_int16    b_Q14[],                /* I    Long term prediction coefs      */
     const opus_int16    AR_shp_Q13[],           /* I    Noise shaping AR coefs          */
@@ -187,16 +187,16 @@ static inline void silk_noise_shape_quantizer(
 )
 {
     opus_int     i, j;
-    opus_int32   LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14;
+    opus_int32   LTP_pred_Q13, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14;
     opus_int32   n_LF_Q10, r_Q10, rr_Q10, q1_Q10, q2_Q10, rd1_Q10, rd2_Q10;
     opus_int32   dither, exc_Q10, LPC_exc_Q10, xq_Q10;
     opus_int32   tmp1, tmp2, sLF_AR_shp_Q10;
     opus_int32   *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
 
     shp_lag_ptr  = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
-    pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+    pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
 
-    /* Setup short term AR state */
+    /* Set up short term AR state */
     psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
 
     for( i = 0; i < length; i++ ) {
@@ -207,11 +207,7 @@ static inline void silk_noise_shape_quantizer(
         dither = silk_RSHIFT( NSQ->rand_seed, 31 );
 
         /* Short-term prediction */
-        silk_assert( ( predictLPCOrder  & 1 ) == 0 );    /* check that order is even */
-        silk_assert( ( (opus_int64)a_Q12 & 3 ) == 0 );    /* check that array starts at 4-byte aligned address */
-        silk_assert( predictLPCOrder >= 10 );            /* check that unrolling works */
-
-        /* Partially unrolled */
+        silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
         LPC_pred_Q10 = silk_SMULWB(               psLPC_Q14[  0 ], a_Q12[ 0 ] );
         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
@@ -222,21 +218,26 @@ static inline void silk_noise_shape_quantizer(
         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
         LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
-        for( j = 10; j < predictLPCOrder; j ++ ) {
-            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] );
+        if( predictLPCOrder == 16 ) {
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] );
         }
 
         /* Long-term prediction */
         if( signalType == TYPE_VOICED ) {
             /* Unrolled loop */
-            LTP_pred_Q14 = silk_SMULWB(               pred_lag_ptr[  0 ], b_Q14[ 0 ] );
-            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
-            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
-            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
-            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
+            LTP_pred_Q13 = silk_SMULWB(               pred_lag_ptr[  0 ], b_Q14[ 0 ] );
+            LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
+            LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
+            LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
+            LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
             pred_lag_ptr++;
         } else {
-            LTP_pred_Q14 = 0;
+            LTP_pred_Q13 = 0;
         }
 
         /* Noise shape feedback */
@@ -268,11 +269,11 @@ static inline void silk_noise_shape_quantizer(
         if( lag > 0 ) {
             /* Symmetric, packed FIR coefficients */
             n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
-            n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ],                     HarmShapeFIRPacked_Q14 );
+            n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ],                      HarmShapeFIRPacked_Q14 );
             n_LTP_Q14 = silk_LSHIFT( n_LTP_Q14, 6 );
             shp_lag_ptr++;
 
-            tmp1 = silk_SUB32( LTP_pred_Q14, n_LTP_Q14 );                        /* Add Q14 stuff */
+            tmp1 = silk_SUB32( LTP_pred_Q13 << 1, n_LTP_Q14 );                        /* Add Q14 stuff */
             tmp1 = silk_RSHIFT( tmp1, 4 );                                       /* convert to Q10  */
             tmp1 = silk_ADD32( tmp1, LPC_pred_Q10 );                             /* add Q10 stuff */
             tmp1 = silk_SUB32( tmp1, n_AR_Q10 );                                 /* subtract Q10 stuff */
@@ -324,18 +325,19 @@ static inline void silk_noise_shape_quantizer(
             q1_Q10 = q2_Q10;
         }
 
-        pulses[ i ] = ( opus_int8 )silk_RSHIFT_ROUND( q1_Q10, 10 );
+        pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 );
 
         /* Excitation */
         exc_Q10 = q1_Q10 ^ dither;
 
         /* Add predictions */
-        LPC_exc_Q10 = silk_ADD32( exc_Q10, silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ) );
+        LPC_exc_Q10 = silk_ADD32( exc_Q10, silk_RSHIFT_ROUND( LTP_pred_Q13, 3 ) );
         xq_Q10      = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
 
         /* Scale XQ back to normal level before saving */
         xq[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q10, Gain_Q16 ), 10 ) );
 
+               /* DEBUG_STORE_DATA( enc.pcm, &xq[i], sizeof( opus_int16 ) ) */
         /* Update states */
         psLPC_Q14++;
         *psLPC_Q14 = silk_LSHIFT( xq_Q10, 4 );
@@ -343,7 +345,7 @@ static inline void silk_noise_shape_quantizer(
         NSQ->sLF_AR_shp_Q12 = silk_LSHIFT( sLF_AR_shp_Q10, 2 );
 
         NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx ] = silk_SUB32( sLF_AR_shp_Q10, n_LF_Q10 );
-        sLTP_Q16[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q10, 6 );
+        sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q10, 5 );
         NSQ->sLTP_shp_buf_idx++;
         NSQ->sLTP_buf_idx++;
 
@@ -358,10 +360,10 @@ static inline void silk_noise_shape_quantizer(
 static inline void silk_nsq_scale_states(
     const silk_encoder_state *psEncC,           /* I    Encoder State                   */
     silk_nsq_state      *NSQ,                   /* I/O  NSQ state                       */
-    const opus_int16    x[],                    /* I    input in Q0                     */
+    const opus_int32    x_Q10[],                /* I    input in Q0                     */
     opus_int32          x_sc_Q10[],             /* O    input scaled with 1/Gain        */
     const opus_int16    sLTP[],                 /* I    re-whitened LTP state in Q0     */
-    opus_int32          sLTP_Q16[],             /* O    LTP state matching scaled input */
+    opus_int32          sLTP_Q15[],             /* O    LTP state matching scaled input */
     opus_int            subfr,                  /* I    subframe number                 */
     const opus_int      LTP_scale_Q14,          /* I                                    */
     const opus_int32    Gains_Q16[ MAX_NB_SUBFR ], /* I                                 */
@@ -370,22 +372,21 @@ static inline void silk_nsq_scale_states(
 )
 {
     opus_int   i, lag;
-    opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32;
+    opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q31;
 
     inv_gain_Q16 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 32 );
-    inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX );
     lag          = pitchL[ subfr ];
 
     /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
     if( NSQ->rewhite_flag ) {
-        inv_gain_Q32 = silk_LSHIFT( inv_gain_Q16, 16 );
+        inv_gain_Q31 = silk_LSHIFT( inv_gain_Q16, 15 );
         if( subfr == 0 ) {
             /* Do LTP downscaling */
-            inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 );
+            inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
         }
         for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
             silk_assert( i < MAX_FRAME_LENGTH );
-            sLTP_Q16[ i ] = silk_SMULWB( inv_gain_Q32, sLTP[ i ] );
+            sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
         }
     }
 
@@ -401,7 +402,7 @@ static inline void silk_nsq_scale_states(
         /* Scale long-term prediction state */
         if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
             for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
-                sLTP_Q16[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] );
+                sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
             }
         }
 
@@ -418,10 +419,10 @@ static inline void silk_nsq_scale_states(
 
     /* Scale input */
     for( i = 0; i < psEncC->subfr_length; i++ ) {
-        x_sc_Q10[ i ] = silk_RSHIFT( silk_SMULBB( x[ i ], ( opus_int16 )inv_gain_Q16 ), 6 );
+        x_sc_Q10[ i ] = silk_SMULWW( x_Q10[ i ], inv_gain_Q16 );
     }
 
-    /* save inv_gain */
+    /* Save inv_gain */
     silk_assert( inv_gain_Q16 != 0 );
     NSQ->prev_inv_gain_Q16 = inv_gain_Q16;
 }
index 4917ddb..48d413b 100644 (file)
@@ -32,7 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "main.h"
 
 typedef struct {
-    opus_int32 sLPC_Q14[ MAX_FRAME_LENGTH / MAX_NB_SUBFR + NSQ_LPC_BUF_LENGTH ];
+    opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
     opus_int32 RandState[ DECISION_DELAY ];
     opus_int32 Q_Q10[     DECISION_DELAY ];
     opus_int32 Xq_Q10[    DECISION_DELAY ];
@@ -58,10 +58,10 @@ static inline void silk_nsq_del_dec_scale_states(
     const silk_encoder_state *psEncC,               /* I    Encoder State                       */
     silk_nsq_state      *NSQ,                       /* I/O  NSQ state                           */
     NSQ_del_dec_struct  psDelDec[],                 /* I/O  Delayed decision states             */
-    const opus_int16    x[],                        /* I    Input in Q0                         */
+    const opus_int32    x_Q10[],                    /* I    Input in Q0                         */
     opus_int32          x_sc_Q10[],                 /* O    Input scaled with 1/Gain in Q10     */
     const opus_int16    sLTP[],                     /* I    Re-whitened LTP state in Q0         */
-    opus_int32          sLTP_Q16[],                 /* O    LTP state matching scaled input     */
+    opus_int32          sLTP_Q15[],                 /* O    LTP state matching scaled input     */
     opus_int            subfr,                      /* I    Subframe number                     */
     opus_int            nStatesDelayedDecision,     /* I    Number of del dec states            */
     const opus_int      LTP_scale_Q14,              /* I    LTP state scaling                   */
@@ -81,7 +81,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
     const opus_int32    x_Q10[],                /* I                                        */
     opus_int8           pulses[],               /* O                                        */
     opus_int16          xq[],                   /* O                                        */
-    opus_int32          sLTP_Q16[],             /* I/O  LTP filter state                    */
+    opus_int32          sLTP_Q15[],             /* I/O  LTP filter state                    */
     opus_int32          delayedGain_Q16[],      /* I/O  Gain delay buffer                   */
     const opus_int16    a_Q12[],                /* I    Short term prediction coefs         */
     const opus_int16    b_Q14[],                /* I    Long term prediction coefs          */
@@ -107,7 +107,7 @@ void silk_NSQ_del_dec(
     const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
-    const opus_int16            x[],                                        /* I    Prefiltered input signal        */
+    const opus_int32            x_Q10[],                                    /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
@@ -121,19 +121,19 @@ void silk_NSQ_del_dec(
     const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
 )
 {
-    opus_int     i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
-    opus_int     last_smple_idx, smpl_buf_idx, decisionDelay;
-    const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
-    opus_int16   *pxq;
-    opus_int32   sLTP_Q16[ 2 * MAX_FRAME_LENGTH ];
-    opus_int16   sLTP[     2 * MAX_FRAME_LENGTH ];
-    opus_int32   HarmShapeFIRPacked_Q14;
-    opus_int     offset_Q10;
-    opus_int32   RDmin_Q10;
-    opus_int32   x_sc_Q10[ MAX_SUB_FRAME_LENGTH ];
-    opus_int32   delayedGain_Q16[  DECISION_DELAY ];
-    NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ];
-    NSQ_del_dec_struct *psDD;
+    opus_int            i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
+    opus_int            last_smple_idx, smpl_buf_idx, decisionDelay;
+    const opus_int16   *A_Q12, *B_Q14, *AR_shp_Q13;
+    opus_int16          *pxq;
+    opus_int32          sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
+    opus_int16          sLTP[     2 * MAX_FRAME_LENGTH ];
+    opus_int32          HarmShapeFIRPacked_Q14;
+    opus_int            offset_Q10;
+    opus_int32          RDmin_Q10;
+    opus_int32          x_sc_Q10[ MAX_SUB_FRAME_LENGTH ];
+    opus_int32          delayedGain_Q16[  DECISION_DELAY ];
+    NSQ_del_dec_struct  psDelDec[ MAX_DEL_DEC_STATES ];
+    NSQ_del_dec_struct  *psDD;
 
     /* Set unvoiced lag to the previous one, overwrite later for voiced */
     lag = NSQ->lagPrev;
@@ -175,7 +175,7 @@ void silk_NSQ_del_dec(
         LSF_interpolation_flag = 1;
     }
 
-    /* Setup pointers to start of sub frame */
+    /* Set up pointers to start of sub frame */
     pxq                   = &NSQ->xq[ psEncC->ltp_mem_length ];
     NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
     NSQ->sLTP_buf_idx     = psEncC->ltp_mem_length;
@@ -188,7 +188,7 @@ void silk_NSQ_del_dec(
         /* Noise shape parameters */
         silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
         HarmShapeFIRPacked_Q14  =                          silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
-        HarmShapeFIRPacked_Q14 |= silk_LSHIFT( ( opus_int32 )silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
+        HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
 
         NSQ->rewhite_flag = 0;
         if( psIndices->signalType == TYPE_VOICED ) {
@@ -220,8 +220,8 @@ void silk_NSQ_del_dec(
                     last_smple_idx = smpl_buf_idx + decisionDelay;
                     for( i = 0; i < decisionDelay; i++ ) {
                         last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
-                        pulses[   i - decisionDelay ] = ( opus_int8 )silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
-                        pxq[ i - decisionDelay ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND(
+                        pulses[   i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
+                        pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
                             silk_SMULWW( psDD->Xq_Q10[ last_smple_idx ], Gains_Q16[ 1 ] ), 10 ) );
                         NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ];
                     }
@@ -241,15 +241,15 @@ void silk_NSQ_del_dec(
             }
         }
 
-        silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x, x_sc_Q10, sLTP, sLTP_Q16, k,
+        silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q10, x_sc_Q10, sLTP, sLTP_Q15, k,
             psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
 
-        silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q16,
+        silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
             delayedGain_Q16, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ],
             Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
             psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
 
-        x      += psEncC->subfr_length;
+        x_Q10  += psEncC->subfr_length;
         pulses += psEncC->subfr_length;
         pxq    += psEncC->subfr_length;
     }
@@ -270,8 +270,8 @@ void silk_NSQ_del_dec(
     last_smple_idx = smpl_buf_idx + decisionDelay;
     for( i = 0; i < decisionDelay; i++ ) {
         last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
-        pulses[   i - decisionDelay ] = ( opus_int8 )silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
-        pxq[ i - decisionDelay ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND(
+        pulses[   i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
+        pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
             silk_SMULWW( psDD->Xq_Q10[ last_smple_idx ], Gains_Q16[ psEncC->nb_subfr - 1 ] ), 10 ) );
         NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ];
     }
@@ -282,7 +282,8 @@ void silk_NSQ_del_dec(
     NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12;
     NSQ->lagPrev        = pitchL[ psEncC->nb_subfr - 1 ];
 
-    /* Save quantized speech and noise shaping signals */
+    /* Save quantized speech signal */
+    /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
     silk_memmove( NSQ->xq,           &NSQ->xq[           psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
     silk_memmove( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
 }
@@ -297,7 +298,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
     const opus_int32    x_Q10[],                /* I                                        */
     opus_int8           pulses[],               /* O                                        */
     opus_int16          xq[],                   /* O                                        */
-    opus_int32          sLTP_Q16[],             /* I/O  LTP filter state                    */
+    opus_int32          sLTP_Q15[],             /* I/O  LTP filter state                    */
     opus_int32          delayedGain_Q16[],      /* I/O  Gain delay buffer                   */
     const opus_int16    a_Q12[],                /* I    Short term prediction coefs         */
     const opus_int16    b_Q14[],                /* I    Long term prediction coefs          */
@@ -321,7 +322,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
 {
     opus_int     i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
     opus_int32   Winner_rand_state;
-    opus_int32   LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14, LTP_Q10;
+    opus_int32   LTP_pred_Q13, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14, LTP_Q10;
     opus_int32   n_LF_Q10, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
     opus_int32   q1_Q10, q2_Q10, dither, exc_Q10, LPC_exc_Q10, xq_Q10;
     opus_int32   tmp1, tmp2, sLF_AR_shp_Q10;
@@ -333,7 +334,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
     silk_assert( nStatesDelayedDecision > 0 );
 
     shp_lag_ptr  = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
-    pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+    pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
 
     for( i = 0; i < length; i++ ) {
         /* Perform common calculations used in all states */
@@ -341,25 +342,25 @@ static inline void silk_noise_shape_quantizer_del_dec(
         /* Long-term prediction */
         if( signalType == TYPE_VOICED ) {
             /* Unrolled loop */
-            LTP_pred_Q14 = silk_SMULWB(               pred_lag_ptr[  0 ], b_Q14[ 0 ] );
-            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
-            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
-            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
-            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
+            LTP_pred_Q13 = silk_SMULWB(               pred_lag_ptr[  0 ], b_Q14[ 0 ] );
+            LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
+            LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
+            LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
+            LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
             pred_lag_ptr++;
         } else {
-            LTP_pred_Q14 = 0;
+            LTP_pred_Q13 = 0;
         }
 
         /* Long-term shaping */
         if( lag > 0 ) {
             /* Symmetric, packed FIR coefficients */
             n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
-            n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ],                     HarmShapeFIRPacked_Q14 );
+            n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ],                      HarmShapeFIRPacked_Q14 );
             n_LTP_Q14 = silk_LSHIFT( n_LTP_Q14, 6 );
             shp_lag_ptr++;
 
-            LTP_Q10 = silk_RSHIFT( silk_SUB32( LTP_pred_Q14, n_LTP_Q14 ), 4 );
+            LTP_Q10 = silk_RSHIFT( silk_SUB32( LTP_pred_Q13 << 1, n_LTP_Q14 ), 4 );
         } else {
             LTP_Q10 = 0;
         }
@@ -380,10 +381,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
             /* Pointer used in short term prediction and shaping */
             psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
             /* Short-term prediction */
-            silk_assert( predictLPCOrder >= 10 );            /* check that unrolling works */
-            silk_assert( ( predictLPCOrder  & 1 ) == 0 );    /* check that order is even */
-            silk_assert( ( (opus_int64)a_Q12 & 3 ) == 0 );    /* check that array starts at 4-byte aligned address */
-            /* Partially unrolled */
+            silk_assert( predictLPCOrder == 10 || predictLPCOrder == 16 );
             LPC_pred_Q10 = silk_SMULWB(               psLPC_Q14[  0 ], a_Q12[ 0 ] );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
@@ -394,8 +392,13 @@ static inline void silk_noise_shape_quantizer_del_dec(
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
-            for( j = 10; j < predictLPCOrder; j ++ ) {
-                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] );
+            if( predictLPCOrder == 16 ) {
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -10 ], a_Q12[ 10 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -11 ], a_Q12[ 11 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -12 ], a_Q12[ 12 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -13 ], a_Q12[ 13 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -14 ], a_Q12[ 14 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -15 ], a_Q12[ 15 ] );
             }
 
             /* Noise shape feedback */
@@ -486,7 +489,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
             exc_Q10 = psSS[ 0 ].Q_Q10 ^ dither;
 
             /* Add predictions */
-            LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q14, 4 );
+            LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q13, 3 );
             xq_Q10      = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
 
             /* Update states */
@@ -502,7 +505,7 @@ static inline void silk_noise_shape_quantizer_del_dec(
             exc_Q10 = psSS[ 1 ].Q_Q10 ^ dither;
 
             /* Add predictions */
-            LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q14, 4 );
+            LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q13, 3 );
             xq_Q10      = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
 
             /* Update states */
@@ -564,11 +567,11 @@ static inline void silk_noise_shape_quantizer_del_dec(
         /* Write samples from winner to output and long-term filter states */
         psDD = &psDelDec[ Winner_ind ];
         if( subfr > 0 || i >= decisionDelay ) {
-            pulses[  i - decisionDelay ] = ( opus_int8 )silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
-            xq[ i - decisionDelay ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND(
+            pulses[  i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
+            xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
                 silk_SMULWW( psDD->Xq_Q10[ last_smple_idx ], delayedGain_Q16[ last_smple_idx ] ), 10 ) );
             NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q10[ last_smple_idx ];
-            sLTP_Q16[          NSQ->sLTP_buf_idx     - decisionDelay ] = psDD->Pred_Q16[  last_smple_idx ];
+            sLTP_Q15[          NSQ->sLTP_buf_idx     - decisionDelay ] = psDD->Pred_Q16[  last_smple_idx ] >> 1;
         }
         NSQ->sLTP_shp_buf_idx++;
         NSQ->sLTP_buf_idx++;
@@ -600,10 +603,10 @@ static inline void silk_nsq_del_dec_scale_states(
     const silk_encoder_state *psEncC,               /* I    Encoder State                       */
     silk_nsq_state      *NSQ,                       /* I/O  NSQ state                           */
     NSQ_del_dec_struct  psDelDec[],                 /* I/O  Delayed decision states             */
-    const opus_int16    x[],                        /* I    Input in Q0                         */
+    const opus_int32    x_Q10[],                    /* I    Input in Q0                         */
     opus_int32          x_sc_Q10[],                 /* O    Input scaled with 1/Gain in Q10     */
     const opus_int16    sLTP[],                     /* I    Re-whitened LTP state in Q0         */
-    opus_int32          sLTP_Q16[],                 /* O    LTP state matching scaled input     */
+    opus_int32          sLTP_Q15[],                 /* O    LTP state matching scaled input     */
     opus_int            subfr,                      /* I    Subframe number                     */
     opus_int            nStatesDelayedDecision,     /* I    Number of del dec states            */
     const opus_int      LTP_scale_Q14,              /* I    LTP state scaling                   */
@@ -614,23 +617,22 @@ static inline void silk_nsq_del_dec_scale_states(
 )
 {
     opus_int            i, k, lag;
-    opus_int32          inv_gain_Q16, gain_adj_Q16, inv_gain_Q32;
-    NSQ_del_dec_struct *psDD;
+    opus_int32          inv_gain_Q16, gain_adj_Q16, inv_gain_Q31;
+    NSQ_del_dec_struct  *psDD;
 
     inv_gain_Q16 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 32 );
-    inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX );
     lag          = pitchL[ subfr ];
 
     /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
     if( NSQ->rewhite_flag ) {
-        inv_gain_Q32 = silk_LSHIFT( inv_gain_Q16, 16 );
+        inv_gain_Q31 = silk_LSHIFT( inv_gain_Q16, 15 );
         if( subfr == 0 ) {
             /* Do LTP downscaling */
-            inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 );
+            inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
         }
         for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
             silk_assert( i < MAX_FRAME_LENGTH );
-            sLTP_Q16[ i ] = silk_SMULWB( inv_gain_Q32, sLTP[ i ] );
+            sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
         }
     }
 
@@ -646,7 +648,7 @@ static inline void silk_nsq_del_dec_scale_states(
         /* Scale long-term prediction state */
         if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
             for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
-                sLTP_Q16[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] );
+                sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
             }
         }
 
@@ -672,7 +674,7 @@ static inline void silk_nsq_del_dec_scale_states(
 
     /* Scale input */
     for( i = 0; i < psEncC->subfr_length; i++ ) {
-        x_sc_Q10[ i ] = silk_RSHIFT( silk_SMULBB( x[ i ], ( opus_int16 )inv_gain_Q16 ), 6 );
+        x_sc_Q10[ i ] = silk_SMULWW( x_Q10[ i ], inv_gain_Q16 );
     }
 
     /* save inv_gain */
index 0ba921f..b76032a 100644 (file)
@@ -192,7 +192,7 @@ static inline void silk_PLC_conceal(
     exc_buf_ptr = exc_buf;
     for( k = 0; k < 2; k++ ) {
         for( i = 0; i < psPLC->subfr_length; i++ ) {
-            exc_buf_ptr[ i ] = ( opus_int16 )silk_RSHIFT(
+            exc_buf_ptr[ i ] = (opus_int16)silk_RSHIFT(
                 silk_SMULWW( psDec->exc_Q10[ i + ( k + psPLC->nb_subfr - 2 ) * psPLC->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 );
         }
         exc_buf_ptr += psPLC->subfr_length;
@@ -209,11 +209,11 @@ static inline void silk_PLC_conceal(
         rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
     }
 
-    /* Setup Gain to random noise component */
+    /* Set up Gain to random noise component */
     B_Q14          = psPLC->LTPCoef_Q14;
     rand_scale_Q14 = psPLC->randScale_Q14;
 
-    /* Setup attenuation gains */
+    /* Set up attenuation gains */
     harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
     if( psDec->prevSignalType == TYPE_VOICED ) {
         rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[  silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
@@ -237,12 +237,12 @@ static inline void silk_PLC_conceal(
                 rand_scale_Q14 -= B_Q14[ i ];
             }
             rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
-            rand_scale_Q14 = ( opus_int16 )silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
+            rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
         } else {
             /* Reduce random noise for unvoiced frames with high LPC gain */
             opus_int32 invGain_Q30, down_scale_Q30;
 
-            silk_LPC_inverse_pred_gain( &invGain_Q30, psPLC->prevLPC_Q12, psDec->LPC_order );
+            invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order );
 
             down_scale_Q30 = silk_min_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
             down_scale_Q30 = silk_max_32( silk_RSHIFT( 1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
@@ -272,7 +272,7 @@ static inline void silk_PLC_conceal(
     /* LTP synthesis filtering */
     /***************************/
     for( k = 0; k < psDec->nb_subfr; k++ ) {
-        /* Setup pointer */
+        /* Set up pointer */
         pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
         for( i = 0; i < psDec->subfr_length; i++ ) {
             /* Unrolled loop */
@@ -334,7 +334,7 @@ static inline void silk_PLC_conceal(
         sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
 
         /* Scale with Gain */
-        frame[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], psPLC->prevGain_Q16[ 1 ] ), 14 ) );
+        frame[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], psPLC->prevGain_Q16[ 1 ] ), 14 ) );
     }
 
     /* Save LPC state */
index 5be504f..6233fa6 100644 (file)
@@ -25,8 +25,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/
 
-#ifndef SILK_PLC_FIX_H
-#define SILK_PLC_FIX_H
+#ifndef SILK_PLC_H
+#define SILK_PLC_H
 
 #include "main.h"
 
index 6a4e3f4..02d9b78 100644 (file)
@@ -52,19 +52,20 @@ extern "C"
  * Initialize/reset the resampler state for a given pair of input/output sampling rates
 */
 opus_int silk_resampler_init(
-    silk_resampler_state_struct *S,                 /* I/O   Resampler state                                            */
-    opus_int32                  Fs_Hz_in,           /* I     Input sampling rate (Hz)                                   */
-    opus_int32                  Fs_Hz_out           /* I     Output sampling rate (Hz)                                  */
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int32                  Fs_Hz_in,           /* I    Input sampling rate (Hz)                                    */
+    opus_int32                  Fs_Hz_out,          /* I    Output sampling rate (Hz)                                   */
+    opus_int                    forEnc              /* I    If 1: encoder; if 0: decoder                                */
 );
 
 /*!
  * Resampler: convert from one sampling rate to another
  */
 opus_int silk_resampler(
-    silk_resampler_state_struct *S,                 /* I/O   Resampler state                                            */
-    opus_int16                  out[],              /* O     Output signal                                              */
-    const opus_int16            in[],               /* I     Input signal                                               */
-    opus_int32                  inLen               /* I     Number of input samples                                    */
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int16                  out[],              /* O    Output signal                                               */
+    const opus_int16            in[],               /* I    Input signal                                                */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
 );
 
 /*!
@@ -127,15 +128,14 @@ void silk_bwexpander_32(
 
 /* Compute inverse of LPC prediction gain, and                           */
 /* test if LPC coefficients are stable (all poles within unit circle)    */
-opus_int silk_LPC_inverse_pred_gain(                /* O   Returns 1 if unstable, otherwise 0                           */
-    opus_int32                  *invGain_Q30,       /* O   Inverse prediction gain, Q30 energy domain                   */
+opus_int32 silk_LPC_inverse_pred_gain(              /* O   Returns inverse prediction gain in energy domain, Q30        */
     const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
     const opus_int              order               /* I   Prediction order                                             */
 );
 
-opus_int silk_LPC_inverse_pred_gain_Q24(            /* O    Returns 1 if unstable, otherwise 0                          */
-    opus_int32                  *invGain_Q30,       /* O    Inverse prediction gain, Q30 energy domain                  */
-    const opus_int32            *A_Q24,             /* I    Prediction coefficients, Q24 [order]                        */
+/* For input in Q24 domain */
+opus_int32 silk_LPC_inverse_pred_gain_Q24(          /* O    Returns inverse prediction gain in energy domain, Q30       */
+    const opus_int32            *A_Q24,             /* I    Prediction coefficients [order]                             */
     const opus_int              order               /* I    Prediction order                                            */
 );
 
@@ -313,9 +313,9 @@ void silk_burg_modified(
     opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
     opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
     const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
     const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceeding samples)   */
     const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
-    const opus_int32            WhiteNoiseFrac_Q32, /* I    Fraction added to zero-lag autocorrelation                  */
     const opus_int              D                   /* I    Order                                                       */
 );
 
@@ -388,9 +388,9 @@ static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
 #endif
 
 /* Useful Macros that can be adjusted to other platforms */
-#define silk_memcpy(a, b, c)                memcpy((a), (b), (c))    /* Dest, Src, ByteCount    */
-#define silk_memset(a, b, c)                memset((a), (b), (c))    /* Dest, value, ByteCount  */
-#define silk_memmove(a, b, c)               memmove((a), (b), (c))   /* Dest, Src, ByteCount    */
+#define silk_memcpy(dest, src, size)        memcpy((dest), (src), (size))
+#define silk_memset(dest, src, size)        memset((dest), (src), (size))
+#define silk_memmove(dest, src, size)       memmove((dest), (src), (size))
 
 /* Fixed point macros */
 
index 1f7e564..d88db82 100644 (file)
@@ -204,7 +204,7 @@ opus_int silk_VAD_GetSA_Q8(                                     /* O    Return v
     sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
 
     /* Root-mean-square approximation, scale to dBs, and write to output pointer */
-    pSNR_dB_Q7 = ( opus_int16 )( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
+    pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
 
     /*********************************/
     /* Speech Probability Estimation */
index 829b08f..16666d6 100644 (file)
@@ -38,13 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #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(
     silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
     opus_int                        fs_kHz              /* I                        */
@@ -150,7 +143,7 @@ opus_int silk_setup_resamplers(
     {
         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 ];
@@ -168,7 +161,7 @@ opus_int silk_setup_resamplers(
 #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 );
+            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 );
@@ -177,7 +170,7 @@ opus_int silk_setup_resamplers(
             nSamples_temp = silk_DIV32_16( nSamples_temp * psEnc->sCmn.API_fs_Hz, silk_SMULBB( psEnc->sCmn.fs_kHz, 1000 ) );
 
             /* 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 );
@@ -234,9 +227,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 );
@@ -336,7 +326,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 +337,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 +348,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 );
index 9fe62d9..c456a6d 100644 (file)
@@ -83,9 +83,9 @@ opus_int silk_Decode(                                   /* O    Returns error co
     opus_int32                      *nSamplesOut        /* O    Number of samples decoded                       */
 )
 {
-    opus_int   i, n, delay, decode_only_middle = 0, ret = SILK_NO_ERROR;
+    opus_int   i, n, decode_only_middle = 0, ret = SILK_NO_ERROR;
     opus_int32 nSamplesOutDec, LBRR_symbol;
-    opus_int16 samplesOut1_tmp[ 2 ][ MAX_FS_KHZ * MAX_FRAME_LENGTH_MS + 2 + MAX_DECODER_DELAY ];
+    opus_int16 samplesOut1_tmp[ 2 ][ MAX_FS_KHZ * MAX_FRAME_LENGTH_MS + 2 ];
     opus_int16 samplesOut2_tmp[ MAX_API_FS_KHZ * MAX_FRAME_LENGTH_MS ];
     opus_int32 MS_pred_Q13[ 2 ] = { 0 };
     opus_int16 *resample_out_ptr;
@@ -139,13 +139,10 @@ opus_int silk_Decode(                                   /* O    Returns error co
         }
     }
 
-    delay = channel_state[ 0 ].delay;
-
     if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 && ( psDec->nChannelsAPI == 1 || psDec->nChannelsInternal == 1 ) ) {
         silk_memset( psDec->sStereo.pred_prev_Q13, 0, sizeof( psDec->sStereo.pred_prev_Q13 ) );
         silk_memset( psDec->sStereo.sSide, 0, sizeof( psDec->sStereo.sSide ) );
         silk_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) );
-        silk_memcpy( &channel_state[ 1 ].delayBuf, &channel_state[ 0 ].delayBuf, sizeof(channel_state[ 0 ].delayBuf));
     }
     psDec->nChannelsAPI      = decControl->nChannelsAPI;
     psDec->nChannelsInternal = decControl->nChannelsInternal;
@@ -264,20 +261,20 @@ opus_int silk_Decode(                                   /* O    Returns error co
             } else {
                 condCoding = CODE_CONDITIONALLY;
             }
-            ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 + delay ], &nSamplesOutDec, lostFlag, condCoding);
+            ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag, condCoding);
         } else {
-            silk_memset( &samplesOut1_tmp[ n ][ 2 + delay ], 0, nSamplesOutDec * sizeof( opus_int16 ) );
+            silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) );
         }
         channel_state[ n ].nFramesDecoded++;
     }
 
     if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
         /* Convert Mid/Side to Left/Right */
-        silk_stereo_MS_to_LR( &psDec->sStereo, &samplesOut1_tmp[ 0 ][ delay ], &samplesOut1_tmp[ 1 ][ delay ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec );
+        silk_stereo_MS_to_LR( &psDec->sStereo, samplesOut1_tmp[ 0 ], samplesOut1_tmp[ 1 ], MS_pred_Q13, channel_state[ 0 ].fs_kHz, nSamplesOutDec );
     } else {
         /* Buffering */
-        silk_memcpy( &samplesOut1_tmp[ 0 ][ delay ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) );
-        silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec + delay ], 2 * sizeof( opus_int16 ) );
+        silk_memcpy( samplesOut1_tmp[ 0 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) );
+        silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) );
     }
 
     /* Number of output samples */
@@ -292,10 +289,8 @@ opus_int silk_Decode(                                   /* O    Returns error co
 
     for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) {
 
-        silk_memcpy(&samplesOut1_tmp[ n ][ 1 ], &channel_state[ n ].delayBuf[ MAX_DECODER_DELAY - delay ], delay * sizeof(opus_int16));
         /* Resample decoded signal to API_sampleRate */
         ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
-        silk_memcpy(channel_state[ n ].delayBuf, &samplesOut1_tmp[ n ][ 1 + nSamplesOutDec + delay - MAX_DECODER_DELAY ], MAX_DECODER_DELAY * sizeof(opus_int16));
 
         /* Interleave if stereo output and stereo stream */
         if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
index 9a4c9f3..6633143 100644 (file)
@@ -41,11 +41,11 @@ void silk_decode_core(
     const opus_int              pulses[ MAX_FRAME_LENGTH ]      /* I    Pulse signal                                */
 )
 {
-    opus_int   i, j, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
+    opus_int   i, k, lag = 0, start_idx, sLTP_buf_idx, NLSF_interpolation_flag, signalType;
     opus_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
     opus_int16 sLTP[ MAX_FRAME_LENGTH ];
-    opus_int32 sLTP_Q16[ 2 * MAX_FRAME_LENGTH ];
-    opus_int32 LTP_pred_Q14, LPC_pred_Q10, Gain_Q10, inv_gain_Q16, inv_gain_Q32, gain_adj_Q16, rand_seed, offset_Q10;
+    opus_int32 sLTP_Q15[ 2 * MAX_FRAME_LENGTH ];
+    opus_int32 LTP_pred_Q13, LPC_pred_Q10, Gain_Q10, inv_gain_Q16, inv_gain_Q31, gain_adj_Q16, rand_seed, offset_Q10;
     opus_int32 *pred_lag_ptr, *pexc_Q10, *pres_Q10;
     opus_int32 res_Q10[ MAX_SUB_FRAME_LENGTH ];
     opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
@@ -64,7 +64,7 @@ void silk_decode_core(
     rand_seed = psDec->indices.Seed;
     for( i = 0; i < psDec->frame_length; i++ ) {
         rand_seed = silk_RAND( rand_seed );
-        psDec->exc_Q10[ i ] = silk_LSHIFT( ( opus_int32 )pulses[ i ], 10 );
+        psDec->exc_Q10[ i ] = silk_LSHIFT( (opus_int32)pulses[ i ], 10 );
         if( psDec->exc_Q10[ i ] > 0 ) {
             psDec->exc_Q10[ i ] -= QUANT_LEVEL_ADJUST_Q10;
         } else
@@ -95,7 +95,6 @@ void silk_decode_core(
 
         Gain_Q10     = silk_RSHIFT( psDecCtrl->Gains_Q16[ k ], 6 );
         inv_gain_Q16 = silk_INVERSE32_varQ( psDecCtrl->Gains_Q16[ k ], 32 );
-        inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX );
 
         /* Calculate Gain adjustment factor */
         gain_adj_Q16 = 1 << 16;
@@ -141,19 +140,19 @@ void silk_decode_core(
                     A_Q12, psDec->ltp_mem_length - start_idx, psDec->LPC_order );
 
                 /* After rewhitening the LTP state is unscaled */
-                inv_gain_Q32 = silk_LSHIFT( inv_gain_Q16, 16 );
+                inv_gain_Q31 = silk_LSHIFT( inv_gain_Q16, 15 );
                 if( k == 0 ) {
                     /* Do LTP downscaling to reduce inter-packet dependency */
-                    inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, psDecCtrl->LTP_scale_Q14 ), 2 );
+                    inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, psDecCtrl->LTP_scale_Q14 ), 2 );
                 }
                 for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
-                    sLTP_Q16[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q32, sLTP[ psDec->ltp_mem_length - i - 1 ] );
+                    sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q31, sLTP[ psDec->ltp_mem_length - i - 1 ] );
                 }
             } else {
                 /* Update LTP state when Gain changes */
                 if( gain_adj_Q16 != 1 << 16 ) {
                     for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
-                        sLTP_Q16[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q16[ sLTP_buf_idx - i - 1 ] );
+                        sLTP_Q15[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ sLTP_buf_idx - i - 1 ] );
                     }
                 }
             }
@@ -161,22 +160,22 @@ void silk_decode_core(
 
         /* Long-term prediction */
         if( signalType == TYPE_VOICED ) {
-            /* Setup pointer */
-            pred_lag_ptr = &sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+            /* Set up pointer */
+            pred_lag_ptr = &sLTP_Q15[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
             for( i = 0; i < psDec->subfr_length; i++ ) {
                 /* Unrolled loop */
-                LTP_pred_Q14 = silk_SMULWB(               pred_lag_ptr[  0 ], B_Q14[ 0 ] );
-                LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
-                LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
-                LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
-                LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
+                LTP_pred_Q13 = silk_SMULWB(               pred_lag_ptr[  0 ], B_Q14[ 0 ] );
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
+                LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
                 pred_lag_ptr++;
 
                 /* Generate LPC excitation */
-                pres_Q10[ i ] = silk_ADD32( pexc_Q10[ i ], silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ) );
+                pres_Q10[ i ] = silk_ADD32( pexc_Q10[ i ], silk_RSHIFT_ROUND( LTP_pred_Q13, 3 ) );
 
                 /* Update states */
-                sLTP_Q16[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q10[ i ], 6 );
+                sLTP_Q15[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q10[ i ], 5 );
                 sLTP_buf_idx++;
             }
         } else {
@@ -184,7 +183,8 @@ void silk_decode_core(
         }
 
         for( i = 0; i < psDec->subfr_length; i++ ) {
-            /* Partially unrolled */
+            /* Short-term prediction */
+            silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
             LPC_pred_Q10 = silk_SMULWB(               sLPC_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12_tmp[ 0 ] );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  2 ], A_Q12_tmp[ 1 ] );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  3 ], A_Q12_tmp[ 2 ] );
@@ -195,17 +195,23 @@ void silk_decode_core(
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  8 ], A_Q12_tmp[ 7 ] );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i -  9 ], A_Q12_tmp[ 8 ] );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp[ 9 ] );
-            for( j = 10; j < psDec->LPC_order; j++ ) {
-                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] );
+            if( psDec->LPC_order == 16 ) {
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12_tmp[ 10 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12_tmp[ 11 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12_tmp[ 12 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12_tmp[ 13 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12_tmp[ 14 ] );
+                LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12_tmp[ 15 ] );
             }
 
             /* Add prediction to LPC excitation */
             sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_LSHIFT( silk_ADD32( pres_Q10[ i ], LPC_pred_Q10 ), 4 );
 
             /* Scale with Gain */
-            pxq[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
+            pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
         }
 
+        /* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */
         /* Update LPC filter state */
         silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
         pexc_Q10 += psDec->subfr_length;
index 6c69cfa..c972805 100644 (file)
@@ -72,8 +72,7 @@ void silk_decode_parameters(
         silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order );
     } else {
         /* Copy LPC coefficients for first half from second half */
-        silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ],
-            psDec->LPC_order * sizeof( opus_int16 ) );
+        silk_memcpy( psDecCtrl->PredCoef_Q12[ 0 ], psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
     }
 
     silk_memcpy( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) );
index 5579b20..8c012d3 100644 (file)
@@ -31,13 +31,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "main.h"
 
-static const int dec_delay_matrix[3][5] = {
-/*SILK API 8  12  16  24  48 */
-/* 8 */   {3, 0, 2, 0, 0},
-/*12 */   {0, 8, 5, 7, 5},
-/*16 */   {0, 0, 8, 5, 5}
-};
-
 /* Set decoder sampling rate */
 opus_int silk_decoder_set_fs(
     silk_decoder_state          *psDec,                         /* I/O  Decoder state pointer                       */
@@ -60,13 +53,9 @@ opus_int silk_decoder_set_fs(
         opus_int16 temp_buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ];
         silk_resampler_state_struct  temp_resampler_state;
 
-        /* New delay value */
-        psDec->delay = dec_delay_matrix[ rateID( silk_SMULBB( fs_kHz, 1000 ) ) ][ rateID( fs_API_Hz ) ];
-        silk_assert( psDec->delay <= MAX_DECODER_DELAY );
-
         if( psDec->fs_kHz != fs_kHz && psDec->fs_kHz > 0 ) {
             /* Initialize resampler for temporary resampling of outBuf data to the new internal sampling rate */
-            ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psDec->fs_kHz, 1000 ), silk_SMULBB( fs_kHz, 1000 ) );
+            ret += silk_resampler_init( &temp_resampler_state, silk_SMULBB( psDec->fs_kHz, 1000 ), silk_SMULBB( fs_kHz, 1000 ), 0 );
 
             /* Temporary resampling of outBuf data to the new internal sampling rate */
             silk_memcpy( temp_buf, psDec->outBuf, psDec->frame_length * sizeof( opus_int16 ) );
@@ -74,7 +63,7 @@ opus_int silk_decoder_set_fs(
         }
 
         /* Initialize the resampler for dec_API.c preparing resampling from fs_kHz to API_fs_Hz */
-        ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz );
+        ret += silk_resampler_init( &psDec->resampler_state, silk_SMULBB( fs_kHz, 1000 ), fs_API_Hz, 0 );
 
         /* Correct resampler state by resampling buffered data from fs_kHz to API_fs_Hz */
         ret += silk_resampler( &psDec->resampler_state, temp_buf, psDec->outBuf, frame_length );
index dcfdee9..fe2a659 100644 (file)
@@ -91,9 +91,6 @@ extern "C"
 #define MAX_FRAME_LENGTH_MS                     ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR )
 #define MAX_FRAME_LENGTH                        ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ )
 
-#define MAX_ENCODER_DELAY                       18
-#define MAX_DECODER_DELAY                       8
-
 /* Milliseconds of lookahead for pitch analysis */
 #define LA_PITCH_MS                             2
 #define LA_PITCH_MAX                            ( LA_PITCH_MS * MAX_FS_KHZ )
@@ -133,7 +130,9 @@ extern "C"
 #define QUANT_LEVEL_ADJUST_Q10                  80
 
 /* Maximum numbers of iterations used to stabilize a LPC vector */
-#define MAX_LPC_STABILIZE_ITERATIONS            20
+#define MAX_LPC_STABILIZE_ITERATIONS            30
+#define MAX_PREDICTION_POWER_GAIN               1e4f
+#define MAX_PREDICTION_POWER_GAIN_AFTER_RESET   1e2f
 
 #define MAX_LPC_ORDER                           16
 #define MIN_LPC_ORDER                           10
index 02a8fd0..b993ed5 100644 (file)
@@ -140,10 +140,10 @@ opus_int silk_Encode(                                   /* O    Returns error co
     opus_int   n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0;
     opus_int   nSamplesToBuffer, nBlocksOf10ms, nSamplesFromInput = 0;
     opus_int   speech_act_thr_for_switch_Q8;
-    opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol;
+    opus_int32 TargetRate_bps, MStargetRates_bps[ 2 ], channelRate_bps, LBRR_symbol, sum;
     silk_encoder *psEnc = ( silk_encoder * )encState;
-    opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ + MAX_ENCODER_DELAY];
-    opus_int transition, delay, curr_block, tot_blocks;
+    opus_int16 buf[ MAX_FRAME_LENGTH_MS * MAX_API_FS_KHZ ];
+    opus_int transition, curr_block, tot_blocks;
 
     psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0;
 
@@ -233,7 +233,6 @@ opus_int silk_Encode(                                   /* O    Returns error co
     }
     silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
 
-    delay = psEnc->state_Fxx[ 0 ].sCmn.delay;
     /* Input buffering/resampling and encoding */
     while( 1 ) {
         nSamplesToBuffer  = psEnc->state_Fxx[ 0 ].sCmn.frame_length - psEnc->state_Fxx[ 0 ].sCmn.inputBufIx;
@@ -243,15 +242,12 @@ opus_int silk_Encode(                                   /* O    Returns error co
         if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 2 ) {
             opus_int id = psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded;
             for( n = 0; n < nSamplesFromInput; n++ ) {
-                buf[ n+delay ] = samplesIn[ 2 * n ];
+                buf[ n ] = samplesIn[ 2 * n ];
             }
-            silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ MAX_ENCODER_DELAY - delay ], delay * sizeof(opus_int16));
             /* Making sure to start both resamplers from the same state when switching from mono to stereo */
-            if(psEnc->nPrevChannelsInternal == 1 && id==0) {
+            if( psEnc->nPrevChannelsInternal == 1 && id==0 ) {
                silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state, &psEnc->state_Fxx[ 0 ].sCmn.resampler_state, sizeof(psEnc->state_Fxx[ 1 ].sCmn.resampler_state));
-               silk_memcpy( &psEnc->state_Fxx[ 1 ].sCmn.delayBuf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf, MAX_ENCODER_DELAY*sizeof(opus_int16));
             }
-            silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf + nSamplesFromInput + delay - MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16));
 
             ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
                 &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
@@ -260,25 +256,18 @@ opus_int silk_Encode(                                   /* O    Returns error co
             nSamplesToBuffer  = psEnc->state_Fxx[ 1 ].sCmn.frame_length - psEnc->state_Fxx[ 1 ].sCmn.inputBufIx;
             nSamplesToBuffer  = silk_min( nSamplesToBuffer, 10 * nBlocksOf10ms * psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
             for( n = 0; n < nSamplesFromInput; n++ ) {
-                buf[ n + delay ] = samplesIn[ 2 * n + 1 ];
+                buf[ n ] = samplesIn[ 2 * n + 1 ];
             }
-            silk_memcpy(buf, &psEnc->state_Fxx[ 1 ].sCmn.delayBuf[ MAX_ENCODER_DELAY - delay ], delay * sizeof(opus_int16));
             ret += silk_resampler( &psEnc->state_Fxx[ 1 ].sCmn.resampler_state,
                 &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
-            silk_memcpy(psEnc->state_Fxx[ 1 ].sCmn.delayBuf, buf + nSamplesFromInput + delay - MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16));
 
             psEnc->state_Fxx[ 1 ].sCmn.inputBufIx += nSamplesToBuffer;
         } else if( encControl->nChannelsAPI == 2 && encControl->nChannelsInternal == 1 ) {
             /* Combine left and right channels before resampling */
             for( n = 0; n < nSamplesFromInput; n++ ) {
-                buf[ n + delay ] = (opus_int16)silk_RSHIFT_ROUND( samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ],  1 );
+                sum = samplesIn[ 2 * n ] + samplesIn[ 2 * n + 1 ];
+                buf[ n ] = (opus_int16)silk_RSHIFT_ROUND( sum,  1 );
             }
-            if(psEnc->nPrevChannelsInternal == 2 && psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded==0) {
-               for( n = 0; n<MAX_ENCODER_DELAY; n++ ) {
-                  psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ n ] = silk_RSHIFT(psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ n ]+(opus_int32)psEnc->state_Fxx[ 1 ].sCmn.delayBuf[ n ], 1);
-               }
-            }
-            silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ MAX_ENCODER_DELAY - delay ], delay * sizeof(opus_int16));
             ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
                 &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
             /* On the first mono frame, average the results for the two resampler states  */
@@ -291,15 +280,12 @@ opus_int silk_Encode(                                   /* O    Returns error co
                                   + psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ psEnc->state_Fxx[ 1 ].sCmn.inputBufIx+n+2 ], 1);
                }
             }
-            silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf + nSamplesFromInput + delay - MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16));
             psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
         } else {
             silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
-            silk_memcpy(buf + delay, samplesIn, nSamplesFromInput*sizeof(opus_int16));
-            silk_memcpy(buf, &psEnc->state_Fxx[ 0 ].sCmn.delayBuf[ MAX_ENCODER_DELAY - delay ], delay * sizeof(opus_int16));
+            silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16));
             ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
                 &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
-            silk_memcpy(psEnc->state_Fxx[ 0 ].sCmn.delayBuf, buf + nSamplesFromInput + delay - MAX_ENCODER_DELAY, MAX_ENCODER_DELAY*sizeof(opus_int16));
             psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
         }
 
index aad7b6e..33257f8 100644 (file)
@@ -69,7 +69,7 @@ void silk_LTP_analysis_filter_FIX(
             LTP_est = silk_RSHIFT_ROUND( LTP_est, 14 ); /* round and -> Q0*/
 
             /* Subtract long-term prediction */
-            LTP_res_ptr[ i ] = ( opus_int16 )silk_SAT16( ( opus_int32 )x_ptr[ i ] - LTP_est );
+            LTP_res_ptr[ i ] = (opus_int16)silk_SAT16( (opus_int32)x_ptr[ i ] - LTP_est );
 
             /* Scale residual */
             LTP_res_ptr[ i ] = silk_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] );
index 0f347e3..0aace53 100644 (file)
@@ -40,16 +40,11 @@ void silk_LTP_scale_ctrl_FIX(
 {
     opus_int round_loss;
 
-    /* 1st order high-pass filter */
-    psEnc->HPLTPredCodGain_Q7 = silk_max_int( psEncCtrl->LTPredCodGain_Q7 - silk_RSHIFT( psEnc->prevLTPredCodGain_Q7, 1 ), 0 )
-        + silk_RSHIFT( psEnc->HPLTPredCodGain_Q7, 1 );
-    psEnc->prevLTPredCodGain_Q7 = psEncCtrl->LTPredCodGain_Q7;
-
-    /* Only scale if first frame in packet */
     if( condCoding == CODE_INDEPENDENTLY ) {
-        round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket - 1;
+        /* Only scale if first frame in packet */
+        round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket;
         psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT(
-            silk_SMULWB( silk_SMULBB( round_loss, psEnc->HPLTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 );
+            silk_SMULWB( silk_SMULBB( round_loss, psEncCtrl->LTPredCodGain_Q7 ), SILK_FIX_CONST( 0.1, 9 ) ), 0, 2 );
     } else {
         /* Default is minimum scaling */
         psEnc->sCmn.indices.LTP_scaleIndex = 0;
index 69d8761..fc82d36 100644 (file)
@@ -30,9 +30,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endif
 
 #include "SigProc_FIX.h"
+#include "define.h"
+#include "tuning_parameters.h"
 
 #define MAX_FRAME_SIZE              384             /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */
-#define MAX_NB_SUBFR                4
 
 #define QA                          25
 #define N_BITS_HEAD_ROOM            2
@@ -45,26 +46,22 @@ void silk_burg_modified(
     opus_int                    *res_nrg_Q,         /* O    Residual energy Q value                                     */
     opus_int32                  A_Q16[],            /* O    Prediction coefficients (length order)                      */
     const opus_int16            x[],                /* I    Input signal, length: nb_subfr * ( D + subfr_length )       */
+    const opus_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
     const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceeding samples)   */
     const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
-    const opus_int32            WhiteNoiseFrac_Q32, /* I    Fraction added to zero-lag autocorrelation                  */
     const opus_int              D                   /* I    Order                                                       */
 )
 {
-    opus_int         k, n, s, lz, rshifts, rshifts_extra;
-    opus_int32       C0, num, nrg, rc_Q31, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
+    opus_int         k, n, s, lz, rshifts, rshifts_extra, reached_max_gain;
+    opus_int32       C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
     const opus_int16 *x_ptr;
-
     opus_int32       C_first_row[ SILK_MAX_ORDER_LPC ];
     opus_int32       C_last_row[  SILK_MAX_ORDER_LPC ];
     opus_int32       Af_QA[       SILK_MAX_ORDER_LPC ];
-
     opus_int32       CAf[ SILK_MAX_ORDER_LPC + 1 ];
     opus_int32       CAb[ SILK_MAX_ORDER_LPC + 1 ];
 
     silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
-    silk_assert( nb_subfr <= MAX_NB_SUBFR );
-
 
     /* Compute autocorrelations, added over subframes */
     silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
@@ -84,6 +81,7 @@ void silk_burg_modified(
         }
         rshifts += rshifts_extra;
     }
+    CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1;                                /* Q(-rshifts) */
     silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) );
     if( rshifts > 0 ) {
         for( s = 0; s < nb_subfr; s++ ) {
@@ -105,8 +103,10 @@ void silk_burg_modified(
     silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) );
 
     /* Initialize */
-    CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( WhiteNoiseFrac_Q32, C0 ) + 1;                                /* Q(-rshifts)*/
+    CAb[ 0 ] = CAf[ 0 ] = C0 + silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ) + 1;                                /* Q(-rshifts) */
 
+    invGain_Q30 = 1 << 30;
+    reached_max_gain = 0;
     for( n = 0; n < D; n++ ) {
         /* Update first row of correlation matrix (without first element) */
         /* Update last row of correlation matrix (without last element, stored in reversed order) */
@@ -115,108 +115,155 @@ void silk_burg_modified(
         if( rshifts > -2 ) {
             for( s = 0; s < nb_subfr; s++ ) {
                 x_ptr = x + s * subfr_length;
-                x1  = -silk_LSHIFT32( (opus_int32)x_ptr[ n ],                    16 - rshifts );        /* Q(16-rshifts)*/
-                x2  = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts );        /* Q(16-rshifts)*/
-                tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ],                    QA - 16 );             /* Q(QA-16)*/
-                tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 );             /* Q(QA-16)*/
+                x1  = -silk_LSHIFT32( (opus_int32)x_ptr[ n ],                    16 - rshifts );        /* Q(16-rshifts) */
+                x2  = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 16 - rshifts );        /* Q(16-rshifts) */
+                tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ],                    QA - 16 );             /* Q(QA-16) */
+                tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], QA - 16 );             /* Q(QA-16) */
                 for( k = 0; k < n; k++ ) {
-                    C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ]            ); /* Q( -rshifts )*/
-                    C_last_row[ k ]  = silk_SMLAWB( C_last_row[ k ],  x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts )*/
+                    C_first_row[ k ] = silk_SMLAWB( C_first_row[ k ], x1, x_ptr[ n - k - 1 ]            ); /* Q( -rshifts ) */
+                    C_last_row[ k ]  = silk_SMLAWB( C_last_row[ k ],  x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */
                     Atmp_QA = Af_QA[ k ];
-                    tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ]            );                 /* Q(QA-16)*/
-                    tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] );                 /* Q(QA-16)*/
+                    tmp1 = silk_SMLAWB( tmp1, Atmp_QA, x_ptr[ n - k - 1 ]            );                 /* Q(QA-16) */
+                    tmp2 = silk_SMLAWB( tmp2, Atmp_QA, x_ptr[ subfr_length - n + k ] );                 /* Q(QA-16) */
                 }
-                tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts );                                       /* Q(16-rshifts)*/
-                tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts );                                       /* Q(16-rshifts)*/
+                tmp1 = silk_LSHIFT32( -tmp1, 32 - QA - rshifts );                                       /* Q(16-rshifts) */
+                tmp2 = silk_LSHIFT32( -tmp2, 32 - QA - rshifts );                                       /* Q(16-rshifts) */
                 for( k = 0; k <= n; k++ ) {
-                    CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ]                    );        /* Q( -rshift )*/
-                    CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] );        /* Q( -rshift )*/
+                    CAf[ k ] = silk_SMLAWB( CAf[ k ], tmp1, x_ptr[ n - k ]                    );        /* Q( -rshift ) */
+                    CAb[ k ] = silk_SMLAWB( CAb[ k ], tmp2, x_ptr[ subfr_length - n + k - 1 ] );        /* Q( -rshift ) */
                 }
             }
         } else {
             for( s = 0; s < nb_subfr; s++ ) {
                 x_ptr = x + s * subfr_length;
-                x1  = -silk_LSHIFT32( (opus_int32)x_ptr[ n ],                    -rshifts );            /* Q( -rshifts )*/
-                x2  = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts );            /* Q( -rshifts )*/
-                tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ],                    17 );                  /* Q17*/
-                tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 );                  /* Q17*/
+                x1  = -silk_LSHIFT32( (opus_int32)x_ptr[ n ],                    -rshifts );            /* Q( -rshifts ) */
+                x2  = -silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], -rshifts );            /* Q( -rshifts ) */
+                tmp1 = silk_LSHIFT32( (opus_int32)x_ptr[ n ],                    17 );                  /* Q17 */
+                tmp2 = silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n - 1 ], 17 );                  /* Q17 */
                 for( k = 0; k < n; k++ ) {
-                    C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ]            ); /* Q( -rshifts )*/
-                    C_last_row[ k ]  = silk_MLA( C_last_row[ k ],  x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts )*/
-                    Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 );                                   /* Q17*/
-                    tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ],            Atmp1 );                      /* Q17*/
-                    tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 );                      /* Q17*/
+                    C_first_row[ k ] = silk_MLA( C_first_row[ k ], x1, x_ptr[ n - k - 1 ]            ); /* Q( -rshifts ) */
+                    C_last_row[ k ]  = silk_MLA( C_last_row[ k ],  x2, x_ptr[ subfr_length - n + k ] ); /* Q( -rshifts ) */
+                    Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 17 );                                   /* Q17 */
+                    tmp1 = silk_MLA( tmp1, x_ptr[ n - k - 1 ],            Atmp1 );                      /* Q17 */
+                    tmp2 = silk_MLA( tmp2, x_ptr[ subfr_length - n + k ], Atmp1 );                      /* Q17 */
                 }
-                tmp1 = -tmp1;                                                                           /* Q17*/
-                tmp2 = -tmp2;                                                                           /* Q17*/
+                tmp1 = -tmp1;                                                                           /* Q17 */
+                tmp2 = -tmp2;                                                                           /* Q17 */
                 for( k = 0; k <= n; k++ ) {
                     CAf[ k ] = silk_SMLAWW( CAf[ k ], tmp1,
-                        silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) );                    /* Q( -rshift )*/
+                        silk_LSHIFT32( (opus_int32)x_ptr[ n - k ], -rshifts - 1 ) );                    /* Q( -rshift ) */
                     CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2,
-                        silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift )*/
+                        silk_LSHIFT32( (opus_int32)x_ptr[ subfr_length - n + k - 1 ], -rshifts - 1 ) ); /* Q( -rshift ) */
                 }
             }
         }
 
         /* Calculate nominator and denominator for the next order reflection (parcor) coefficient */
-        tmp1 = C_first_row[ n ];                                                                        /* Q( -rshifts )*/
-        tmp2 = C_last_row[ n ];                                                                         /* Q( -rshifts )*/
-        num  = 0;                                                                                       /* Q( -rshifts )*/
-        nrg  = silk_ADD32( CAb[ 0 ], CAf[ 0 ] );                                                        /* Q( 1-rshifts )*/
+        tmp1 = C_first_row[ n ];                                                                        /* Q( -rshifts ) */
+        tmp2 = C_last_row[ n ];                                                                         /* Q( -rshifts ) */
+        num  = 0;                                                                                       /* Q( -rshifts ) */
+        nrg  = silk_ADD32( CAb[ 0 ], CAf[ 0 ] );                                                        /* Q( 1-rshifts ) */
         for( k = 0; k < n; k++ ) {
             Atmp_QA = Af_QA[ k ];
             lz = silk_CLZ32( silk_abs( Atmp_QA ) ) - 1;
             lz = silk_min( 32 - QA, lz );
-            Atmp1 = silk_LSHIFT32( Atmp_QA, lz );                                                       /* Q( QA + lz )*/
+            Atmp1 = silk_LSHIFT32( Atmp_QA, lz );                                                       /* Q( QA + lz ) */
 
-            tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[  n - k - 1 ], Atmp1 ), 32 - QA - lz );  /* Q( -rshifts )*/
-            tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz );  /* Q( -rshifts )*/
-            num  = silk_ADD_LSHIFT32( num,  silk_SMMUL( CAb[ n - k ],             Atmp1 ), 32 - QA - lz );  /* Q( -rshifts )*/
+            tmp1 = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( C_last_row[  n - k - 1 ], Atmp1 ), 32 - QA - lz );  /* Q( -rshifts ) */
+            tmp2 = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( C_first_row[ n - k - 1 ], Atmp1 ), 32 - QA - lz );  /* Q( -rshifts ) */
+            num  = silk_ADD_LSHIFT32( num,  silk_SMMUL( CAb[ n - k ],             Atmp1 ), 32 - QA - lz );  /* Q( -rshifts ) */
             nrg  = silk_ADD_LSHIFT32( nrg,  silk_SMMUL( silk_ADD32( CAb[ k + 1 ], CAf[ k + 1 ] ),
-                                                                                Atmp1 ), 32 - QA - lz );    /* Q( 1-rshifts )*/
+                                                                                Atmp1 ), 32 - QA - lz );    /* Q( 1-rshifts ) */
         }
-        CAf[ n + 1 ] = tmp1;                                                                            /* Q( -rshifts )*/
-        CAb[ n + 1 ] = tmp2;                                                                            /* Q( -rshifts )*/
-        num = silk_ADD32( num, tmp2 );                                                                  /* Q( -rshifts )*/
-        num = silk_LSHIFT32( -num, 1 );                                                                 /* Q( 1-rshifts )*/
+        CAf[ n + 1 ] = tmp1;                                                                            /* Q( -rshifts ) */
+        CAb[ n + 1 ] = tmp2;                                                                            /* Q( -rshifts ) */
+        num = silk_ADD32( num, tmp2 );                                                                  /* Q( -rshifts ) */
+        num = silk_LSHIFT32( -num, 1 );                                                                 /* Q( 1-rshifts ) */
 
         /* Calculate the next order reflection (parcor) coefficient */
         if( silk_abs( num ) < nrg ) {
             rc_Q31 = silk_DIV32_varQ( num, nrg, 31 );
         } else {
-            /* Negative energy or ratio too high; set remaining coefficients to zero and exit loop */
-            silk_memset( &Af_QA[ n ], 0, ( D - n ) * sizeof( opus_int32 ) );
-            silk_assert( 0 );
-            break;
+            rc_Q31 = ( num > 0 ) ? silk_int32_MAX : silk_int32_MIN;
+        }
+
+        /* Update inverse prediction gain */
+        tmp1 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+        tmp1 = silk_LSHIFT( silk_SMMUL( invGain_Q30, tmp1 ), 2 );
+        if( tmp1 <= minInvGain_Q30 ) {
+            /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */
+            tmp2 = ( 1 << 30 ) - silk_DIV32_varQ( minInvGain_Q30, invGain_Q30, 30 );            /* Q30 */
+            rc_Q31 = silk_SQRT_APPROX( tmp2 );                                                  /* Q15 */
+            /* Newton-Raphson iteration */
+            rc_Q31 = silk_RSHIFT32( rc_Q31 + silk_DIV32( tmp2, rc_Q31 ), 1 );                   /* Q15 */
+            rc_Q31 = silk_LSHIFT32( rc_Q31, 16 );                                               /* Q31 */
+            if( num < 0 ) {
+                /* Ensure adjusted reflection coefficients has the original sign */
+                rc_Q31 = -rc_Q31;
+            }
+            invGain_Q30 = minInvGain_Q30;
+            reached_max_gain = 1;
+        } else {
+            invGain_Q30 = tmp1;
         }
 
         /* Update the AR coefficients */
         for( k = 0; k < (n + 1) >> 1; k++ ) {
-            tmp1 = Af_QA[ k ];                                                                  /* QA*/
-            tmp2 = Af_QA[ n - k - 1 ];                                                          /* QA*/
-            Af_QA[ k ]         = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 );      /* QA*/
-            Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 );      /* QA*/
+            tmp1 = Af_QA[ k ];                                                                  /* QA */
+            tmp2 = Af_QA[ n - k - 1 ];                                                          /* QA */
+            Af_QA[ k ]         = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 );      /* QA */
+            Af_QA[ n - k - 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 );      /* QA */
+        }
+        Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA );                                          /* QA */
+
+        if( reached_max_gain ) {
+            /* Reached max prediction gain; set remaining coefficients to zero and exit loop */
+            for( k = n + 1; k < D; k++ ) {
+                Af_QA[ k ] = 0;
+            }
+            break;
         }
-        Af_QA[ n ] = silk_RSHIFT32( rc_Q31, 31 - QA );                                          /* QA*/
 
         /* Update C * Af and C * Ab */
         for( k = 0; k <= n + 1; k++ ) {
-            tmp1 = CAf[ k ];                                                                    /* Q( -rshifts )*/
-            tmp2 = CAb[ n - k + 1 ];                                                            /* Q( -rshifts )*/
-            CAf[ k ]         = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 );        /* Q( -rshifts )*/
-            CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 );        /* Q( -rshifts )*/
+            tmp1 = CAf[ k ];                                                                    /* Q( -rshifts ) */
+            tmp2 = CAb[ n - k + 1 ];                                                            /* Q( -rshifts ) */
+            CAf[ k ]         = silk_ADD_LSHIFT32( tmp1, silk_SMMUL( tmp2, rc_Q31 ), 1 );        /* Q( -rshifts ) */
+            CAb[ n - k + 1 ] = silk_ADD_LSHIFT32( tmp2, silk_SMMUL( tmp1, rc_Q31 ), 1 );        /* Q( -rshifts ) */
         }
     }
 
-    /* Return residual energy */
-    nrg  = CAf[ 0 ];                                                                            /* Q( -rshifts )*/
-    tmp1 = 1 << 16;                                                                             /* Q16*/
-    for( k = 0; k < D; k++ ) {
-        Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 );                                       /* Q16*/
-        nrg  = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 );                                         /* Q( -rshifts )*/
-        tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 );                                               /* Q16*/
-        A_Q16[ k ] = -Atmp1;
-    }
-    *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( WhiteNoiseFrac_Q32, C0 ), -tmp1 );                 /* Q( -rshifts )*/
-    *res_nrg_Q = -rshifts;
+    if( reached_max_gain ) {
+        for( k = 0; k < D; k++ ) {
+            /* Scale coefficients */
+            A_Q16[ k ] = -silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 );
+        }
+        /* Subtract energy of preceeding samples from C0 */
+        if( rshifts > 0 ) {
+            for( s = 0; s < nb_subfr; s++ ) {
+                x_ptr = x + s * subfr_length;
+                C0 -= (opus_int32)silk_RSHIFT64( silk_inner_prod16_aligned_64( x_ptr, x_ptr, D ), rshifts );
+            }
+        } else {
+            for( s = 0; s < nb_subfr; s++ ) {
+                x_ptr = x + s * subfr_length;
+                C0 -= silk_LSHIFT32( silk_inner_prod_aligned( x_ptr, x_ptr, D ), -rshifts );
+            }
+        }
+        /* Approximate residual energy */
+        *res_nrg = silk_LSHIFT( silk_SMMUL( invGain_Q30, C0 ), 2 );
+        *res_nrg_Q = -rshifts;
+    } else {
+        /* Return residual energy */
+        nrg  = CAf[ 0 ];                                                                            /* Q( -rshifts ) */
+        tmp1 = 1 << 16;                                                                             /* Q16 */
+        for( k = 0; k < D; k++ ) {
+            Atmp1 = silk_RSHIFT_ROUND( Af_QA[ k ], QA - 16 );                                       /* Q16 */
+            nrg  = silk_SMLAWW( nrg, CAf[ k + 1 ], Atmp1 );                                         /* Q( -rshifts ) */
+            tmp1 = silk_SMLAWW( tmp1, Atmp1, Atmp1 );                                               /* Q16 */
+            A_Q16[ k ] = -Atmp1;
+        }
+        *res_nrg = silk_SMLAWW( nrg, silk_SMMUL( FIND_LPC_COND_FAC, C0 ), -tmp1 );                  /* Q( -rshifts ) */
+        *res_nrg_Q = -rshifts;
+    }   
 }
index 855abdf..11b9c69 100644 (file)
@@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 static inline void silk_LBRR_encode_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
-    const opus_int16                xfw[],                                  /* I    Input signal                                                                */
+    const opus_int32                xfw_Q10[],                              /* I    Input signal                                                                */
     opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
 );
 
@@ -85,7 +85,7 @@ opus_int silk_encode_frame_FIX(
     silk_encoder_control_FIX sEncCtrl;
     opus_int     i, iter, maxIter, found_upper, found_lower, ret = 0;
     opus_int16   *x_frame, *res_pitch_frame;
-    opus_int16   xfw[ MAX_FRAME_LENGTH ];
+    opus_int32   xfw_Q10[ MAX_FRAME_LENGTH ];
     opus_int16   res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
     ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
     silk_nsq_state sNSQ_copy, sNSQ_copy2;
@@ -103,7 +103,7 @@ opus_int silk_encode_frame_FIX(
     psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
 
     /**************************************************************/
-    /* Setup Input Pointers, and insert frame in input buffer    */
+    /* Set up Input Pointers, and insert frame in input buffer   */
     /*************************************************************/
     /* pointers aligned with start of frame to encode */
     x_frame         = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;    /* start of frame to encode */
@@ -143,15 +143,15 @@ opus_int silk_encode_frame_FIX(
         /*****************************************/
         /* Prefiltering for noise shaper         */
         /*****************************************/
-        silk_prefilter_FIX( psEnc, &sEncCtrl, xfw, x_frame );
+        silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q10, x_frame );
 
         /****************************************/
         /* Low Bitrate Redundant Encoding       */
         /****************************************/
-        silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw, condCoding );
+        silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q10, condCoding );
 
         /* Loop over quantizer and entropy coding to control bitrate */
-        maxIter = 5;
+        maxIter = 6;
         gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
         found_lower = 0;
         found_upper = 0;
@@ -183,11 +183,11 @@ opus_int silk_encode_frame_FIX(
                 /* Noise shaping quantization            */
                 /*****************************************/
                 if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
-                    silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
+                    silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q10, psEnc->sCmn.pulses,
                            sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
                            sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
                 } else {
-                    silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw, psEnc->sCmn.pulses,
+                    silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q10, psEnc->sCmn.pulses,
                             sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
                             sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14 );
                 }
@@ -316,7 +316,7 @@ opus_int silk_encode_frame_FIX(
 static inline void silk_LBRR_encode_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
-    const opus_int16                xfw[],                                  /* I    Input signal                                                                */
+    const opus_int32                xfw_Q10[],                              /* I    Input signal                                                                */
     opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
 )
 {
@@ -355,12 +355,12 @@ static inline void silk_LBRR_encode_FIX(
         /* Noise shaping quantization            */
         /*****************************************/
         if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
-            silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw,
+            silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q10,
                 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
                 psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
                 psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 );
         } else {
-            silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw,
+            silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q10,
                 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
                 psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
                 psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14 );
index 4619273..ba52fa2 100644 (file)
@@ -34,18 +34,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /* Finds LPC vector from correlations, and converts to NLSF */
 void silk_find_LPC_FIX(
+    silk_encoder_state              *psEncC,                                /* I/O  Encoder state                                                               */
     opus_int16                      NLSF_Q15[],                             /* O    NLSFs                                                                       */
-    opus_int8                       *interpIndex,                           /* O    NLSF interpolation index, only used for NLSF interpolation                  */
-    const opus_int16                prev_NLSFq_Q15[],                       /* I    previous NLSFs, only used for NLSF interpolation                            */
-    const opus_int                  useInterpNLSFs,                         /* I    Flag                                                                        */
-    const opus_int                  firstFrameAfterReset,                   /* I    Flag                                                                        */
-    const opus_int                  LPC_order,                              /* I    LPC order                                                                   */
     const opus_int16                x[],                                    /* I    Input signal                                                                */
-    const opus_int                  subfr_length,                           /* I    Input signal subframe length including preceeding samples                   */
-    const opus_int                  nb_subfr                                /* I    Number of subframes                                                         */
+    const opus_int32                minInvGain_Q30                          /* I    Inverse of max prediction gain                                              */
 )
 {
-    opus_int     k;
+    opus_int     k, subfr_length;
     opus_int32   a_Q16[ MAX_LPC_ORDER ];
     opus_int     isInterpLower, shift;
     opus_int32   res_nrg0, res_nrg1;
@@ -56,27 +51,19 @@ void silk_find_LPC_FIX(
     opus_int     res_nrg_interp_Q, res_nrg_Q, res_tmp_nrg_Q;
     opus_int16   a_tmp_Q12[ MAX_LPC_ORDER ];
     opus_int16   NLSF0_Q15[ MAX_LPC_ORDER ];
-    opus_int16   LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ];
+    opus_int16   LPC_res[ MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ];
+
+    subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder;
 
     /* Default: no interpolation */
-    *interpIndex = 4;
+    psEncC->indices.NLSFInterpCoef_Q2 = 4;
 
     /* Burg AR analysis for the full frame */
-    silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, subfr_length, nb_subfr, SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order );
-
-    if( firstFrameAfterReset ) {
-        silk_bwexpander_32( a_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP_FIRST_FRAME, 16 ) );
-    } else {
-        silk_bwexpander_32( a_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) );
-    }
-
-    if( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) {
+    silk_burg_modified( &res_nrg, &res_nrg_Q, a_Q16, x, minInvGain_Q30, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder );
 
+    if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) {
         /* Optimal solution for last 10 ms */
-        silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + ( MAX_NB_SUBFR >> 1 ) * subfr_length,
-            subfr_length, ( MAX_NB_SUBFR >> 1 ), SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), LPC_order );
-
-        silk_bwexpander_32( a_tmp_Q16, LPC_order, SILK_FIX_CONST( FIND_LPC_CHIRP, 16 ) );
+        silk_burg_modified( &res_tmp_nrg, &res_tmp_nrg_Q, a_tmp_Q16, x + 2 * subfr_length, minInvGain_Q30, subfr_length, 2, psEncC->predictLPCOrder );
 
         /* subtract residual energy here, as that's easier than adding it to the    */
         /* residual energy of the first 10 ms in each iteration of the search below */
@@ -92,21 +79,21 @@ void silk_find_LPC_FIX(
         }
 
         /* Convert to NLSFs */
-        silk_A2NLSF( NLSF_Q15, a_tmp_Q16, LPC_order );
+        silk_A2NLSF( NLSF_Q15, a_tmp_Q16, psEncC->predictLPCOrder );
 
         /* Search over interpolation indices to find the one with lowest residual energy */
         for( k = 3; k >= 0; k-- ) {
             /* Interpolate NLSFs for first half */
-            silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order );
+            silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
 
             /* Convert to LPC for residual energy evaluation */
-            silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, LPC_order );
+            silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder );
 
             /* Calculate residual energy with NLSF interpolation */
-            silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, LPC_order );
+            silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder );
 
-            silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + LPC_order,                subfr_length - LPC_order );
-            silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + LPC_order + subfr_length, subfr_length - LPC_order );
+            silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder,                subfr_length - psEncC->predictLPCOrder );
+            silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder );
 
             /* Add subframe energies from first half frame */
             shift = rshift0 - rshift1;
@@ -144,15 +131,15 @@ void silk_find_LPC_FIX(
                 /* Interpolation has lower residual energy */
                 res_nrg   = res_nrg_interp;
                 res_nrg_Q = res_nrg_interp_Q;
-                *interpIndex = (opus_int8)k;
+                psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k;
             }
         }
     }
 
-    if( *interpIndex == 4 ) {
+    if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) {
         /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */
-        silk_A2NLSF( NLSF_Q15, a_Q16, LPC_order );
+        silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder );
     }
 
-    silk_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) );
+    silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
 }
index daa3fef..078d84c 100644 (file)
@@ -113,7 +113,7 @@ void silk_find_LTP_FIX(
             silk_RSHIFT( silk_SMULWB( subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts );    /* Q( -corr_rshifts[ k ] + extra_shifts ) */
         denom32 = silk_max( denom32, 1 );
         silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX );                       /* Wght always < 0.5 in Q0 */
-        temp32 = silk_DIV32( silk_LSHIFT( ( opus_int32 )Wght_Q15[ k ], 16 ), denom32 );           /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */
+        temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 );             /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */
         temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 );               /* Q26 */
 
         /* Limit temp such that the below scaling never wraps around */
@@ -124,7 +124,7 @@ void silk_find_LTP_FIX(
         lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */
         silk_assert( 26 - 18 + lshift >= 0 );
         if( 26 - 18 + lshift < 31 ) {
-            temp32 = silk_min_32( temp32, silk_LSHIFT( ( opus_int32 )1, 26 - 18 + lshift ) );
+            temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) );
         }
 
         silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */
@@ -216,16 +216,16 @@ void silk_find_LTP_FIX(
             silk_DIV32(
                 SILK_FIX_CONST( LTP_SMOOTHING, 26 ),
                 silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ),                          /* Q10 */
-            silk_LSHIFT_SAT32( silk_SUB_SAT32( ( opus_int32 )m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) );  /* Q16 */
+            silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) );    /* Q16 */
 
         temp32 = 0;
         for( i = 0; i < LTP_ORDER; i++ ) {
-            delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 );  /* 1638_Q14 = 0.1_Q0 */
-            temp32 += delta_b_Q14[ i ];                          /* Q14 */
+            delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 );     /* 1638_Q14 = 0.1_Q0 */
+            temp32 += delta_b_Q14[ i ];                                 /* Q14 */
         }
-        temp32 = silk_DIV32( g_Q26, temp32 ); /* Q14->Q12 */
+        temp32 = silk_DIV32( g_Q26, temp32 );                           /* Q14 -> Q12 */
         for( i = 0; i < LTP_ORDER; i++ ) {
-            b_Q14_ptr[ i ] = silk_LIMIT_32( ( opus_int32 )b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 );
+            b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 );
         }
         b_Q14_ptr += LTP_ORDER;
     }
@@ -239,6 +239,6 @@ void silk_fit_LTP(
     opus_int i;
 
     for( i = 0; i < LTP_ORDER; i++ ) {
-        LTP_coefs_Q14[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) );
+        LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) );
     }
 }
index 0f41158..a830cdf 100644 (file)
@@ -50,7 +50,7 @@ void silk_find_pitch_lags_FIX(
     opus_int16 A_Q12[     MAX_FIND_PITCH_LPC_ORDER ];
 
     /******************************************/
-    /* Setup buffer lengths etc based on Fs   */
+    /* Set up buffer lengths etc based on Fs  */
     /******************************************/
     buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
 
@@ -97,7 +97,7 @@ void silk_find_pitch_lags_FIX(
 
     /* Convert From 32 bit Q24 to 16 bit Q12 coefs */
     for( i = 0; i < psEnc->sCmn.pitchEstimationLPCOrder; i++ ) {
-        A_Q12[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT( A_Q24[ i ], 12 ) );
+        A_Q12[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( A_Q24[ i ], 12 ) );
     }
 
     /* Do BWE */
@@ -122,7 +122,7 @@ void silk_find_pitch_lags_FIX(
         /*****************************************/
         if( silk_pitch_analysis_core( res, psEncCtrl->pitchL, &psEnc->sCmn.indices.lagIndex, &psEnc->sCmn.indices.contourIndex,
                 &psEnc->LTPCorr_Q15, psEnc->sCmn.prevLag, psEnc->sCmn.pitchEstimationThreshold_Q16,
-                ( opus_int16 )thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 )
+                (opus_int16)thrhld_Q15, psEnc->sCmn.fs_kHz, psEnc->sCmn.pitchEstimationComplexity, psEnc->sCmn.nb_subfr ) == 0 )
         {
             psEnc->sCmn.indices.signalType = TYPE_VOICED;
         } else {
index 27e0c2c..5f67e63 100644 (file)
@@ -45,7 +45,7 @@ void silk_find_pred_coefs_FIX(
     opus_int16       NLSF_Q15[ MAX_LPC_ORDER ];
     const opus_int16 *x_ptr;
     opus_int16       *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
-    opus_int32       tmp, min_gain_Q16;
+    opus_int32       tmp, min_gain_Q16, minInvGain_Q30;
     opus_int         LTP_corrs_rshift[ MAX_NB_SUBFR ];
 
     /* weighting for weighted least squares */
@@ -111,10 +111,18 @@ void silk_find_pred_coefs_FIX(
         psEncCtrl->LTPredCodGain_Q7 = 0;
     }
 
+    /* Limit on total predictive coding gain */
+    if( psEnc->sCmn.first_frame_after_reset ) {
+        minInvGain_Q30 = SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET, 30 );
+    } else {        
+        minInvGain_Q30 = silk_log2lin( silk_SMLAWB( 16 << 7, psEncCtrl->LTPredCodGain_Q7, SILK_FIX_CONST( 1.0 / 3, 16 ) ) );      /* Q16 */
+        minInvGain_Q30 = silk_DIV32_varQ( minInvGain_Q30, 
+            silk_SMULWW( SILK_FIX_CONST( MAX_PREDICTION_POWER_GAIN, 0 ), 
+                silk_SMLAWB( SILK_FIX_CONST( 0.1, 18 ), SILK_FIX_CONST( 0.9, 18 ), psEncCtrl->coding_quality_Q14 ) ), 14 );
+    }
+
     /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */
-    silk_find_LPC_FIX( NLSF_Q15, &psEnc->sCmn.indices.NLSFInterpCoef_Q2, psEnc->sCmn.prev_NLSFq_Q15,
-        psEnc->sCmn.useInterpolatedNLSFs, psEnc->sCmn.first_frame_after_reset, psEnc->sCmn.predictLPCOrder,
-        LPC_in_pre, psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder, psEnc->sCmn.nb_subfr );
+    silk_find_LPC_FIX( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain_Q30 );
 
     /* Quantize LSFs */
     silk_process_NLSFs( &psEnc->sCmn, psEncCtrl->PredCoef_Q12, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 );
index 30782e1..9f17897 100644 (file)
@@ -92,7 +92,7 @@ opus_int silk_control_encoder(
 void silk_prefilter_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state                                                               */
     const silk_encoder_control_FIX  *psEncCtrl,                             /* I    Encoder control                                                             */
-    opus_int16                      xw[],                                   /* O    Weighted signal                                                             */
+    opus_int32                      xw_Q10[],                               /* O    Weighted signal                                                             */
     const opus_int16                x[]                                     /* I    Speech signal                                                               */
 );
 
@@ -146,15 +146,10 @@ void silk_find_pred_coefs_FIX(
 
 /* LPC analysis */
 void silk_find_LPC_FIX(
+    silk_encoder_state              *psEncC,                                /* I/O  Encoder state                                                               */
     opus_int16                      NLSF_Q15[],                             /* O    NLSFs                                                                       */
-    opus_int8                       *interpIndex,                           /* O    NLSF interpolation index, only used for NLSF interpolation                  */
-    const opus_int16                prev_NLSFq_Q15[],                       /* I    previous NLSFs, only used for NLSF interpolation                            */
-    const opus_int                  useInterpNLSFs,                         /* I    Flag                                                                        */
-    const opus_int                  firstFrameAfterReset,                   /* I    Flag                                                                        */
-    const opus_int                  LPC_order,                              /* I    LPC order                                                                   */
     const opus_int16                x[],                                    /* I    Input signal                                                                */
-    const opus_int                  subfr_length,                           /* I    Input signal subframe length including preceeding samples                   */
-    const opus_int                  nb_subfr                                /* I    Number of subframes                                                         */
+    const opus_int32                minInvGain_Q30                          /* I    Inverse of max prediction gain                                              */
 );
 
 /* LTP analysis */
index d85c8ed..94c5bb2 100644 (file)
@@ -166,12 +166,12 @@ void silk_noise_shape_analysis_FIX(
     SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7;
 
     /* Input quality is the average of the quality in the lowest two VAD bands */
-    psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( ( opus_int32 )psEnc->sCmn.input_quality_bands_Q15[ 0 ]
+    psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ]
         + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 );
 
     /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */
     psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 -
-        SILK_FIX_CONST( 18.0, 7 ), 4 ) ), 1 );
+        SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 );
 
     /* Reduce coding SNR during low speech activity */
     if( psEnc->sCmn.useCBR == 0 ) {
@@ -326,8 +326,8 @@ void silk_noise_shape_analysis_FIX(
         silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
 
         /* Ratio of prediction gains, in energy domain */
-        silk_LPC_inverse_pred_gain_Q24( &pre_nrg_Q30, AR2_Q24, psEnc->sCmn.shapingLPCOrder );
-        silk_LPC_inverse_pred_gain_Q24( &nrg,         AR1_Q24, psEnc->sCmn.shapingLPCOrder );
+        pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
+        nrg         = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
 
         /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
         pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
index f76c611..7471eb5 100644 (file)
@@ -116,7 +116,7 @@ opus_int silk_pitch_analysis_core(                  /* O    Voicing estimate: 0
     silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) );
     silk_assert( search_thres2_Q15 >= 0 && search_thres2_Q15 <= (1<<15) );
 
-    /* Setup frame lengths max / min lag for the sampling frequency */
+    /* Set up frame lengths max / min lag for the sampling frequency */
     frame_length      = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz;
     frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4;
     frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8;
@@ -375,7 +375,7 @@ opus_int silk_pitch_analysis_core(                  /* O    Voicing estimate: 0
         prevLag_log2_Q7 = 0;
     }
     silk_assert( search_thres2_Q15 == silk_SAT16( search_thres2_Q15 ) );
-    /* Setup stage 2 codebook based on number of subframes */
+    /* Set up stage 2 codebook based on number of subframes */
     if( nb_subfr == PE_MAX_NB_SUBFR ) {
         cbk_size   = PE_NB_CBKS_STAGE2_EXT;
         Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
@@ -500,7 +500,7 @@ opus_int silk_pitch_analysis_core(                  /* O    Voicing estimate: 0
         silk_assert( lag == silk_SAT16( lag ) );
         contour_bias_Q20 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 20 ), lag );
 
-        /* Setup cbk parameters acording to complexity setting and frame length */
+        /* Set up codebook parameters acording to complexity setting and frame length */
         if( nb_subfr == PE_MAX_NB_SUBFR ) {
             nb_cbk_search   = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ];
             cbk_size        = PE_NB_CBKS_STAGE3_MAX;
index 437899f..fe663fa 100644 (file)
@@ -36,7 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 static inline void silk_prefilt_FIX(
     silk_prefilter_state_FIX    *P,                         /* I/O  state                               */
     opus_int32                  st_res_Q12[],               /* I    short term residual signal          */
-    opus_int16                  xw[],                       /* O    prefiltered signal                  */
+    opus_int32                  pxw_Q10[],                  /* O    prefiltered signal                  */
     opus_int32                  HarmShapeFIRPacked_Q12,     /* I    Harmonic shaping coeficients        */
     opus_int                    Tilt_Q14,                   /* I    Tilt shaping coeficient             */
     opus_int32                  LF_shp_Q14,                 /* I    Low-frequancy shaping coeficients   */
@@ -46,7 +46,7 @@ static inline void silk_prefilt_FIX(
 
 void silk_warped_LPC_analysis_filter_FIX(
           opus_int32            state[],                    /* I/O  State [order + 1]                   */
-          opus_int16            res[],                      /* O    Residual signal [length]            */
+          opus_int32            res_Q2[],                   /* O    Residual signal [length]            */
     const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
     const opus_int16            input[],                    /* I    Input signal [length]               */
     const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
@@ -81,14 +81,14 @@ void silk_warped_LPC_analysis_filter_FIX(
         }
         state[ order ] = tmp1;
         acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
-        res[ n ] = ( opus_int16 )silk_SAT16( ( opus_int32 )input[ n ] - silk_RSHIFT_ROUND( acc_Q11, 11 ) );
+        res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
     }
 }
 
 void silk_prefilter_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state                                                               */
     const silk_encoder_control_FIX  *psEncCtrl,                             /* I    Encoder control                                                             */
-    opus_int16                      xw[],                                   /* O    Weighted signal                                                             */
+    opus_int32                      xw_Q10[],                               /* O    Weighted signal                                                             */
     const opus_int16                x[]                                     /* I    Speech signal                                                               */
 )
 {
@@ -97,16 +97,16 @@ void silk_prefilter_FIX(
     opus_int32 tmp_32;
     const opus_int16 *AR1_shp_Q13;
     const opus_int16 *px;
-    opus_int16 *pxw;
+    opus_int32 *pxw_Q10;
     opus_int   HarmShapeGain_Q12, Tilt_Q14;
     opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14;
-    opus_int32 x_filt_Q12[ MAX_FRAME_LENGTH / MAX_NB_SUBFR ];
-    opus_int16 st_res[ ( MAX_FRAME_LENGTH / MAX_NB_SUBFR ) + MAX_LPC_ORDER ];
-    opus_int16 B_Q12[ 2 ];
+    opus_int32 x_filt_Q12[ MAX_SUB_FRAME_LENGTH ];
+    opus_int32 st_res_Q2[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
+    opus_int16 B_Q10[ 2 ];
 
-    /* Setup pointers */
+    /* Set up pointers */
     px  = x;
-    pxw = xw;
+    pxw_Q10 = xw_Q10;
     lag = P->lagPrev;
     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
         /* Update Variables that change per sub frame */
@@ -118,34 +118,33 @@ void silk_prefilter_FIX(
         HarmShapeGain_Q12 = silk_SMULWB( psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] );
         silk_assert( HarmShapeGain_Q12 >= 0 );
         HarmShapeFIRPacked_Q12  =                          silk_RSHIFT( HarmShapeGain_Q12, 2 );
-        HarmShapeFIRPacked_Q12 |= silk_LSHIFT( ( opus_int32 )silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 );
+        HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 );
         Tilt_Q14    = psEncCtrl->Tilt_Q14[   k ];
         LF_shp_Q14  = psEncCtrl->LF_shp_Q14[ k ];
         AR1_shp_Q13 = &psEncCtrl->AR1_Q13[   k * MAX_SHAPE_LPC_ORDER ];
 
         /* Short term FIR filtering*/
-        silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res, AR1_shp_Q13, px,
+        silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px,
             psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder );
 
-        /* reduce (mainly) low frequencies during harmonic emphasis */
-        B_Q12[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 2 );
+        /* Reduce (mainly) low frequencies during harmonic emphasis */
+        B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 );
         tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 );   /* Q26 */
         tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) );    /* Q26 */
-        tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] );                                               /* Q24 */
-        tmp_32 = silk_RSHIFT_ROUND( tmp_32, 12 );                                                                    /* Q12 */
-        B_Q12[ 1 ]= silk_SAT16( tmp_32 );
-
-        x_filt_Q12[ 0 ] = silk_SMLABB( silk_SMULBB( st_res[ 0 ], B_Q12[ 0 ] ), P->sHarmHP, B_Q12[ 1 ] );
+        tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] );                                                /* Q24 */
+        tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 );                                                                     /* Q10 */
+        B_Q10[ 1 ]= silk_SAT16( tmp_32 );
+        x_filt_Q12[ 0 ] = silk_SMLABB( silk_SMULBB( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] );
         for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
-            x_filt_Q12[ j ] = silk_SMLABB( silk_SMULBB( st_res[ j ], B_Q12[ 0 ] ), st_res[ j - 1 ], B_Q12[ 1 ] );
+            x_filt_Q12[ j ] = silk_SMLABB( silk_SMULBB( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] );
         }
-        P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ];
+        P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ];
 
-        silk_prefilt_FIX( P, x_filt_Q12, pxw, HarmShapeFIRPacked_Q12, Tilt_Q14,
+        silk_prefilt_FIX( P, x_filt_Q12, pxw_Q10, HarmShapeFIRPacked_Q12, Tilt_Q14,
             LF_shp_Q14, lag, psEnc->sCmn.subfr_length );
 
         px  += psEnc->sCmn.subfr_length;
-        pxw += psEnc->sCmn.subfr_length;
+        pxw_Q10 += psEnc->sCmn.subfr_length;
     }
 
     P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
@@ -155,7 +154,7 @@ void silk_prefilter_FIX(
 static inline void silk_prefilt_FIX(
     silk_prefilter_state_FIX    *P,                         /* I/O  state                               */
     opus_int32                  st_res_Q12[],               /* I    short term residual signal          */
-    opus_int16                  xw[],                       /* O    prefiltered signal                  */
+    opus_int32                  xw_Q10[],                   /* O    prefiltered signal                  */
     opus_int32                  HarmShapeFIRPacked_Q12,     /* I    Harmonic shaping coeficients        */
     opus_int                    Tilt_Q14,                   /* I    Tilt shaping coeficient             */
     opus_int32                  LF_shp_Q14,                 /* I    Low-frequancy shaping coeficients   */
@@ -193,9 +192,9 @@ static inline void silk_prefilt_FIX(
         sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12,  silk_LSHIFT( n_LF_Q10,   2 ) );
 
         LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
-        LTP_shp_buf[ LTP_shp_buf_idx ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
+        LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
 
-        xw[i] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 12 ) );
+        xw_Q10[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 2 );
     }
 
     /* Copy temp variable back to state */
index bbd1027..044469f 100644 (file)
@@ -57,7 +57,7 @@ opus_int32 silk_residual_energy16_covar_FIX(
 
     c_max = 0;
     for( i = 0; i < D; i++ ) {
-        c_max = silk_max_32( c_max, silk_abs( ( opus_int32 )c[ i ] ) );
+        c_max = silk_max_32( c_max, silk_abs( (opus_int32)c[ i ] ) );
     }
     Qxtra = silk_min_int( Qxtra, silk_CLZ32( c_max ) - 17 );
 
index 14e4578..f037f3f 100644 (file)
@@ -76,7 +76,7 @@ opus_int32 silk_schur(                              /* O    Returns residual ene
         rc_tmp_Q15 = silk_SAT16( rc_tmp_Q15 );
 
         /* Store */
-        rc_Q15[ k ] = ( opus_int16 )rc_tmp_Q15;
+        rc_Q15[ k ] = (opus_int16)rc_tmp_Q15;
 
         /* Update correlations */
         for( n = 0; n < order - k; n++ ) {
index 4569492..8ba14fa 100644 (file)
@@ -56,7 +56,7 @@ typedef struct {
     opus_int                    sLTP_shp_buf_idx;
     opus_int32                  sLF_AR_shp_Q12;
     opus_int32                  sLF_MA_shp_Q12;
-    opus_int                    sHarmHP;
+    opus_int32                  sHarmHP_Q2;
     opus_int32                  rand_seed;
     opus_int                    lagPrev;
 } silk_prefilter_state_FIX;
@@ -72,10 +72,6 @@ typedef struct {
     /* Buffer for find pitch and noise shape analysis */
     silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis  */
     opus_int                    LTPCorr_Q15;                            /* Normalized correlation from pitch lag estimator      */
-
-    /* Parameters For LTP scaling Control */
-    opus_int                    prevLTPredCodGain_Q7;
-    opus_int                    HPLTPredCodGain_Q7;
 } silk_encoder_state_FIX;
 
 /************************/
index c79c04f..92912e5 100644 (file)
@@ -55,7 +55,7 @@ void silk_warped_autocorrelation_FIX(
 
     /* Loop over samples */
     for( n = 0; n < length; n++ ) {
-        tmp1_QS = silk_LSHIFT32( ( opus_int32 )input[ n ], QS );
+        tmp1_QS = silk_LSHIFT32( (opus_int32)input[ n ], QS );
         /* Loop over allpass sections */
         for( i = 0; i < order; i += 2 ) {
             /* Output of allpass section */
@@ -77,11 +77,11 @@ void silk_warped_autocorrelation_FIX(
     silk_assert( *scale >= -30 && *scale <= 12 );
     if( lsh >= 0 ) {
         for( i = 0; i < order + 1; i++ ) {
-            corr[ i ] = ( opus_int32 )silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) );
+            corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QC[ i ], lsh ) );
         }
     } else {
         for( i = 0; i < order + 1; i++ ) {
-            corr[ i ] = ( opus_int32 )silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) );
+            corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) );
         }
     }
     silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/
index d7a5d87..59ed7d4 100644 (file)
@@ -37,29 +37,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /* compute inverse of LPC prediction gain, and                          */
 /* test if LPC coefficients are stable (all poles within unit circle)   */
 /* this code is based on silk_a2k_FLP()                                 */
-opus_int silk_LPC_inverse_pred_gain_FLP(    /* O    returns 1 if unstable, otherwise 0                          */
-    silk_float          *invGain,           /* O    inverse prediction gain, energy domain                      */
+silk_float silk_LPC_inverse_pred_gain_FLP(  /* O    return inverse prediction gain, energy domain               */
     const silk_float    *A,                 /* I    prediction coefficients [order]                             */
     opus_int32          order               /* I    prediction order                                            */
 )
 {
     opus_int   k, n;
-    double     rc, rc_mult1, rc_mult2;
+    double     invGain, rc, rc_mult1, rc_mult2;
     silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ];
     silk_float *Aold, *Anew;
 
     Anew = Atmp[ order & 1 ];
     silk_memcpy( Anew, A, order * sizeof(silk_float) );
 
-    *invGain = 1.0f;
+    invGain = 1.0;
     for( k = order - 1; k > 0; k-- ) {
         rc = -Anew[ k ];
         if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
-            return 1;
+            return 0.0f;
         }
         rc_mult1 = 1.0f - rc * rc;
         rc_mult2 = 1.0f / rc_mult1;
-        *invGain *= (silk_float)rc_mult1;
+        invGain *= rc_mult1;
         /* swap pointers */
         Aold = Anew;
         Anew = Atmp[ k & 1 ];
@@ -69,9 +68,9 @@ opus_int silk_LPC_inverse_pred_gain_FLP(    /* O    returns 1 if unstable, other
     }
     rc = -Anew[ 0 ];
     if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
-        return 1;
+        return 0.0f;
     }
     rc_mult1 = 1.0f - rc * rc;
-    *invGain *= (silk_float)rc_mult1;
-    return 0;
+    invGain *= rc_mult1;
+    return (silk_float)invGain;
 }
index ebfdbf4..2354ebe 100644 (file)
@@ -39,19 +39,14 @@ void silk_LTP_scale_ctrl_FLP(
 {
     opus_int   round_loss;
 
-    /* 1st order high-pass filter */
-    /*g_HP(n) = g(n) - 0.5 * g(n-1) + 0.5 * g_HP(n-1);*/
-    psEnc->HPLTPredCodGain = silk_max_float( psEncCtrl->LTPredCodGain - 0.5f * psEnc->prevLTPredCodGain, 0.0f )
-                            + 0.5f * psEnc->HPLTPredCodGain;
-    psEnc->prevLTPredCodGain = psEncCtrl->LTPredCodGain;
-
-    /* Only scale if first frame in packet */
     if( condCoding == CODE_INDEPENDENTLY ) {
+        /* Only scale if first frame in packet */
         round_loss = psEnc->sCmn.PacketLoss_perc + psEnc->sCmn.nFramesPerPacket;
-        psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( round_loss * psEnc->HPLTPredCodGain * 0.1f, 0.0f, 2.0f );
+        psEnc->sCmn.indices.LTP_scaleIndex = (opus_int8)silk_LIMIT( round_loss * psEncCtrl->LTPredCodGain * 0.1f, 0.0f, 2.0f );
     } else {
         /* Default is minimum scaling */
         psEnc->sCmn.indices.LTP_scaleIndex = 0;
     }
+
     psEncCtrl->LTP_scale = (silk_float)silk_LTPScales_table_Q14[ psEnc->sCmn.indices.LTP_scaleIndex ] / 16384.0f;
 }
index 7b2ba08..0d70ca1 100644 (file)
@@ -50,8 +50,7 @@ void silk_bwexpander_FLP(
 /* compute inverse of LPC prediction gain, and                          */
 /* test if LPC coefficients are stable (all poles within unit circle)   */
 /* this code is based on silk_FLP_a2k()                                 */
-opus_int silk_LPC_inverse_pred_gain_FLP(    /* O    returns 1 if unstable, otherwise 0                          */
-    silk_float          *invGain,           /* O    inverse prediction gain, energy domain                      */
+silk_float silk_LPC_inverse_pred_gain_FLP(  /* O    return inverse prediction gain, energy domain               */
     const silk_float    *A,                 /* I    prediction coefficients [order]                             */
     opus_int32          order               /* I    prediction order                                            */
 );
@@ -108,9 +107,9 @@ void silk_insertion_sort_decreasing_FLP(
 silk_float silk_burg_modified_FLP(          /* O    returns residual energy                                     */
     silk_float          A[],                /* O    prediction coefficients (length order)                      */
     const silk_float    x[],                /* I    input signal, length: nb_subfr*(D+L_sub)                    */
+    const silk_float    minInvGain,         /* I    minimum inverse prediction gain                             */
     const opus_int      subfr_length,       /* I    input signal subframe length (incl. D preceeding samples)   */
     const opus_int      nb_subfr,           /* I    number of subframes stacked in x                            */
-    const silk_float    WhiteNoiseFrac,     /* I    fraction added to zero-lag autocorrelation                  */
     const opus_int      D                   /* I    order                                                       */
 );
 
index b5862a5..2f6edfa 100644 (file)
@@ -30,29 +30,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endif
 
 #include "SigProc_FLP.h"
+#include "tuning_parameters.h"
+#include "define.h"
 
 #define MAX_FRAME_SIZE              384 /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384*/
-#define MAX_NB_SUBFR                4
 
 /* Compute reflection coefficients from input signal */
 silk_float silk_burg_modified_FLP(          /* O    returns residual energy                                     */
     silk_float          A[],                /* O    prediction coefficients (length order)                      */
     const silk_float    x[],                /* I    input signal, length: nb_subfr*(D+L_sub)                    */
+    const silk_float    minInvGain,         /* I    minimum inverse prediction gain                             */
     const opus_int      subfr_length,       /* I    input signal subframe length (incl. D preceeding samples)   */
     const opus_int      nb_subfr,           /* I    number of subframes stacked in x                            */
-    const silk_float    WhiteNoiseFrac,     /* I    fraction added to zero-lag autocorrelation                  */
     const opus_int      D                   /* I    order                                                       */
 )
 {
-    opus_int         k, n, s;
-    double          C0, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2;
+    opus_int         k, n, s, reached_max_gain;
+    double           C0, invGain, num, nrg_f, nrg_b, rc, Atmp, tmp1, tmp2;
     const silk_float *x_ptr;
-    double          C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ SILK_MAX_ORDER_LPC ];
-    double          CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
-    double          Af[ SILK_MAX_ORDER_LPC ];
+    double           C_first_row[ SILK_MAX_ORDER_LPC ], C_last_row[ SILK_MAX_ORDER_LPC ];
+    double           CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
+    double           Af[ SILK_MAX_ORDER_LPC ];
 
     silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
-    silk_assert( nb_subfr <= MAX_NB_SUBFR );
 
     /* Compute autocorrelations, added over subframes */
     C0 = silk_energy_FLP( x, nb_subfr * subfr_length );
@@ -66,8 +66,9 @@ silk_float silk_burg_modified_FLP(          /* O    returns residual energy
     silk_memcpy( C_last_row, C_first_row, SILK_MAX_ORDER_LPC * sizeof( double ) );
 
     /* Initialize */
-    CAb[ 0 ] = CAf[ 0 ] = C0 + WhiteNoiseFrac * C0 + 1e-9f;
-
+    CAb[ 0 ] = CAf[ 0 ] = C0 + FIND_LPC_COND_FAC * C0 + 1e-9f;
+    invGain = 1.0f;
+    reached_max_gain = 0;
     for( n = 0; n < D; n++ ) {
         /* Update first row of correlation matrix (without first element) */
         /* Update last row of correlation matrix (without last element, stored in reversed order) */
@@ -93,7 +94,7 @@ silk_float silk_burg_modified_FLP(          /* O    returns residual energy
         tmp2 = C_last_row[ n ];
         for( k = 0; k < n; k++ ) {
             Atmp = Af[ k ];
-            tmp1 += C_last_row[ n - k - 1 ]  * Atmp;
+            tmp1 += C_last_row[  n - k - 1 ] * Atmp;
             tmp2 += C_first_row[ n - k - 1 ] * Atmp;
         }
         CAf[ n + 1 ] = tmp1;
@@ -116,6 +117,21 @@ silk_float silk_burg_modified_FLP(          /* O    returns residual energy
         rc = -2.0 * num / ( nrg_f + nrg_b );
         silk_assert( rc > -1.0 && rc < 1.0 );
 
+        /* Update inverse prediction gain */
+        tmp1 = invGain * ( 1.0 - rc * rc );
+        if( tmp1 <= minInvGain ) {
+            /* Max prediction gain exceeded; set reflection coefficient such that max prediction gain is exactly hit */
+            rc = sqrt( 1.0 - minInvGain / invGain );
+            if( num > 0 ) {
+                /* Ensure adjusted reflection coefficients has the original sign */
+                rc = -rc;
+            }
+            invGain = minInvGain;
+            reached_max_gain = 1;
+        } else {
+            invGain = tmp1;
+        }
+
         /* Update the AR coefficients */
         for( k = 0; k < (n + 1) >> 1; k++ ) {
             tmp1 = Af[ k ];
@@ -125,6 +141,14 @@ silk_float silk_burg_modified_FLP(          /* O    returns residual energy
         }
         Af[ n ] = rc;
 
+        if( reached_max_gain ) {
+            /* Reached max prediction gain; set remaining coefficients to zero and exit loop */
+            for( k = n + 1; k < D; k++ ) {
+                Af[ k ] = 0.0;
+            }
+            break;
+        }
+
         /* Update C * Af and C * Ab */
         for( k = 0; k <= n + 1; k++ ) {
             tmp1 = CAf[ k ];
@@ -133,16 +157,30 @@ silk_float silk_burg_modified_FLP(          /* O    returns residual energy
         }
     }
 
-    /* Return residual energy */
-    nrg_f = CAf[ 0 ];
-    tmp1 = 1.0;
-    for( k = 0; k < D; k++ ) {
-        Atmp = Af[ k ];
-        nrg_f += CAf[ k + 1 ] * Atmp;
-        tmp1  += Atmp * Atmp;
-        A[ k ] = (silk_float)(-Atmp);
+    if( reached_max_gain ) {
+        /* Convert to silk_float */
+        for( k = 0; k < D; k++ ) {
+            A[ k ] = (silk_float)( -Af[ k ] );
+        }
+        /* Subtract energy of preceeding samples from C0 */
+        for( s = 0; s < nb_subfr; s++ ) {
+            C0 -= silk_energy_FLP( x + s * subfr_length, D );
+        }
+        /* Approximate residual energy */
+        nrg_f = C0 * invGain;
+    } else {
+        /* Compute residual energy and store coefficients as silk_float */
+        nrg_f = CAf[ 0 ];
+        tmp1 = 1.0;
+        for( k = 0; k < D; k++ ) {
+            Atmp = Af[ k ];
+            nrg_f += CAf[ k + 1 ] * Atmp;
+            tmp1  += Atmp * Atmp;
+            A[ k ] = (silk_float)(-Atmp);
+        }
+        nrg_f -= FIND_LPC_COND_FAC * C0 * tmp1;
     }
-    nrg_f -= WhiteNoiseFrac * C0 * tmp1;
 
+    /* Return residual energy */
     return (silk_float)nrg_f;
 }
index faae848..facb410 100644 (file)
@@ -104,8 +104,8 @@ opus_int silk_encode_frame_FLP(
     psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
 
     /**************************************************************/
-    /* Setup Input Pointers, and insert frame in input buffer    */
-    /*************************************************************/
+    /* Set up Input Pointers, and insert frame in input buffer    */
+    /**************************************************************/
     /* pointers aligned with start of frame to encode */
     x_frame         = psEnc->x_buf + psEnc->sCmn.ltp_mem_length;    /* start of frame to encode */
     res_pitch_frame = res_pitch    + psEnc->sCmn.ltp_mem_length;    /* start of pitch LPC residual frame */
@@ -157,7 +157,7 @@ opus_int silk_encode_frame_FLP(
         silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );
 
         /* Loop over quantizer and entroy coding to control bitrate */
-        maxIter = 5;
+        maxIter = 6;
         gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
         found_lower = 0;
         found_upper = 0;
index 23de2e7..940a8c0 100644 (file)
@@ -29,73 +29,63 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "config.h"
 #endif
 
+#include "define.h"
 #include "main_FLP.h"
 #include "tuning_parameters.h"
 
+/* LPC analysis */
 void silk_find_LPC_FLP(
+    silk_encoder_state              *psEncC,                            /* I/O  Encoder state                               */
     opus_int16                      NLSF_Q15[],                         /* O    NLSFs                                       */
-    opus_int8                       *interpIndex,                       /* O    NLSF interp. index for NLSF interp.         */
-    const opus_int16                prev_NLSFq_Q15[],                   /* I    Previous NLSFs, for NLSF interpolation      */
-    const opus_int                  useInterpNLSFs,                     /* I    Flag                                        */
-    const opus_int                  firstFrameAfterReset,               /* I    Flag                                        */
-    const opus_int                  LPC_order,                          /* I    LPC order                                   */
     const silk_float                x[],                                /* I    Input signal                                */
-    const opus_int                  subfr_length,                       /* I    Subframe length incl preceeding samples     */
-    const opus_int                  nb_subfr                            /* I    Number of subframes                         */
+    const silk_float                minInvGain                          /* I    Inverse of max prediction gain              */
 )
 {
-    opus_int     k;
-    silk_float   a[ MAX_LPC_ORDER ];
+    opus_int    k, subfr_length;
+    silk_float  a[ MAX_LPC_ORDER ];
 
     /* Used only for NLSF interpolation */
-    double      res_nrg, res_nrg_2nd, res_nrg_interp;
-    opus_int16   NLSF0_Q15[ MAX_LPC_ORDER ];
-    silk_float   a_tmp[ MAX_LPC_ORDER ];
-    silk_float   LPC_res[ ( MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ) / 2 ];
+    silk_float  res_nrg, res_nrg_2nd, res_nrg_interp;
+    opus_int16  NLSF0_Q15[ MAX_LPC_ORDER ];
+    silk_float  a_tmp[ MAX_LPC_ORDER ];
+    silk_float  LPC_res[ MAX_FRAME_LENGTH + MAX_NB_SUBFR * MAX_LPC_ORDER ];
+
+    subfr_length = psEncC->subfr_length + psEncC->predictLPCOrder;
 
     /* Default: No interpolation */
-    *interpIndex = 4;
+    psEncC->indices.NLSFInterpCoef_Q2 = 4;
 
     /* Burg AR analysis for the full frame */
-    res_nrg = silk_burg_modified_FLP( a, x, subfr_length, nb_subfr, FIND_LPC_COND_FAC, LPC_order );
-
-    if( firstFrameAfterReset ) {
-        silk_bwexpander_FLP( a, LPC_order, FIND_LPC_CHIRP_FIRST_FRAME );
-    } else {
-        silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP );
-    }
+    res_nrg = silk_burg_modified_FLP( a, x, minInvGain, subfr_length, psEncC->nb_subfr, psEncC->predictLPCOrder );
 
-    if( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) {
+    if( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) {
         /* Optimal solution for last 10 ms; subtract residual energy here, as that's easier than        */
         /* adding it to the residual energy of the first 10 ms in each iteration of the search below    */
-        res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length,
-            subfr_length, MAX_NB_SUBFR / 2, FIND_LPC_COND_FAC, LPC_order );
-
-        silk_bwexpander_FLP( a_tmp, LPC_order, FIND_LPC_CHIRP );
+        res_nrg -= silk_burg_modified_FLP( a_tmp, x + ( MAX_NB_SUBFR / 2 ) * subfr_length, minInvGain, subfr_length, MAX_NB_SUBFR / 2, psEncC->predictLPCOrder );
 
         /* Convert to NLSFs */
-        silk_A2NLSF_FLP( NLSF_Q15, a_tmp, LPC_order );
+        silk_A2NLSF_FLP( NLSF_Q15, a_tmp, psEncC->predictLPCOrder );
 
         /* Search over interpolation indices to find the one with lowest residual energy */
         res_nrg_2nd = silk_float_MAX;
         for( k = 3; k >= 0; k-- ) {
             /* Interpolate NLSFs for first half */
-            silk_interpolate( NLSF0_Q15, prev_NLSFq_Q15, NLSF_Q15, k, LPC_order );
+            silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
 
             /* Convert to LPC for residual energy evaluation */
-            silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, LPC_order );
+            silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder );
 
             /* Calculate residual energy with LSF interpolation */
-            silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, LPC_order );
-            res_nrg_interp =
-                silk_energy_FLP( LPC_res + LPC_order,                subfr_length - LPC_order ) +
-                silk_energy_FLP( LPC_res + LPC_order + subfr_length, subfr_length - LPC_order );
+            silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder );
+            res_nrg_interp = (silk_float)(
+                silk_energy_FLP( LPC_res + psEncC->predictLPCOrder,                subfr_length - psEncC->predictLPCOrder ) +
+                silk_energy_FLP( LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ) );
 
             /* Determine whether current interpolated NLSFs are best so far */
             if( res_nrg_interp < res_nrg ) {
                 /* Interpolation has lower residual energy */
                 res_nrg = res_nrg_interp;
-                *interpIndex = (opus_int8)k;
+                psEncC->indices.NLSFInterpCoef_Q2 = (opus_int8)k;
             } else if( res_nrg_interp > res_nrg_2nd ) {
                 /* No reason to continue iterating - residual energies will continue to climb */
                 break;
@@ -104,10 +94,11 @@ void silk_find_LPC_FLP(
         }
     }
 
-    if( *interpIndex == 4 ) {
+    if( psEncC->indices.NLSFInterpCoef_Q2 == 4 ) {
         /* NLSF interpolation is currently inactive, calculate NLSFs from full frame AR coefficients */
-        silk_A2NLSF_FLP( NLSF_Q15, a, LPC_order );
+        silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder );
     }
 
-    silk_assert( *interpIndex == 4 || ( useInterpNLSFs && !firstFrameAfterReset && nb_subfr == MAX_NB_SUBFR ) );
+    silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || 
+        ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
 }
index 43f7ff9..c037138 100644 (file)
@@ -50,7 +50,7 @@ void silk_find_pitch_lags_FLP(
     silk_float *Wsig_ptr;
 
     /******************************************/
-    /* Setup buffer lengths etc based on Fs   */
+    /* Set up buffer lengths etc based on Fs  */
     /******************************************/
     buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
 
index 03500c2..7186677 100644 (file)
@@ -46,6 +46,7 @@ void silk_find_pred_coefs_FLP(
     opus_int16       NLSF_Q15[ MAX_LPC_ORDER ];
     const silk_float *x_ptr;
     silk_float       *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
+    silk_float       minInvGain;
 
     /* Weighting for weighted least squares */
     for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
@@ -74,7 +75,6 @@ void silk_find_pred_coefs_FLP(
         /* Create LTP residual */
         silk_LTP_analysis_filter_FLP( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef,
             psEncCtrl->pitchL, invGains, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
-
     } else {
         /************/
         /* UNVOICED */
@@ -88,15 +88,20 @@ void silk_find_pred_coefs_FLP(
             x_pre_ptr += psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder;
             x_ptr     += psEnc->sCmn.subfr_length;
         }
-
         silk_memset( psEncCtrl->LTPCoef, 0, psEnc->sCmn.nb_subfr * LTP_ORDER * sizeof( silk_float ) );
         psEncCtrl->LTPredCodGain = 0.0f;
     }
 
+    /* Limit on total predictive coding gain */
+    if( psEnc->sCmn.first_frame_after_reset ) {
+        minInvGain = 1.0f / MAX_PREDICTION_POWER_GAIN_AFTER_RESET;
+    } else {        
+        minInvGain = (silk_float)powf( 2, psEncCtrl->LTPredCodGain / 3 ) /  MAX_PREDICTION_POWER_GAIN;
+        minInvGain /= 0.1f + 0.9f * psEncCtrl->coding_quality;
+    }
+
     /* LPC_in_pre contains the LTP-filtered input for voiced, and the unfiltered input for unvoiced */
-    silk_find_LPC_FLP( NLSF_Q15, &psEnc->sCmn.indices.NLSFInterpCoef_Q2, psEnc->sCmn.prev_NLSFq_Q15,
-        psEnc->sCmn.useInterpolatedNLSFs, psEnc->sCmn.first_frame_after_reset, psEnc->sCmn.predictLPCOrder,
-        LPC_in_pre, psEnc->sCmn.subfr_length + psEnc->sCmn.predictLPCOrder, psEnc->sCmn.nb_subfr );
+    silk_find_LPC_FLP( &psEnc->sCmn, NLSF_Q15, LPC_in_pre, minInvGain );
 
     /* Quantize LSFs */
     silk_process_NLSFs_FLP( &psEnc->sCmn, psEncCtrl->PredCoef, NLSF_Q15, psEnc->sCmn.prev_NLSFq_Q15 );
index d288900..5107921 100644 (file)
@@ -143,15 +143,10 @@ void silk_find_pred_coefs_FLP(
 
 /* LPC analysis */
 void silk_find_LPC_FLP(
+    silk_encoder_state              *psEncC,                            /* I/O  Encoder state                               */
     opus_int16                      NLSF_Q15[],                         /* O    NLSFs                                       */
-    opus_int8                       *interpIndex,                       /* O    NLSF interp. index for NLSF interp.         */
-    const opus_int16                prev_NLSFq_Q15[],                   /* I    Previous NLSFs, for NLSF interpolation      */
-    const opus_int                  useInterpNLSFs,                     /* I    Flag                                        */
-    const opus_int                  firstFrameAfterReset,               /* I    Flag                                        */
-    const opus_int                  LPC_order,                          /* I    LPC order                                   */
     const silk_float                x[],                                /* I    Input signal                                */
-    const opus_int                  subfr_length,                       /* I    Subframe length incl preceeding samples     */
-    const opus_int                  nb_subfr                            /* I    Number of subframes                         */
+    const silk_float                minInvGain                          /* I    Prediction gain from LTP (dB)               */
 );
 
 /* LTP analysis */
index e19ff70..d1f1a69 100644 (file)
@@ -151,7 +151,7 @@ void silk_noise_shape_analysis_FLP(
     psEncCtrl->input_quality = 0.5f * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] + psEnc->sCmn.input_quality_bands_Q15[ 1 ] ) * ( 1.0f / 32768.0f );
 
     /* Coding quality level, between 0.0 and 1.0 */
-    psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 18.0f ) );
+    psEncCtrl->coding_quality = silk_sigmoid( 0.25f * ( SNR_adj_dB - 20.0f ) );
 
     if( psEnc->sCmn.useCBR == 0 ) {
         /* Reduce coding SNR during low speech activity */
@@ -274,8 +274,8 @@ void silk_noise_shape_analysis_FLP(
         silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 );
 
         /* Ratio of prediction gains, in energy domain */
-        silk_LPC_inverse_pred_gain_FLP( &pre_nrg, &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
-        silk_LPC_inverse_pred_gain_FLP( &nrg,     &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
+        pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
+        nrg     = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
         psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg );
 
         /* Convert to monic warped prediction coefficients and limit absolute values */
index c798003..5546d09 100644 (file)
@@ -115,7 +115,7 @@ opus_int silk_pitch_analysis_core_FLP(      /* O    Voicing estimate: 0 voiced,
     silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
     silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f );
 
-    /* Setup frame lengths max / min lag for the sampling frequency */
+    /* Set up frame lengths max / min lag for the sampling frequency */
     frame_length      = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz;
     frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4;
     frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8;
@@ -322,7 +322,7 @@ opus_int silk_pitch_analysis_core_FLP(      /* O    Voicing estimate: 0 voiced,
         prevLag_log2 = 0;
     }
 
-    /* Setup stage 2 codebook based on number of subframes */
+    /* Set up stage 2 codebook based on number of subframes */
     if( nb_subfr == PE_MAX_NB_SUBFR ) {
         cbk_size   = PE_NB_CBKS_STAGE2_EXT;
         Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
@@ -419,7 +419,7 @@ opus_int silk_pitch_analysis_core_FLP(      /* O    Voicing estimate: 0 voiced,
         silk_assert( lag == silk_SAT16( lag ) );
         contour_bias = PE_FLATCONTOUR_BIAS / lag;
 
-        /* Setup cbk parameters acording to complexity setting and frame length */
+        /* Set up cbk parameters acording to complexity setting and frame length */
         if( nb_subfr == PE_MAX_NB_SUBFR ) {
             nb_cbk_search = (opus_int)silk_nb_cbk_searchs_stage3[ complexity ];
             cbk_size      = PE_NB_CBKS_STAGE3_MAX;
index 3dcf7b5..79ebf65 100644 (file)
@@ -108,7 +108,7 @@ void silk_prefilter_FLP(
     silk_float HarmShapeFIR[ 3 ];
     silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
 
-    /* Setup pointers */
+    /* Set up pointers */
     px  = x;
     pxw = xw;
     lag = P->lagPrev;
index 020f847..edac122 100644 (file)
@@ -64,7 +64,7 @@ void silk_process_gains_FLP(
 
     /* Prepare gains for noise shaping quantization */
     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
-        pGains_Q16[ k ] = ( opus_int32 ) ( psEncCtrl->Gains[ k ] * 65536.0f );
+        pGains_Q16[ k ] = (opus_int32)( psEncCtrl->Gains[ k ] * 65536.0f );
     }
 
     /* Save unquantized gains and gain Index */
index f56a972..b879fd1 100644 (file)
@@ -72,10 +72,6 @@ typedef struct {
     /* Buffer for find pitch and noise shape analysis */
     silk_float                  x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
     silk_float                  LTPCorr;                            /* Normalized correlation from pitch lag estimator */
-
-    /* Parameters for LTP scaling control */
-    silk_float                  prevLTPredCodGain;
-    silk_float                  HPLTPredCodGain;
 } silk_encoder_state_FLP;
 
 /************************/
index 9fd9147..ad9c2a5 100644 (file)
@@ -102,7 +102,7 @@ void silk_NSQ_wrapper_FLP(
 )
 {
     opus_int     i, j;
-    opus_int16   x_16[ MAX_FRAME_LENGTH ];
+    opus_int32   x_Q10[ MAX_FRAME_LENGTH ];
     opus_int32   Gains_Q16[ MAX_NB_SUBFR ];
     silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
     opus_int16   LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
@@ -133,12 +133,12 @@ void silk_NSQ_wrapper_FLP(
 
     /* prediction and coding parameters */
     for( i = 0; i < psEnc->sCmn.nb_subfr * LTP_ORDER; i++ ) {
-        LTPCoef_Q14[ i ] = ( opus_int16 )silk_float2int( psEncCtrl->LTPCoef[ i ] * 16384.0f );
+        LTPCoef_Q14[ i ] = (opus_int16)silk_float2int( psEncCtrl->LTPCoef[ i ] * 16384.0f );
     }
 
     for( j = 0; j < 2; j++ ) {
         for( i = 0; i < psEnc->sCmn.predictLPCOrder; i++ ) {
-            PredCoef_Q12[ j ][ i ] = ( opus_int16 )silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f );
+            PredCoef_Q12[ j ][ i ] = (opus_int16)silk_float2int( psEncCtrl->PredCoef[ j ][ i ] * 4096.0f );
         }
     }
 
@@ -154,14 +154,16 @@ void silk_NSQ_wrapper_FLP(
     }
 
     /* Convert input to fix */
-    silk_float2short_array( x_16, x, psEnc->sCmn.frame_length );
+    for( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+        x_Q10[ i ] = silk_float2int( 1024.0 * x[ i ] );
+    }
 
     /* Call NSQ */
     if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
-        silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+        silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q10, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
             AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 );
     } else {
-        silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+        silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_Q10, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
             AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14 );
     }
 }
index 0f40a93..216f7c7 100644 (file)
@@ -46,6 +46,6 @@ void silk_interpolate(
     silk_assert( ifact_Q2 <= 4 );
 
     for( i = 0; i < d; i++ ) {
-        xi[ i ] = ( opus_int16 )silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 );
+        xi[ i ] = (opus_int16)silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 );
     }
 }
index e3ab0e7..e6121e8 100644 (file)
@@ -25,8 +25,12 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/
 
-#ifndef SILK_API_C_H
-#define SILK_API_C_H
+#ifndef SILK_MACROS_H
+#define SILK_MACROS_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 /* This is an inline header file for general platform. */
 
@@ -128,5 +132,5 @@ static inline opus_int32 silk_CLZ32(opus_int32 in32)
 #endif
 #define matrix_c_adr(Matrix_base_adr, row, column, M)        (Matrix_base_adr + ((row)+(M)*(column)))
 
-#endif /* SILK_API_C_H */
+#endif /* SILK_MACROS_H */
 
index adf11f6..1d9e7b8 100644 (file)
@@ -38,9 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "entenc.h"
 #include "entdec.h"
 
-/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0,1,2,3,4] */
-#define rateID(R) ( ( ( ((R)>>12) - ((R)>16000) ) >> ((R)>24000) ) - 1 )
-
 /* Convert Left/Right stereo signal to adaptive Mid/Side representation */
 void silk_stereo_LR_to_MS(
     stereo_enc_state            *state,                         /* I/O  State                                       */
@@ -232,7 +229,7 @@ void silk_NSQ(
     const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
-    const opus_int16            x[],                                        /* I    Prefiltered input signal        */
+    const opus_int32            x_Q10[],                                    /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
@@ -251,7 +248,7 @@ void silk_NSQ_del_dec(
     const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
-    const opus_int16            x[],                                        /* I    Prefiltered input signal        */
+    const opus_int32            x_Q10[],                                    /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
index 4724659..d98798e 100644 (file)
@@ -59,7 +59,7 @@ void silk_quant_LTP_gains(
         cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[        k ];
         cbk_size   = silk_LTP_vq_sizes[          k ];
 
-        /* Setup pointer to first subframe */
+        /* Set up pointer to first subframe */
         W_Q18_ptr = W_Q18;
         b_Q14_ptr = B_Q14;
 
index eeda054..9055c81 100644 (file)
@@ -29,30 +29,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "config.h"
 #endif
 
-/* Matrix of resampling methods used:
+/*
+ * Matrix of resampling methods used:
  *                                 Fs_out (kHz)
- *                        8      12     16     24    48
+ *                        8      12     16     24     48
  *
  *               8        C      UF     U      UF     UF
  *              12        AF     C      UF     U      UF
  * Fs_in (kHz)  16        D      AF     C      UF     UF
- *              24        AIF    D      AF     C      U
- *              48        DAF    DAF    AF     D      C
- *
- * default method: UF
+ *              24        AF     D      AF     C      U
+ *              48        AF     AF     AF     D      C
  *
  * C   -> Copy (no resampling)
  * D   -> Allpass-based 2x downsampling
  * U   -> Allpass-based 2x upsampling
- * DAF -> Allpass-based 2x downsampling followed by AR2 filter followed by FIR interpolation
  * UF  -> Allpass-based 2x upsampling followed by FIR interpolation
  * AF  -> AR2 filter followed by FIR interpolation
- *
- * Signals sampled above 48 kHz are not supported.
  */
 
 #include "resampler_private.h"
 
+/* Tables with delay compensation values to equalize total delay for different modes */
+static const opus_int8 delay_matrix_enc[ 5 ][ 3 ] = {
+/* in  \ out  8  12  16 */
+/*  8 */   {  6,  0,  3 },
+/* 12 */   {  0,  7,  3 },
+/* 16 */   {  0,  1, 10 },
+/* 24 */   {  0,  2,  6 },
+/* 48 */   { 18, 10, 12 }
+};
+
+static const opus_int8 delay_matrix_dec[ 3 ][ 5 ] = {
+/* in  \ out  8  12  16  24  48 */
+/*  8 */   {  4,  0,  2,  0,  0 },
+/* 12 */   {  0,  9,  4,  7,  4 },
+/* 16 */   {  0,  3, 12,  7,  7 }
+};
+
+/* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0, 1, 2, 3, 4] */
+#define rateID(R) ( ( ( ((R)>>12) - ((R)>16000) ) >> ((R)>24000) ) - 1 )
+
 #define USE_silk_resampler_copy                     (0)
 #define USE_silk_resampler_private_up2_HQ_wrapper   (1)
 #define USE_silk_resampler_private_IIR_FIR          (2)
@@ -60,27 +76,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /* Initialize/reset the resampler state for a given pair of input/output sampling rates */
 opus_int silk_resampler_init(
-    silk_resampler_state_struct *S,                 /* I/O   Resampler state                                            */
-    opus_int32                  Fs_Hz_in,           /* I     Input sampling rate (Hz)                                   */
-    opus_int32                  Fs_Hz_out           /* I     Output sampling rate (Hz)                                  */
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int32                  Fs_Hz_in,           /* I    Input sampling rate (Hz)                                    */
+    opus_int32                  Fs_Hz_out,          /* I    Output sampling rate (Hz)                                   */
+    opus_int                    forEnc              /* I    If 1: encoder; if 0: decoder                                */
 )
 {
-    opus_int32 up2 = 0, down2 = 0;
+    opus_int up2x;
 
     /* Clear state */
     silk_memset( S, 0, sizeof( silk_resampler_state_struct ) );
 
     /* Input checking */
-    if( ( Fs_Hz_in  != 8000 && Fs_Hz_in  != 12000 && Fs_Hz_in  != 16000 && Fs_Hz_in  != 24000 && Fs_Hz_in  != 48000 ) ||
-        ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) {
-        silk_assert( 0 );
-        return -1;
+    if( forEnc ) {
+        if( ( Fs_Hz_in  != 8000 && Fs_Hz_in  != 12000 && Fs_Hz_in  != 16000 && Fs_Hz_in  != 24000 && Fs_Hz_in  != 48000 ) ||
+            ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) {
+            silk_assert( 0 );
+            return -1;
+        }
+        S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
+    } else {
+        if( ( Fs_Hz_in  != 8000 && Fs_Hz_in  != 12000 && Fs_Hz_in  != 16000 ) ||
+            ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) {
+            silk_assert( 0 );
+            return -1;
+        }
+        S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
     }
 
+    S->Fs_in_kHz  = silk_DIV32_16( Fs_Hz_in,  1000 );
+    S->Fs_out_kHz = silk_DIV32_16( Fs_Hz_out, 1000 );
+
     /* Number of samples processed per batch */
-    S->batchSize = silk_DIV32_16( Fs_Hz_in, 100 );
+    S->batchSize = S->Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS;
 
     /* Find resampler with the right sampling ratio */
+    up2x = 0;
     if( Fs_Hz_out > Fs_Hz_in ) {
         /* Upsample */
         if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) {                            /* Fs_out : Fs_in = 2 : 1 */
@@ -89,36 +120,35 @@ opus_int silk_resampler_init(
         } else {
             /* Default resampler */
             S->resampler_function = USE_silk_resampler_private_IIR_FIR;
-            up2 = 1;
+            up2x = 1;
         }
     } else if ( Fs_Hz_out < Fs_Hz_in ) {
         /* Downsample */
+         S->resampler_function = USE_silk_resampler_private_down_FIR;
         if( silk_MUL( Fs_Hz_out, 4 ) == silk_MUL( Fs_Hz_in, 3 ) ) {             /* Fs_out : Fs_in = 3 : 4 */
             S->FIR_Fracs = 3;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
             S->Coefs = silk_Resampler_3_4_COEFS;
-            S->resampler_function = USE_silk_resampler_private_down_FIR;
         } else if( silk_MUL( Fs_Hz_out, 3 ) == silk_MUL( Fs_Hz_in, 2 ) ) {      /* Fs_out : Fs_in = 2 : 3 */
             S->FIR_Fracs = 2;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0;
             S->Coefs = silk_Resampler_2_3_COEFS;
-            S->resampler_function = USE_silk_resampler_private_down_FIR;
         } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) {                     /* Fs_out : Fs_in = 1 : 2 */
             S->FIR_Fracs = 1;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1;
             S->Coefs = silk_Resampler_1_2_COEFS;
-            S->resampler_function = USE_silk_resampler_private_down_FIR;
         } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) {                     /* Fs_out : Fs_in = 1 : 3 */
             S->FIR_Fracs = 1;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
             S->Coefs = silk_Resampler_1_3_COEFS;
-            S->resampler_function = USE_silk_resampler_private_down_FIR;
         } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) {                     /* Fs_out : Fs_in = 1 : 4 */
             S->FIR_Fracs = 1;
-            down2 = 1;
-            S->Coefs = silk_Resampler_1_2_COEFS;
-            S->resampler_function = USE_silk_resampler_private_down_FIR;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
+            S->Coefs = silk_Resampler_1_4_COEFS;
         } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) {                     /* Fs_out : Fs_in = 1 : 6 */
             S->FIR_Fracs = 1;
-            down2 = 1;
-            S->Coefs = silk_Resampler_1_3_COEFS;
-            S->resampler_function = USE_silk_resampler_private_down_FIR;
+            S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2;
+            S->Coefs = silk_Resampler_1_6_COEFS;
         } else {
             /* None available */
             silk_assert( 0 );
@@ -129,12 +159,10 @@ opus_int silk_resampler_init(
         S->resampler_function = USE_silk_resampler_copy;
     }
 
-    S->input2x = up2 | down2;
-
     /* Ratio of input/output samples */
-    S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2 - down2 ), Fs_Hz_out ), 2 );
+    S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2x ), Fs_Hz_out ), 2 );
     /* Make sure the ratio is rounded up */
-    while( silk_SMULWW( S->invRatio_Q16, silk_LSHIFT32( Fs_Hz_out, down2 ) ) < silk_LSHIFT32( Fs_Hz_in, up2 ) ) {
+    while( silk_SMULWW( S->invRatio_Q16, Fs_Hz_out ) < silk_LSHIFT32( Fs_Hz_in, up2x ) ) {
         S->invRatio_Q16++;
     }
 
@@ -142,26 +170,46 @@ opus_int silk_resampler_init(
 }
 
 /* Resampler: convert from one sampling rate to another */
+/* Input and output sampling rate are at most 48000 Hz  */
 opus_int silk_resampler(
-    silk_resampler_state_struct *S,                 /* I/O   Resampler state                                            */
-    opus_int16                  out[],              /* O     Output signal                                              */
-    const opus_int16            in[],               /* I     Input signal                                               */
-    opus_int32                  inLen               /* I     Number of input samples                                    */
+    silk_resampler_state_struct *S,                 /* I/O  Resampler state                                             */
+    opus_int16                  out[],              /* O    Output signal                                               */
+    const opus_int16            in[],               /* I    Input signal                                                */
+    opus_int32                  inLen               /* I    Number of input samples                                     */
 )
 {
-    /* Input and output sampling rate are at most 48000 Hz */
+    opus_int nSamples;
+
+    /* Need at least 1 ms of input data */
+    silk_assert( inLen >= S->Fs_in_kHz );
+    /* Delay can't exceed the 1 ms of buffering */
+    silk_assert( S->inputDelay <= S->Fs_in_kHz );
+
+    nSamples = S->Fs_in_kHz - S->inputDelay;
+
+    /* Copy to delay buffer */
+    silk_memcpy( &S->delayBuf[ S->inputDelay ], in, nSamples * sizeof( opus_int16 ) );
+
     switch( S->resampler_function ) {
         case USE_silk_resampler_private_up2_HQ_wrapper:
-            silk_resampler_private_up2_HQ_wrapper( S, out, in, inLen );
+            silk_resampler_private_up2_HQ_wrapper( S, out, S->delayBuf, S->Fs_in_kHz );
+            silk_resampler_private_up2_HQ_wrapper( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
             break;
         case USE_silk_resampler_private_IIR_FIR:
-            silk_resampler_private_IIR_FIR( S, out, in, inLen );
+            silk_resampler_private_IIR_FIR( S, out, S->delayBuf, S->Fs_in_kHz );
+            silk_resampler_private_IIR_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
             break;
         case USE_silk_resampler_private_down_FIR:
-            silk_resampler_private_down_FIR( S, out, in, inLen );
+            silk_resampler_private_down_FIR( S, out, S->delayBuf, S->Fs_in_kHz );
+            silk_resampler_private_down_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz );
             break;
         default:
-            silk_memcpy( out, in, inLen * sizeof( opus_int16 ) );
+            silk_memcpy( out, S->delayBuf, S->Fs_in_kHz * sizeof( opus_int16 ) );
+            silk_memcpy( &out[ S->Fs_out_kHz ], &in[ nSamples ], ( inLen - S->Fs_in_kHz ) * sizeof( opus_int16 ) );
     }
+
+    /* Copy to delay buffer */
+    silk_memcpy( S->delayBuf, &in[ inLen - S->inputDelay ], S->inputDelay * sizeof( opus_int16 ) );
+
     return 0;
 }
index fe33d35..3f6a8f9 100644 (file)
@@ -32,7 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "SigProc_FIX.h"
 #include "resampler_rom.h"
 
-/* Downsample by a factor 2, mediocre quality */
+/* Downsample by a factor 2 */
 void silk_resampler_down2(
     opus_int32                  *S,                 /* I/O  State vector [ 2 ]                                          */
     opus_int16                  *out,               /* O    Output signal [ len ]                                       */
index 9e14c0f..96fe83e 100644 (file)
@@ -25,8 +25,8 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/
 
-#ifndef SILK_RESAMPLER_H
-#define SILK_RESAMPLER_H
+#ifndef SILK_RESAMPLER_PRIVATE_H
+#define SILK_RESAMPLER_PRIVATE_H
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,7 +37,9 @@ extern "C" {
 #include "resampler_rom.h"
 
 /* Number of input samples to process in the inner loop */
-#define RESAMPLER_MAX_BATCH_SIZE_IN             480
+#define RESAMPLER_MAX_BATCH_SIZE_MS             10
+#define RESAMPLER_MAX_FS_KHZ                    48
+#define RESAMPLER_MAX_BATCH_SIZE_IN             ( RESAMPLER_MAX_BATCH_SIZE_MS * RESAMPLER_MAX_FS_KHZ )
 
 /* Description: Hybrid IIR/FIR polyphase implementation of resampling */
 void silk_resampler_private_IIR_FIR(
@@ -83,4 +85,4 @@ void silk_resampler_private_AR2(
 #ifdef __cplusplus
 }
 #endif
-#endif /* SILK_RESAMPLER_H */
+#endif /* SILK_RESAMPLER_PRIVATE_H */
index 725f857..f17fb5c 100644 (file)
@@ -45,15 +45,17 @@ static inline opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL(
 
     /* Interpolate upsampled signal and store in output array */
     for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
-        table_index = silk_SMULWB( index_Q16 & 0xFFFF, 144 );
+        table_index = silk_SMULWB( index_Q16 & 0xFFFF, 12 );
         buf_ptr = &buf[ index_Q16 >> 16 ];
 
-        res_Q15 = silk_SMULBB(          buf_ptr[ 0 ], silk_resampler_frac_FIR_144[       table_index ][ 0 ] );
-        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_144[       table_index ][ 1 ] );
-        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_144[       table_index ][ 2 ] );
-        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 2 ] );
-        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 1 ] );
-        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_144[ 143 - table_index ][ 0 ] );
+        res_Q15 = silk_SMULBB(          buf_ptr[ 0 ], silk_resampler_frac_FIR_12[      table_index ][ 0 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_12[      table_index ][ 1 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_12[      table_index ][ 2 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_12[      table_index ][ 3 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 3 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 2 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 6 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 1 ] );
+        res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 7 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 0 ] );
         *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q15, 15 ) );
     }
     return out;
@@ -69,34 +71,33 @@ void silk_resampler_private_IIR_FIR(
     silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
     opus_int32 nSamplesIn;
     opus_int32 max_index_Q16, index_increment_Q16;
-    opus_int16 buf[ 2 * RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_144 ];
+    opus_int16 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_ORDER_FIR_12 ];
 
     /* Copy buffered samples to start of buffer */
-    silk_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) );
+    silk_memcpy( buf, S->sFIR, RESAMPLER_ORDER_FIR_12 * sizeof( opus_int32 ) );
 
     /* Iterate over blocks of frameSizeIn input samples */
     index_increment_Q16 = S->invRatio_Q16;
     while( 1 ) {
         nSamplesIn = silk_min( inLen, S->batchSize );
 
-        silk_assert( S->input2x );
         /* Upsample 2x */
-        silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_144 ], in, nSamplesIn );
+        silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_12 ], in, nSamplesIn );
 
-        max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + S->input2x );         /* +1 if 2x upsampling */
-        out = silk_resampler_private_IIR_FIR_INTERPOL(out, buf, max_index_Q16, index_increment_Q16);
+        max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + 1 );         /* + 1 because 2x upsampling */
+        out = silk_resampler_private_IIR_FIR_INTERPOL( out, buf, max_index_Q16, index_increment_Q16 );
         in += nSamplesIn;
         inLen -= nSamplesIn;
 
         if( inLen > 0 ) {
             /* More iterations to do; copy last part of filtered signal to beginning of buffer */
-            silk_memcpy( buf, &buf[ nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) );
+            silk_memcpy( buf, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int32 ) );
         } else {
             break;
         }
     }
 
     /* Copy last part of filtered signal to the state for the next call */
-    silk_memcpy( S->sFIR, &buf[nSamplesIn << S->input2x ], RESAMPLER_ORDER_FIR_144 * sizeof( opus_int32 ) );
+    silk_memcpy( S->sFIR, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int32 ) );
 }
 
index b9c2519..d1ee15a 100644 (file)
@@ -32,86 +32,115 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "SigProc_FIX.h"
 #include "resampler_private.h"
 
-static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL0(
+static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL(
     opus_int16          *out, 
-    opus_int32          *buf2
+    opus_int32          *buf, 
     const opus_int16    *FIR_Coefs, 
+    opus_int            FIR_Order,
+    opus_int            FIR_Fracs,
     opus_int32          max_index_Q16, 
     opus_int32          index_increment_Q16
 )
 {
     opus_int32 index_Q16, res_Q6;
     opus_int32 *buf_ptr;
-
-    for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
-        /* Integer part gives pointer to buffered input */
-        buf_ptr = buf2 + silk_RSHIFT( index_Q16, 16 );
-
-        /* Inner product */
-        res_Q6 = silk_SMULWB(         silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 15 ] ), FIR_Coefs[ 0 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 14 ] ), FIR_Coefs[ 1 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 13 ] ), FIR_Coefs[ 2 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 12 ] ), FIR_Coefs[ 3 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 11 ] ), FIR_Coefs[ 4 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 10 ] ), FIR_Coefs[ 5 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[  9 ] ), FIR_Coefs[ 6 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[  8 ] ), FIR_Coefs[ 7 ] );
-
-        /* Scale down, saturate and store in output array */
-        *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
-    }
-    return out;
-}
-
-static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL1(
-    opus_int16          *out, 
-    opus_int32          *buf2, 
-    const opus_int16    *FIR_Coefs, 
-    opus_int32          max_index_Q16, 
-    opus_int32          index_increment_Q16, 
-    opus_int32          FIR_Fracs
-)
-{
-    opus_int32 index_Q16, res_Q6;
-    opus_int32 *buf_ptr;
     opus_int32 interpol_ind;
     const opus_int16 *interpol_ptr;
 
-    for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
-        /* Integer part gives pointer to buffered input */
-        buf_ptr = buf2 + silk_RSHIFT( index_Q16, 16 );
-
-        /* Fractional part gives interpolation coefficients */
-        interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
-
-        /* Inner product */
-        interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * interpol_ind ];
-        res_Q6 = silk_SMULWB(         buf_ptr[ 0 ], interpol_ptr[ 0 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] );
-        interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * ( FIR_Fracs - 1 - interpol_ind ) ];
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 0 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 1 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 2 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 3 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 4 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 5 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[  9 ], interpol_ptr[ 6 ] );
-        res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[  8 ], interpol_ptr[ 7 ] );
-
-        /* Scale down, saturate and store in output array */
-        *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+    switch( FIR_Order ) {
+        case RESAMPLER_DOWN_ORDER_FIR0:
+            for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+                /* Integer part gives pointer to buffered input */
+                buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+                /* Fractional part gives interpolation coefficients */
+                interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
+
+                /* Inner product */
+                interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind ];
+                res_Q6 = silk_SMULWB(         buf_ptr[ 0 ], interpol_ptr[ 0 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 8 ] );
+                interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * ( FIR_Fracs - 1 - interpol_ind ) ];
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 17 ], interpol_ptr[ 0 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 16 ], interpol_ptr[ 1 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 2 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 3 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 4 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 5 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 6 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 7 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[  9 ], interpol_ptr[ 8 ] );
+
+                /* Scale down, saturate and store in output array */
+                *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+            }
+            break;
+        case RESAMPLER_DOWN_ORDER_FIR1:
+            for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+                /* Integer part gives pointer to buffered input */
+                buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+                /* Inner product */
+                res_Q6 = silk_SMULWB(         silk_ADD32( buf_ptr[  0 ], buf_ptr[ 23 ] ), FIR_Coefs[  0 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  1 ], buf_ptr[ 22 ] ), FIR_Coefs[  1 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  2 ], buf_ptr[ 21 ] ), FIR_Coefs[  2 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  3 ], buf_ptr[ 20 ] ), FIR_Coefs[  3 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  4 ], buf_ptr[ 19 ] ), FIR_Coefs[  4 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  5 ], buf_ptr[ 18 ] ), FIR_Coefs[  5 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  6 ], buf_ptr[ 17 ] ), FIR_Coefs[  6 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  7 ], buf_ptr[ 16 ] ), FIR_Coefs[  7 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  8 ], buf_ptr[ 15 ] ), FIR_Coefs[  8 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  9 ], buf_ptr[ 14 ] ), FIR_Coefs[  9 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 13 ] ), FIR_Coefs[ 10 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 12 ] ), FIR_Coefs[ 11 ] );
+
+                /* Scale down, saturate and store in output array */
+                *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+            }
+            break;
+        case RESAMPLER_DOWN_ORDER_FIR2:
+            for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
+                /* Integer part gives pointer to buffered input */
+                buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
+
+                /* Inner product */
+                res_Q6 = silk_SMULWB(         silk_ADD32( buf_ptr[  0 ], buf_ptr[ 35 ] ), FIR_Coefs[  0 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  1 ], buf_ptr[ 34 ] ), FIR_Coefs[  1 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  2 ], buf_ptr[ 33 ] ), FIR_Coefs[  2 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  3 ], buf_ptr[ 32 ] ), FIR_Coefs[  3 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  4 ], buf_ptr[ 31 ] ), FIR_Coefs[  4 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  5 ], buf_ptr[ 30 ] ), FIR_Coefs[  5 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  6 ], buf_ptr[ 29 ] ), FIR_Coefs[  6 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  7 ], buf_ptr[ 28 ] ), FIR_Coefs[  7 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  8 ], buf_ptr[ 27 ] ), FIR_Coefs[  8 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[  9 ], buf_ptr[ 26 ] ), FIR_Coefs[  9 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 25 ] ), FIR_Coefs[ 10 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 24 ] ), FIR_Coefs[ 11 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 12 ], buf_ptr[ 23 ] ), FIR_Coefs[ 12 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 13 ], buf_ptr[ 22 ] ), FIR_Coefs[ 13 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 14 ], buf_ptr[ 21 ] ), FIR_Coefs[ 14 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 15 ], buf_ptr[ 20 ] ), FIR_Coefs[ 15 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 16 ], buf_ptr[ 19 ] ), FIR_Coefs[ 16 ] );
+                res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 17 ], buf_ptr[ 18 ] ), FIR_Coefs[ 17 ] );
+
+                /* Scale down, saturate and store in output array */
+                *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
+            }
+            break;
+        default:
+            silk_assert( 0 );
     }
     return out;
 }
 
-
-/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */
+/* Resample with a 2nd order AR filter followed by FIR interpolation */
 void silk_resampler_private_down_FIR(
     void                            *SS,            /* I/O  Resampler state             */
     opus_int16                      out[],          /* O    Output signal               */
@@ -122,12 +151,11 @@ void silk_resampler_private_down_FIR(
     silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
     opus_int32 nSamplesIn;
     opus_int32 max_index_Q16, index_increment_Q16;
-    opus_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ];
-    opus_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ];
+    opus_int32 buf[ RESAMPLER_MAX_BATCH_SIZE_IN + SILK_RESAMPLER_MAX_FIR_ORDER ];
     const opus_int16 *FIR_Coefs;
 
     /* Copy buffered samples to start of buffer */
-    silk_memcpy( buf2, S->sFIR, RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );
+    silk_memcpy( buf, S->sFIR, S->FIR_Order * sizeof( opus_int32 ) );
 
     FIR_Coefs = &S->Coefs[ 2 ];
 
@@ -136,40 +164,26 @@ void silk_resampler_private_down_FIR(
     while( 1 ) {
         nSamplesIn = silk_min( inLen, S->batchSize );
 
-        if( S->input2x == 1 ) {
-            /* Downsample 2x */
-            silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn );
-
-            nSamplesIn = silk_RSHIFT32( nSamplesIn, 1 );
-
-            /* Second-order AR filter (output in Q8) */
-            silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn );
-        } else {
-            /* Second-order AR filter (output in Q8) */
-            silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], in, S->Coefs, nSamplesIn );
-        }
+        /* Second-order AR filter (output in Q8) */
+        silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, S->Coefs, nSamplesIn );
 
         max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 );
 
         /* Interpolate filtered signal */
-        if( S->FIR_Fracs == 1 ) {
-            out = silk_resampler_private_down_FIR_INTERPOL0(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16);
-        } else {
-            out = silk_resampler_private_down_FIR_INTERPOL1(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16, S->FIR_Fracs);
-        }
+        out = silk_resampler_private_down_FIR_INTERPOL( out, buf, FIR_Coefs, S->FIR_Order, 
+            S->FIR_Fracs, max_index_Q16, index_increment_Q16 );
 
-        in += nSamplesIn << S->input2x;
-        inLen -= nSamplesIn << S->input2x;
+        in += nSamplesIn;
+        inLen -= nSamplesIn;
 
-        if( inLen > S->input2x ) {
+        if( inLen > 1 ) {
             /* More iterations to do; copy last part of filtered signal to beginning of buffer */
-            silk_memcpy( buf2, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );
+            silk_memcpy( buf, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
         } else {
             break;
         }
     }
 
     /* Copy last part of filtered signal to the state for the next call */
-    silk_memcpy( S->sFIR, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );
+    silk_memcpy( S->sFIR, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
 }
-
index 05e6afb..09dc9c7 100644 (file)
@@ -46,9 +46,11 @@ void silk_resampler_private_up2_HQ(
     opus_int32 in32, out32_1, out32_2, Y, X;
 
     silk_assert( silk_resampler_up2_hq_0[ 0 ] > 0 );
-    silk_assert( silk_resampler_up2_hq_0[ 1 ] < 0 );
+    silk_assert( silk_resampler_up2_hq_0[ 1 ] > 0 );
+    silk_assert( silk_resampler_up2_hq_0[ 2 ] < 0 );
     silk_assert( silk_resampler_up2_hq_1[ 0 ] > 0 );
-    silk_assert( silk_resampler_up2_hq_1[ 1 ] < 0 );
+    silk_assert( silk_resampler_up2_hq_1[ 1 ] > 0 );
+    silk_assert( silk_resampler_up2_hq_1[ 2 ] < 0 );
 
     /* Internal variables and state are in Q10 format */
     for( k = 0; k < len; k++ ) {
@@ -63,41 +65,39 @@ void silk_resampler_private_up2_HQ(
 
         /* Second all-pass section for even output sample */
         Y       = silk_SUB32( out32_1, S[ 1 ] );
-        X       = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 1 ] );
+        X       = silk_SMULWB( Y, silk_resampler_up2_hq_0[ 1 ] );
         out32_2 = silk_ADD32( S[ 1 ], X );
         S[ 1 ]  = silk_ADD32( out32_1, X );
 
-        /* Biquad notch filter */
-        out32_2 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 2 ] );
-        out32_2 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 1 ] );
-        out32_1 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 0 ] );
-        S[ 5 ]  = silk_SUB32(  out32_2, S[ 5 ] );
+        /* Third all-pass section for even output sample */
+        Y       = silk_SUB32( out32_2, S[ 2 ] );
+        X       = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_0[ 2 ] );
+        out32_1 = silk_ADD32( S[ 2 ], X );
+        S[ 2 ]  = silk_ADD32( out32_2, X );
 
         /* Apply gain in Q15, convert back to int16 and store to output */
-        out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT32(
-            silk_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) );
+        out[ 2 * k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) );
 
         /* First all-pass section for odd output sample */
-        Y       = silk_SUB32( in32, S[ 2 ] );
+        Y       = silk_SUB32( in32, S[ 3 ] );
         X       = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 0 ] );
-        out32_1 = silk_ADD32( S[ 2 ], X );
-        S[ 2 ]  = silk_ADD32( in32, X );
+        out32_1 = silk_ADD32( S[ 3 ], X );
+        S[ 3 ]  = silk_ADD32( in32, X );
 
         /* Second all-pass section for odd output sample */
-        Y       = silk_SUB32( out32_1, S[ 3 ] );
-        X       = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 1 ] );
-        out32_2 = silk_ADD32( S[ 3 ], X );
-        S[ 3 ]  = silk_ADD32( out32_1, X );
+        Y       = silk_SUB32( out32_1, S[ 4 ] );
+        X       = silk_SMULWB( Y, silk_resampler_up2_hq_1[ 1 ] );
+        out32_2 = silk_ADD32( S[ 4 ], X );
+        S[ 4 ]  = silk_ADD32( out32_1, X );
 
-        /* Biquad notch filter */
-        out32_2 = silk_SMLAWB( out32_2, S[ 4 ], silk_resampler_up2_hq_notch[ 2 ] );
-        out32_2 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 1 ] );
-        out32_1 = silk_SMLAWB( out32_2, S[ 5 ], silk_resampler_up2_hq_notch[ 0 ] );
-        S[ 4 ]  = silk_SUB32(  out32_2, S[ 4 ] );
+        /* Third all-pass section for odd output sample */
+        Y       = silk_SUB32( out32_2, S[ 5 ] );
+        X       = silk_SMLAWB( Y, Y, silk_resampler_up2_hq_1[ 2 ] );
+        out32_1 = silk_ADD32( S[ 5 ], X );
+        S[ 5 ]  = silk_ADD32( out32_2, X );
 
         /* Apply gain in Q15, convert back to int16 and store to output */
-        out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT32(
-            silk_SMLAWB( 256, out32_1, silk_resampler_up2_hq_notch[ 3 ] ), 9 ) );
+        out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( out32_1, 10 ) );
     }
 }
 
index 15473e0..9c4750c 100644 (file)
@@ -30,7 +30,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endif
 
 /* Filter coefficients for IIR/FIR polyphase resampling     *
- * Total size: < 600 Words (1.2 kB)                         */
+ * Total size: 179 Words (358 Bytes)                        */
 
 #include "resampler_private.h"
 
@@ -39,32 +39,46 @@ const opus_int16 silk_resampler_down2_0 = 9872;
 const opus_int16 silk_resampler_down2_1 = 39809 - 65536;
 
 /* Tables for 2x upsampler, high quality */
-const opus_int16 silk_resampler_up2_hq_0[ 2 ] = {  4280, 33727 - 65536 };
-const opus_int16 silk_resampler_up2_hq_1[ 2 ] = { 16295, 54015 - 65536 };
-const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 6554,  -3932,   6554,  30573 };
+const opus_int16 silk_resampler_up2_hq_0[ 3 ] = { 1746, 14986, 39083 - 65536 };
+const opus_int16 silk_resampler_up2_hq_1[ 3 ] = { 6854, 25769, 55542 - 65536 };
 
-/* Tables with IIR and FIR coefficients for fractional downsamplers (90 Words) */
-silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = {
-    -20253, -13986,
-        86,      7,   -151,    368,   -542,    232,  11041,  21904,
-        39,     90,   -181,    216,    -17,   -877,   6408,  19695,
-         2,    113,   -108,      2,    314,   -977,   2665,  15787,
+/* Matlab code for the notch filter coefficients: */
+/* B = [1, 0.147, 1];  A = [1, 0.107, 0.89]; G = 0.93; freqz(G * B, A, 2^14, 16e3); axis([0, 8000, -10, 1]) */
+/* fprintf('\t%6d, %6d, %6d, %6d\n', round(B(2)*2^16), round(-A(2)*2^16), round((1-A(3))*2^16), round(G*2^15)) */
+const opus_int16 silk_resampler_up2_hq_notch[ 4 ] = { 9634,  -7012,   7209,  30474 };
+
+/* Tables with IIR and FIR coefficients for fractional downsamplers (123 Words) */
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
+       -20694, -13867,
+          -49,     64,     17,   -157,    353,   -496,    163,  11047,  22205,
+          -39,      6,     91,   -170,    186,     23,   -896,   6336,  19928,
+          -19,    -36,    102,    -89,    -24,    328,   -951,   2568,  15909,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ] = {
+       -14457, -14019,
+           64,    128,   -122,     36,    310,   -768,    584,   9267,  17733,
+           12,    128,     18,   -142,    288,   -117,   -865,   4123,  14459,
+};
+
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR1 / 2 ] = {
+          616, -14323,
+          -10,     39,     58,    -46,    -84,    120,    184,   -315,   -541,   1284,   5380,   9024,
 };
 
-silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ] = {
-    -13997, -14120,
-        60,   -174,     71,    298,   -800,    659,   9238,  17461,
-        48,    -40,   -150,    314,   -155,   -845,   4188,  14293,
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+        16102, -15162,
+          -13,      0,     20,     26,      5,    -31,    -43,     -4,     65,     90,      7,   -157,   -248,    -44,    593,   1583,   2612,   3271,
 };
 
-silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_2_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = {
-      1233, -14293,
-       -91,    162,    169,   -342,   -505,   1332,   5281,   8742,
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_4_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+        22500, -15099,
+            3,    -14,    -20,    -15,      2,     25,     37,     25,    -16,    -71,   -107,    -79,     50,    292,    623,    982,   1288,   1464,
 };
 
-silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_3_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR / 2 ] = {
-     16306, -14409,
-        99,   -201,   -220,    -16,    572,   1483,   2433,   3043,
+silk_DWORD_ALIGN const opus_int16 silk_Resampler_1_6_COEFS[ 2 + RESAMPLER_DOWN_ORDER_FIR2 / 2 ] = {
+        27540, -15257,
+           17,     12,      8,      1,    -10,    -22,    -30,    -32,    -22,      3,     44,    100,    168,    243,    317,    381,    429,    455,
 };
 
 silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
@@ -73,150 +87,18 @@ silk_DWORD_ALIGN const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ] = {
       1567,   8276,
 };
 
-/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */
-silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ] = {
-    {  -25,    58, 32526},
-    {   -8,   -69, 32461},
-    {    8,  -195, 32393},
-    {   25,  -318, 32321},
-    {   41,  -439, 32244},
-    {   57,  -557, 32163},
-    {   72,  -673, 32079},
-    {   88,  -787, 31990},
-    {  103,  -899, 31897},
-    {  118, -1009, 31801},
-    {  133, -1116, 31700},
-    {  148, -1221, 31596},
-    {  162, -1324, 31488},
-    {  177, -1424, 31376},
-    {  191, -1522, 31260},
-    {  205, -1618, 31140},
-    {  218, -1712, 31017},
-    {  231, -1803, 30890},
-    {  245, -1893, 30759},
-    {  257, -1980, 30625},
-    {  270, -2065, 30487},
-    {  282, -2147, 30346},
-    {  295, -2228, 30201},
-    {  306, -2306, 30052},
-    {  318, -2382, 29900},
-    {  330, -2456, 29745},
-    {  341, -2528, 29586},
-    {  352, -2597, 29424},
-    {  362, -2664, 29259},
-    {  373, -2730, 29090},
-    {  383, -2793, 28918},
-    {  393, -2854, 28743},
-    {  402, -2912, 28565},
-    {  411, -2969, 28384},
-    {  421, -3024, 28199},
-    {  429, -3076, 28012},
-    {  438, -3126, 27822},
-    {  446, -3175, 27628},
-    {  454, -3221, 27432},
-    {  462, -3265, 27233},
-    {  469, -3307, 27031},
-    {  476, -3348, 26826},
-    {  483, -3386, 26619},
-    {  490, -3422, 26409},
-    {  496, -3456, 26196},
-    {  502, -3488, 25981},
-    {  508, -3518, 25763},
-    {  514, -3547, 25543},
-    {  519, -3573, 25320},
-    {  524, -3597, 25095},
-    {  529, -3620, 24867},
-    {  533, -3640, 24637},
-    {  538, -3659, 24405},
-    {  541, -3676, 24171},
-    {  545, -3691, 23934},
-    {  548, -3704, 23696},
-    {  552, -3716, 23455},
-    {  554, -3726, 23212},
-    {  557, -3733, 22967},
-    {  559, -3740, 22721},
-    {  561, -3744, 22472},
-    {  563, -3747, 22222},
-    {  565, -3748, 21970},
-    {  566, -3747, 21716},
-    {  567, -3745, 21460},
-    {  568, -3741, 21203},
-    {  568, -3735, 20944},
-    {  568, -3728, 20684},
-    {  568, -3719, 20422},
-    {  568, -3708, 20159},
-    {  568, -3697, 19894},
-    {  567, -3683, 19628},
-    {  566, -3668, 19361},
-    {  564, -3652, 19093},
-    {  563, -3634, 18823},
-    {  561, -3614, 18552},
-    {  559, -3594, 18280},
-    {  557, -3571, 18008},
-    {  554, -3548, 17734},
-    {  552, -3523, 17459},
-    {  549, -3497, 17183},
-    {  546, -3469, 16907},
-    {  542, -3440, 16630},
-    {  539, -3410, 16352},
-    {  535, -3379, 16074},
-    {  531, -3346, 15794},
-    {  527, -3312, 15515},
-    {  522, -3277, 15235},
-    {  517, -3241, 14954},
-    {  513, -3203, 14673},
-    {  507, -3165, 14392},
-    {  502, -3125, 14110},
-    {  497, -3085, 13828},
-    {  491, -3043, 13546},
-    {  485, -3000, 13264},
-    {  479, -2957, 12982},
-    {  473, -2912, 12699},
-    {  466, -2867, 12417},
-    {  460, -2820, 12135},
-    {  453, -2772, 11853},
-    {  446, -2724, 11571},
-    {  439, -2675, 11289},
-    {  432, -2625, 11008},
-    {  424, -2574, 10727},
-    {  417, -2522, 10446},
-    {  409, -2470, 10166},
-    {  401, -2417,  9886},
-    {  393, -2363,  9607},
-    {  385, -2309,  9328},
-    {  376, -2253,  9050},
-    {  368, -2198,  8773},
-    {  359, -2141,  8497},
-    {  351, -2084,  8221},
-    {  342, -2026,  7946},
-    {  333, -1968,  7672},
-    {  324, -1910,  7399},
-    {  315, -1850,  7127},
-    {  305, -1791,  6856},
-    {  296, -1731,  6586},
-    {  286, -1670,  6317},
-    {  277, -1609,  6049},
-    {  267, -1548,  5783},
-    {  257, -1486,  5517},
-    {  247, -1424,  5254},
-    {  237, -1362,  4991},
-    {  227, -1300,  4730},
-    {  217, -1237,  4470},
-    {  207, -1174,  4212},
-    {  197, -1110,  3956},
-    {  187, -1047,  3701},
-    {  176,  -984,  3448},
-    {  166,  -920,  3196},
-    {  155,  -856,  2946},
-    {  145,  -792,  2698},
-    {  134,  -728,  2452},
-    {  124,  -664,  2207},
-    {  113,  -600,  1965},
-    {  102,  -536,  1724},
-    {   92,  -472,  1486},
-    {   81,  -408,  1249},
-    {   70,  -345,  1015},
-    {   60,  -281,   783},
-    {   49,  -217,   553},
-    {   38,  -154,   325},
+/* Table with interplation fractions of 1/24, 3/24, 5/24, ... , 23/24 : 23/24 (46 Words) */
+silk_DWORD_ALIGN const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ] = {
+       {  189,  -600,   617, 30567 },
+       {  117,  -159, -1070, 29704 },
+       {   52,   221, -2392, 28276 },
+       {   -4,   529, -3350, 26341 },
+       {  -48,   758, -3956, 23973 },
+       {  -80,   905, -4235, 21254 },
+       {  -99,   972, -4222, 18278 },
+       { -107,   967, -3957, 15143 },
+       { -103,   896, -3487, 11950 },
+       {  -91,   773, -2865,  8798 },
+       {  -71,   611, -2143,  5784 },
+       {  -46,   425, -1375,  2996 },
 };
index e273d64..c1ff59e 100644 (file)
@@ -36,27 +36,30 @@ extern "C"
 #include "typedef.h"
 #include "resampler_structs.h"
 
-#define RESAMPLER_DOWN_ORDER_FIR                16
-#define RESAMPLER_ORDER_FIR_144                 6
+#define RESAMPLER_DOWN_ORDER_FIR0               18
+#define RESAMPLER_DOWN_ORDER_FIR1               24
+#define RESAMPLER_DOWN_ORDER_FIR2               36
+#define RESAMPLER_ORDER_FIR_12                  8
 
-/* Tables for 2x downsampler. Values above 32767 intentionally wrap to a negative value. */
+/* Tables for 2x downsampler */
 extern const opus_int16 silk_resampler_down2_0;
 extern const opus_int16 silk_resampler_down2_1;
 
-/* Tables for 2x upsampler, high quality. Values above 32767 intentionally wrap to a negative value. */
-extern const opus_int16 silk_resampler_up2_hq_0[ 2 ];
-extern const opus_int16 silk_resampler_up2_hq_1[ 2 ];
-extern const opus_int16 silk_resampler_up2_hq_notch[ 4 ];
+/* Tables for 2x upsampler, high quality */
+extern const opus_int16 silk_resampler_up2_hq_0[ 3 ];
+extern const opus_int16 silk_resampler_up2_hq_1[ 3 ];
 
 /* Tables with IIR and FIR coefficients for fractional downsamplers */
-extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR / 2 ];
-extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR / 2 ];
-extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR / 2 ];
-extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR / 2 ];
+extern const opus_int16 silk_Resampler_3_4_COEFS[ 2 + 3 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ];
+extern const opus_int16 silk_Resampler_2_3_COEFS[ 2 + 2 * RESAMPLER_DOWN_ORDER_FIR0 / 2 ];
+extern const opus_int16 silk_Resampler_1_2_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR1 / 2 ];
+extern const opus_int16 silk_Resampler_1_3_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
+extern const opus_int16 silk_Resampler_1_4_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
+extern const opus_int16 silk_Resampler_1_6_COEFS[ 2 +     RESAMPLER_DOWN_ORDER_FIR2 / 2 ];
 extern const opus_int16 silk_Resampler_2_3_COEFS_LQ[ 2 + 2 * 2 ];
 
-/* Table with interplation fractions of 1/288 : 2/288 : 287/288 (432 Words) */
-extern const opus_int16 silk_resampler_frac_FIR_144[ 144 ][ RESAMPLER_ORDER_FIR_144 / 2 ];
+/* Table with interplation fractions of 1/24, 3/24, ..., 23/24 */
+extern const opus_int16 silk_resampler_frac_FIR_12[ 12 ][ RESAMPLER_ORDER_FIR_12 / 2 ];
 
 #ifdef  __cplusplus
 }
index eb2844d..e5289ef 100644 (file)
@@ -32,18 +32,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 extern "C" {
 #endif
 
-#define SILK_RESAMPLER_MAX_FIR_ORDER                 16
+#define SILK_RESAMPLER_MAX_FIR_ORDER                 36
 #define SILK_RESAMPLER_MAX_IIR_ORDER                 6
 
 typedef struct _silk_resampler_state_struct{
     opus_int32       sIIR[ SILK_RESAMPLER_MAX_IIR_ORDER ]; /* this must be the first element of this struct */
     opus_int32       sFIR[ SILK_RESAMPLER_MAX_FIR_ORDER ];
-    opus_int32       sDown2[ 2 ];
-    opus_int32       resampler_function;
-    opus_int32       batchSize;
+    opus_int16       delayBuf[ 48 ];
+    opus_int         resampler_function;
+    opus_int         batchSize;
     opus_int32       invRatio_Q16;
-    opus_int32       FIR_Fracs;
-    opus_int32       input2x;
+    opus_int         FIR_Order;
+    opus_int         FIR_Fracs;
+    opus_int         Fs_in_kHz;
+    opus_int         Fs_out_kHz;
+    opus_int         inputDelay;
     const opus_int16 *Coefs;
 } silk_resampler_state_struct;
 
index df600e6..bc20394 100644 (file)
@@ -198,9 +198,9 @@ void silk_stereo_LR_to_MS(
         pred0_Q13 += delta0_Q13;
         pred1_Q13 += delta1_Q13;
         w_Q24   += deltaw_Q24;
-        sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 );      /* Q11 */
-        sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 );                 /* Q8  */
-        sum = silk_SMLAWB( sum, silk_LSHIFT( ( opus_int32 )mid[ n + 1 ], 11 ), pred1_Q13 );        /* Q8  */
+        sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 );    /* Q11 */
+        sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 );               /* Q8  */
+        sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 );       /* Q8  */
         x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
     }
 
@@ -208,9 +208,9 @@ void silk_stereo_LR_to_MS(
     pred1_Q13 = -pred_Q13[ 1 ];
     w_Q24     =  silk_LSHIFT( width_Q14, 10 );
     for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) {
-        sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 );      /* Q11 */
-        sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 );                 /* Q8  */
-        sum = silk_SMLAWB( sum, silk_LSHIFT( ( opus_int32 )mid[ n + 1 ], 11 ), pred1_Q13 );        /* Q8  */
+        sum = silk_LSHIFT( silk_ADD_LSHIFT( mid[ n ] + mid[ n + 2 ], mid[ n + 1 ], 1 ), 9 );    /* Q11 */
+        sum = silk_SMLAWB( silk_SMULWB( w_Q24, side[ n + 1 ] ), sum, pred0_Q13 );               /* Q8  */
+        sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)mid[ n + 1 ], 11 ), pred1_Q13 );       /* Q8  */
         x2[ n - 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
     }
     state->pred_prev_Q13[ 0 ] = (opus_int16)pred_Q13[ 0 ];
index e95e47b..a9f105b 100644 (file)
@@ -59,17 +59,17 @@ void silk_stereo_MS_to_LR(
     for( n = 0; n < STEREO_INTERP_LEN_MS * fs_kHz; n++ ) {
         pred0_Q13 += delta0_Q13;
         pred1_Q13 += delta1_Q13;
-        sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 );         /* Q11 */
-        sum = silk_SMLAWB( silk_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 );          /* Q8  */
-        sum = silk_SMLAWB( sum, silk_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 );         /* Q8  */
+        sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 );       /* Q11 */
+        sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 );         /* Q8  */
+        sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 );        /* Q8  */
         x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
     }
     pred0_Q13 = pred_Q13[ 0 ];
     pred1_Q13 = pred_Q13[ 1 ];
     for( n = STEREO_INTERP_LEN_MS * fs_kHz; n < frame_length; n++ ) {
-        sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 );         /* Q11 */
-        sum = silk_SMLAWB( silk_LSHIFT( ( opus_int32 )x2[ n + 1 ], 8 ), sum, pred0_Q13 );          /* Q8  */
-        sum = silk_SMLAWB( sum, silk_LSHIFT( ( opus_int32 )x1[ n + 1 ], 11 ), pred1_Q13 );         /* Q8  */
+        sum = silk_LSHIFT( silk_ADD_LSHIFT( x1[ n ] + x1[ n + 2 ], x1[ n + 1 ], 1 ), 9 );       /* Q11 */
+        sum = silk_SMLAWB( silk_LSHIFT( (opus_int32)x2[ n + 1 ], 8 ), sum, pred0_Q13 );         /* Q8  */
+        sum = silk_SMLAWB( sum, silk_LSHIFT( (opus_int32)x1[ n + 1 ], 11 ), pred1_Q13 );        /* Q8  */
         x2[ n + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sum, 8 ) );
     }
     state->pred_prev_Q13[ 0 ] = pred_Q13[ 0 ];
index 9f7fd29..338281b 100644 (file)
@@ -150,7 +150,6 @@ typedef struct {
     opus_int                     minInternal_fs_Hz;                 /* Minimum internal sampling frequency (Hz)                         */
     opus_int                     desiredInternal_fs_Hz;             /* Soft request for internal sampling frequency (Hz)                */
     opus_int                     fs_kHz;                            /* Internal sampling frequency (kHz)                                */
-    opus_int                     delay;                             /* Number of samples of delay to apply */
     opus_int                     nb_subfr;                          /* Number of 5 ms subframes in a frame                              */
     opus_int                     frame_length;                      /* Frame length (samples)                                           */
     opus_int                     subfr_length;                      /* Subframe length (samples)                                        */
@@ -194,7 +193,6 @@ typedef struct {
 
     /* Input/output buffering */
     opus_int16                   inputBuf[ MAX_FRAME_LENGTH + 2 ];  /* Buffer containing input signal                                   */
-    opus_int16                   delayBuf[MAX_ENCODER_DELAY];
     opus_int                     inputBufIx;
     opus_int                     nFramesPerPacket;
     opus_int                     nFramesEncoded;                    /* Number of frames analyzed in current packet                      */
@@ -261,8 +259,6 @@ typedef struct {
     opus_int32                  exc_Q10[ MAX_FRAME_LENGTH ];
     opus_int32                  sLPC_Q14_buf[ MAX_LPC_ORDER ];
     opus_int16                  outBuf[ MAX_FRAME_LENGTH + 2 * MAX_SUB_FRAME_LENGTH ];  /* Buffer for output signal                     */
-    opus_int16                  delayBuf[ MAX_DECODER_DELAY ];      /* Buffer for delaying the SILK output prior to resampling          */
-    opus_int                    delay;                              /* How much decoder delay to add                                    */
     opus_int                    lagPrev;                            /* Previous Lag                                                     */
     opus_int8                   LastGainIndex;                      /* Previous gain index                                              */
     opus_int                    fs_kHz;                             /* Sampling frequency in kHz                                        */
index d42a963..ff0d0b6 100644 (file)
@@ -51,13 +51,11 @@ extern "C"
 /*********************/
 
 /* LPC analysis defines: regularization and bandwidth expansion */
-#define FIND_LPC_COND_FAC                               2.5e-5f
-#define FIND_LPC_CHIRP                                  0.99995f
-#define FIND_LPC_CHIRP_FIRST_FRAME                      0.96f
+#define FIND_LPC_COND_FAC                               1e-5f
 
 /* LTP analysis defines */
 #define FIND_LTP_COND_FAC                               1e-5f
-#define LTP_DAMPING                                     0.01f
+#define LTP_DAMPING                                     0.05f
 #define LTP_SMOOTHING                                   0.1f
 
 /* LTP quantization settings */
@@ -108,7 +106,7 @@ extern "C"
 #define WARPING_MULTIPLIER                              0.015f
 
 /* fraction added to first autocorrelation value */
-#define SHAPE_WHITE_NOISE_FRACTION                      1e-5f
+#define SHAPE_WHITE_NOISE_FRACTION                      5e-5f
 
 /* noise shaping filter chirp factor */
 #define BANDWIDTH_EXPANSION                             0.95f
index a6772f9..54b48d4 100644 (file)
@@ -126,10 +126,6 @@ static const opus_int32 mode_thresholds[2][2] = {
       {  48000,      24000}, /* stereo */
 };
 
-static const int celt_delay_table[5] = {
-/* API 8  12  16  24  48 */
-      10, 16, 21, 27, 55
-};
 int opus_encoder_get_size(int channels)
 {
     int silkEncSizeBytes, celtEncSizeBytes;
@@ -209,11 +205,11 @@ int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int applicat
     st->voice_ratio = -1;
     st->encoder_buffer = st->Fs/100;
 
-    st->delay_compensation = st->Fs/400;
-
-    st->delay_compensation += celt_delay_table[rateID(st->Fs)];
+    /* Delay compensation of 4 ms (2.5 ms for SILK's extra look-ahead 
+       + 1.5 ms for SILK resamplers and stereo prediction) */
+    st->delay_compensation = st->Fs/250;
 
-    st->hybrid_stereo_width_Q14             = 1 << 14;
+    st->hybrid_stereo_width_Q14 = 1 << 14;
     st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
     st->first = 1;
     st->mode = MODE_HYBRID;
index 528ff8e..38cb441 100644 (file)
@@ -1,21 +1,21 @@
-#ifndef CONFIG_H\r
-#define CONFIG_H\r
-\r
-#define CELT_BUILD            1\r
-\r
-#define restrict \r
-#define inline __inline\r
-\r
-#define USE_ALLOCA            1\r
-\r
-/* Comment out the next line for floating-point code */\r
-/*#define FIXED_POINT           1 */\r
-\r
-#define OPUS_BUILD            1\r
-\r
-/* Get rid of the CELT VS compile warnings */\r
-#if 1\r
-#pragma warning(disable : 4996)/* This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. */\r
-#endif\r
-\r
-#endif CONFIG_H\r
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#define CELT_BUILD            1
+
+#define restrict 
+#define inline __inline
+
+#define USE_ALLOCA            1
+
+/* Comment out the next line for floating-point code */
+/*#define FIXED_POINT           1 */
+
+#define OPUS_BUILD            1
+
+/* Get rid of the CELT VS compile warnings */
+#if 1
+#pragma warning(disable : 4996)/* This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. */
+#endif
+
+#endif CONFIG_H