Update SILK code using the CELT range coder
[opus.git] / src_SigProc_FLP / SKP_Silk_LPC_inv_pred_gain_FLP.c
similarity index 54%
rename from src/SKP_Silk_resample_2_3.c
rename to src_SigProc_FLP/SKP_Silk_LPC_inv_pred_gain_FLP.c
index dbb16fe..976f9fd 100644 (file)
@@ -26,49 +26,56 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/\r
 \r
 /*                                                                      *\r
- * File Name:    SKP_Silk_resample_2_3.c                              *\r
+ * SKP_Silk_LPC_inverse_pred_gain.c                                   *\r
  *                                                                      *\r
- * Resamples by a factor 2/3                                            *\r
+ * compute inverse of LPC prediction gain, and                          *\r
+ * test if LPC coefficients are stable (all poles within unit circle)   *\r
  *                                                                      *\r
  * Copyright 2008 (c), Skype Limited                                    *\r
- * All rights reserved.                                                 *\r
- *                                                                      *\r
- * Date: 081113                                                         *\r
  *                                                                      */\r
-\r
 #include "SKP_Silk_SigProc_FIX.h"\r
+#include "SKP_Silk_SigProc_FLP.h"\r
 \r
-#define OUT_SUBFR_LEN        80\r
+#define RC_THRESHOLD        0.9999f\r
 \r
-/* Resamples by a factor 2/3 */\r
-void SKP_Silk_resample_2_3(\r
-    SKP_int16            *out,       /* O:   Fs_low signal    [inLen * 2/3]           */\r
-    SKP_int32            *S,         /* I/O: State vector     [7+4]                   */\r
-    const SKP_int16      *in,        /* I:   Fs_high signal   [inLen]                 */\r
-    const SKP_int        inLen       /* I:   Input length, must be a multiple of 3    */\r
+/* compute inverse of LPC prediction gain, and                          */\r
+/* test if LPC coefficients are stable (all poles within unit circle)   */\r
+/* this code is based on SKP_Silk_a2k_FLP()                               */\r
+SKP_int SKP_Silk_LPC_inverse_pred_gain_FLP(   /* O:   returns 1 if unstable, otherwise 0      */\r
+    SKP_float       *invGain,               /* O:   inverse prediction gain, energy domain  */\r
+    const SKP_float *A,                     /* I:   prediction coefficients [order]         */\r
+    SKP_int32       order                   /* I:   prediction order                        */\r
 )\r
 {\r
-    SKP_int      outLen, LSubFrameIn, LSubFrameOut;\r
-    SKP_int16    outH[      3 * OUT_SUBFR_LEN ];\r
-    SKP_int32    scratch[ ( 9 * OUT_SUBFR_LEN ) / 2 ];\r
-\r
-    /* Check that input length is multiple of 3 */\r
-    SKP_assert( inLen % 3 == 0 );\r
+    SKP_int   k, n;\r
+    double    rc, rc_mult1, rc_mult2;\r
+    SKP_float Atmp[ 2 ][ SKP_Silk_MAX_ORDER_LPC ];\r
+    SKP_float *Aold, *Anew;\r
 \r
-    outLen = SKP_DIV32_16( SKP_LSHIFT( inLen, 1 ), 3 );\r
-    while( outLen > 0 ) {\r
-        LSubFrameOut = SKP_min_int( OUT_SUBFR_LEN, outLen );\r
-        LSubFrameIn  = SKP_SMULWB( 98304, LSubFrameOut ); /* 98304_Q16 = 3/2_Q0 */\r
-            \r
-        /* Upsample by a factor 2 */\r
-        /* Scratch size needs to be: 3 * LSubFrameIn * sizeof( SKP_int32 ) */\r
-        SKP_Silk_resample_2_1_coarse( in, &S[ 0 ], outH, scratch, LSubFrameIn );\r
+    Anew = Atmp[ order & 1 ];\r
+    SKP_memcpy( Anew, A, order * sizeof(SKP_float) );\r
 \r
-        /* Downsample by a factor 3 */\r
-        SKP_Silk_resample_1_3( out, &S[ 4 ], outH, SKP_LSHIFT( LSubFrameIn, 1 ) );\r
-\r
-        in     += LSubFrameIn;\r
-        out    += LSubFrameOut;\r
-        outLen -= LSubFrameOut;\r
+    *invGain = 1.0f;\r
+    for( k = order - 1; k > 0; k-- ) {\r
+        rc = -Anew[ k ];\r
+        if (rc > RC_THRESHOLD || rc < -RC_THRESHOLD) {\r
+            return 1;\r
+        }\r
+        rc_mult1 = 1.0f - rc * rc;\r
+        rc_mult2 = 1.0f / rc_mult1;\r
+        *invGain *= (SKP_float)rc_mult1;\r
+        /* swap pointers */\r
+        Aold = Anew;\r
+        Anew = Atmp[ k & 1 ];\r
+        for( n = 0; n < k; n++ ) {\r
+            Anew[ n ] = (SKP_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 );\r
+        }\r
+    }\r
+    rc = -Anew[ 0 ];\r
+    if ( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {\r
+        return 1;\r
     }\r
+    rc_mult1 = 1.0f - rc * rc;\r
+    *invGain *= (SKP_float)rc_mult1;\r
+    return 0;\r
 }\r