shithub: opus

Download patch

ref: 1c2f5633d101c08b5ef8095a8682d3d52cbd952d
parent: fb3a437c9dabb4aafe4a3927158161590ed745ab
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Thu Sep 15 21:16:53 EDT 2011

Removed all the silk_ prefixes in source file names (not symbols)

--- /dev/null
+++ b/silk/A2NLSF.c
@@ -1,0 +1,284 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+/* Conversion between prediction filter coefficients and NLSFs  */
+/* Requires the order to be an even number                      */
+/* A piecewise linear approximation maps LSF <-> cos(LSF)       */
+/* Therefore the result is not accurate NLSFs, but the two      */
+/* functions are accurate inverses of each other                */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+#include "tables.h"
+
+/* Number of binary divisions, when not in low complexity mode */
+#define BIN_DIV_STEPS_A2NLSF_FIX      3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
+#define QPoly                        16
+#define MAX_ITERATIONS_A2NLSF_FIX    30
+
+/* Flag for using 2x as many cosine sampling points, reduces the risk of missing a root */
+#define OVERSAMPLE_COSINE_TABLE       0
+
+/* Helper function for A2NLSF(..)                    */
+/* Transforms polynomials from cos(n*f) to cos(f)^n  */
+static inline void silk_A2NLSF_trans_poly(
+    opus_int32        *p,    /* I/O    Polynomial                                */
+    const opus_int    dd     /* I      Polynomial order (= filter order / 2 )    */
+)
+{
+    opus_int k, n;
+
+    for( k = 2; k <= dd; k++ ) {
+        for( n = dd; n > k; n-- ) {
+            p[ n - 2 ] -= p[ n ];
+        }
+        p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 );
+    }
+}
+/* Helper function for A2NLSF(..)                    */
+/* Polynomial evaluation                             */
+static inline opus_int32 silk_A2NLSF_eval_poly(    /* return the polynomial evaluation, in QPoly */
+    opus_int32        *p,    /* I    Polynomial, QPoly        */
+    const opus_int32   x,    /* I    Evaluation point, Q12    */
+    const opus_int    dd     /* I    Order                    */
+)
+{
+    opus_int   n;
+    opus_int32 x_Q16, y32;
+
+    y32 = p[ dd ];                                    /* QPoly */
+    x_Q16 = silk_LSHIFT( x, 4 );
+    for( n = dd - 1; n >= 0; n-- ) {
+        y32 = silk_SMLAWW( p[ n ], y32, x_Q16 );       /* QPoly */
+    }
+    return y32;
+}
+
+static inline void silk_A2NLSF_init(
+     const opus_int32    *a_Q16,
+     opus_int32          *P,
+     opus_int32          *Q,
+     const opus_int      dd
+)
+{
+    opus_int k;
+
+    /* Convert filter coefs to even and odd polynomials */
+    P[dd] = silk_LSHIFT( 1, QPoly );
+    Q[dd] = silk_LSHIFT( 1, QPoly );
+    for( k = 0; k < dd; k++ ) {
+#if( QPoly < 16 )
+        P[ k ] = silk_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */
+        Q[ k ] = silk_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */
+#elif( Qpoly == 16 )
+        P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* QPoly*/
+        Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* QPoly*/
+#else
+        P[ k ] = silk_LSHIFT( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */
+        Q[ k ] = silk_LSHIFT( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */
+#endif
+    }
+
+    /* Divide out zeros as we have that for even filter orders, */
+    /* z =  1 is always a root in Q, and                        */
+    /* z = -1 is always a root in P                             */
+    for( k = dd; k > 0; k-- ) {
+        P[ k - 1 ] -= P[ k ];
+        Q[ k - 1 ] += Q[ k ];
+    }
+
+    /* Transform polynomials from cos(n*f) to cos(f)^n */
+    silk_A2NLSF_trans_poly( P, dd );
+    silk_A2NLSF_trans_poly( Q, dd );
+}
+
+/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients        */
+/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence.    */
+void silk_A2NLSF(
+    opus_int16        *NLSF,                 /* O    Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d]    */
+    opus_int32        *a_Q16,                /* I/O  Monic whitening filter coefficients in Q16 [d]                   */
+    const opus_int    d                      /* I    Filter order (must be even)                                      */
+)
+{
+    opus_int      i, k, m, dd, root_ix, ffrac;
+    opus_int32 xlo, xhi, xmid;
+    opus_int32 ylo, yhi, ymid;
+    opus_int32 nom, den;
+    opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ];
+    opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
+    opus_int32 *PQ[ 2 ];
+    opus_int32 *p;
+
+    /* Store pointers to array */
+    PQ[ 0 ] = P;
+    PQ[ 1 ] = Q;
+
+    dd = silk_RSHIFT( d, 1 );
+
+    silk_A2NLSF_init( a_Q16, P, Q, dd );
+
+    /* Find roots, alternating between P and Q */
+    p = P;    /* Pointer to polynomial */
+
+    xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
+    ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+
+    if( ylo < 0 ) {
+        /* Set the first NLSF to zero and move on to the next */
+        NLSF[ 0 ] = 0;
+        p = Q;                      /* Pointer to polynomial */
+        ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+        root_ix = 1;                /* Index of current root */
+    } else {
+        root_ix = 0;                /* Index of current root */
+    }
+    k = 1;                          /* Loop counter */
+    i = 0;                          /* Counter for bandwidth expansions applied */
+    while( 1 ) {
+        /* Evaluate polynomial */
+#if OVERSAMPLE_COSINE_TABLE
+        xhi = silk_LSFCosTab_FIX_Q12[   k       >> 1 ] +
+          ( ( silk_LSFCosTab_FIX_Q12[ ( k + 1 ) >> 1 ] -
+              silk_LSFCosTab_FIX_Q12[   k       >> 1 ] ) >> 1 );    /* Q12 */
+#else
+        xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
+#endif
+        yhi = silk_A2NLSF_eval_poly( p, xhi, dd );
+
+        /* Detect zero crossing */
+        if( ( ylo <= 0 && yhi >= 0 ) || ( ylo >= 0 && yhi <= 0 ) ) {
+            /* Binary division */
+#if OVERSAMPLE_COSINE_TABLE
+            ffrac = -128;
+#else
+            ffrac = -256;
+#endif
+            for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
+                /* Evaluate polynomial */
+                xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 );
+                ymid = silk_A2NLSF_eval_poly( p, xmid, dd );
+
+                /* Detect zero crossing */
+                if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
+                    /* Reduce frequency */
+                    xhi = xmid;
+                    yhi = ymid;
+                } else {
+                    /* Increase frequency */
+                    xlo = xmid;
+                    ylo = ymid;
+#if OVERSAMPLE_COSINE_TABLE
+                    ffrac = silk_ADD_RSHIFT( ffrac,  64, m );
+#else
+                    ffrac = silk_ADD_RSHIFT( ffrac, 128, m );
+#endif
+                }
+            }
+
+            /* Interpolate */
+            if( silk_abs( ylo ) < 65536 ) {
+                /* Avoid dividing by zero */
+                den = ylo - yhi;
+                nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 );
+                if( den != 0 ) {
+                    ffrac += silk_DIV32( nom, den );
+                }
+            } else {
+                /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
+                ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
+            }
+#if OVERSAMPLE_COSINE_TABLE
+            NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 7 ) + ffrac, silk_int16_MAX );
+#else
+            NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX );
+#endif
+
+            silk_assert( NLSF[ root_ix ] >=     0 );
+            silk_assert( NLSF[ root_ix ] <= 32767 );
+
+            root_ix++;        /* Next root */
+            if( root_ix >= d ) {
+                /* Found all roots */
+                break;
+            }
+            /* Alternate pointer to polynomial */
+            p = PQ[ root_ix & 1 ];
+
+            /* Evaluate polynomial */
+#if OVERSAMPLE_COSINE_TABLE
+            xlo = silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] +
+              ( ( silk_LSFCosTab_FIX_Q12[   k       >> 1 ] -
+                  silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] ) >> 1 ); /* Q12*/
+#else
+            xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/
+#endif
+            ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 );
+        } else {
+            /* Increment loop counter */
+            k++;
+            xlo    = xhi;
+            ylo    = yhi;
+
+#if OVERSAMPLE_COSINE_TABLE
+            if( k > 2 * LSF_COS_TAB_SZ_FIX ) {
+#else
+            if( k > LSF_COS_TAB_SZ_FIX ) {
+#endif
+                i++;
+                if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
+                    /* Set NLSFs to white spectrum and exit */
+                    NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
+                    for( k = 1; k < d; k++ ) {
+                        NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] );
+                    }
+                    return;
+                }
+
+                /* Error: Apply progressively more bandwidth expansion and run again */
+                silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/
+
+                silk_A2NLSF_init( a_Q16, P, Q, dd );
+                p = P;                            /* Pointer to polynomial */
+                xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
+                ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+                if( ylo < 0 ) {
+                    /* Set the first NLSF to zero and move on to the next */
+                    NLSF[ 0 ] = 0;
+                    p = Q;                        /* Pointer to polynomial */
+                    ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
+                    root_ix = 1;                  /* Index of current root */
+                } else {
+                    root_ix = 0;                  /* Index of current root */
+                }
+                k = 1;                            /* Reset loop counter */
+            }
+        }
+    }
+}
--- /dev/null
+++ b/silk/API.h
@@ -1,0 +1,138 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_API_H
+#define SILK_API_H
+
+#include "control.h"
+#include "typedef.h"
+#include "errors.h"
+#include "entenc.h"
+#include "entdec.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define SILK_MAX_FRAMES_PER_PACKET  3
+
+/* Struct for TOC (Table of Contents) */
+typedef struct {
+    opus_int     VADFlag;                                /* Voice activity for packet                            */
+    opus_int     VADFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Voice activity for each frame in packet              */
+    opus_int     inbandFECFlag;                          /* Flag indicating if packet contains in-band FEC       */
+} silk_TOC_struct;
+
+/****************************************/
+/* Encoder functions                    */
+/****************************************/
+
+/***********************************************/
+/* Get size in bytes of the Silk encoder state */
+/***********************************************/
+opus_int silk_Get_Encoder_Size(                          /* O:   Returns error code                              */
+    int                                  *encSizeBytes   /* O:   Number of bytes in SILK encoder state           */
+);
+
+/*************************/
+/* Init or reset encoder */
+/*************************/
+opus_int silk_InitEncoder(                               /* O:   Returns error code                              */
+    void                                *encState,      /* I/O: State                                           */
+    silk_EncControlStruct               *encStatus      /* O:   Encoder Status                                  */
+);
+
+/***************************************/
+/* Read control structure from encoder */
+/***************************************/
+opus_int silk_QueryEncoder(                              /* O:   Returns error code                              */
+    const void                          *encState,      /* I:   State                                           */
+    silk_EncControlStruct               *encStatus      /* O:   Encoder Status                                  */
+);
+
+/**************************/
+/* Encode frame with Silk */
+/**************************/
+/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what                     */
+/* encControl->payloadSize_ms is set to                                                                         */
+opus_int silk_Encode(                                    /* O:   Returns error code                              */
+    void                                *encState,      /* I/O: State                                           */
+    silk_EncControlStruct               *encControl,    /* I:   Control status                                  */
+    const opus_int16                     *samplesIn,     /* I:   Speech sample input vector                      */
+    opus_int                             nSamplesIn,     /* I:   Number of samples in input vector               */
+    ec_enc                              *psRangeEnc,    /* I/O  Compressor data structure                       */
+    opus_int                             *nBytesOut,     /* I/O: Number of bytes in payload (input: Max bytes)   */
+    const opus_int                       prefillFlag     /* I:   Flag to indicate prefilling buffers no coding   */
+);
+
+/****************************************/
+/* Decoder functions                    */
+/****************************************/
+
+/***********************************************/
+/* Get size in bytes of the Silk decoder state */
+/***********************************************/
+opus_int silk_Get_Decoder_Size(                          /* O:   Returns error code                              */
+    int                                  *decSizeBytes   /* O:   Number of bytes in SILK decoder state           */
+);
+
+/*************************/
+/* Init or Reset decoder */
+/*************************/
+opus_int silk_InitDecoder(                               /* O:   Returns error code                              */
+    void                                *decState       /* I/O: State                                           */
+);
+
+/******************/
+/* Decode a frame */
+/******************/
+opus_int silk_Decode(                                    /* O:   Returns error code                              */
+    void*                               decState,       /* I/O: State                                           */
+    silk_DecControlStruct*              decControl,     /* I/O: Control Structure                               */
+    opus_int                             lostFlag,       /* I:   0: no loss, 1 loss, 2 decode fec                */
+    opus_int                             newPacketFlag,  /* I:   Indicates first decoder call for this packet    */
+    ec_dec                              *psRangeDec,    /* I/O  Compressor data structure                       */
+    opus_int16                           *samplesOut,    /* O:   Decoded output speech vector                    */
+    opus_int32                           *nSamplesOut    /* O:   Number of samples decoded                       */
+);
+
+/**************************************/
+/* Get table of contents for a packet */
+/**************************************/
+opus_int silk_get_TOC(
+    const opus_uint8                     *payload,           /* I    Payload data                                */
+    const opus_int                       nBytesIn,           /* I:   Number of input bytes                       */
+    const opus_int                       nFramesPerPayload,  /* I:   Number of SILK frames per payload           */
+    silk_TOC_struct                     *Silk_TOC           /* O:   Type of content                             */
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+++ b/silk/CNG.c
@@ -1,0 +1,160 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Generates excitation for CNG LPC synthesis */
+static inline void silk_CNG_exc(
+    opus_int32                       residual_Q10[],     /* O    CNG residual signal Q10                     */
+    opus_int32                       exc_buf_Q10[],      /* I    Random samples buffer Q10                   */
+    opus_int32                       Gain_Q16,           /* I    Gain to apply                               */
+    opus_int                         length,             /* I    Length                                      */
+    opus_int32                       *rand_seed          /* I/O  Seed to random index generator              */
+)
+{
+    opus_int32 seed;
+    opus_int   i, idx, exc_mask;
+
+    exc_mask = CNG_BUF_MASK_MAX;
+    while( exc_mask > length ) {
+        exc_mask = silk_RSHIFT( exc_mask, 1 );
+    }
+
+    seed = *rand_seed;
+    for( i = 0; i < length; i++ ) {
+        seed = silk_RAND( seed );
+        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 ) );
+    }
+    *rand_seed = seed;
+}
+
+void silk_CNG_Reset(
+    silk_decoder_state      *psDec              /* I/O  Decoder state                               */
+)
+{
+    opus_int i, NLSF_step_Q15, NLSF_acc_Q15;
+
+    NLSF_step_Q15 = silk_DIV32_16( silk_int16_MAX, psDec->LPC_order + 1 );
+    NLSF_acc_Q15 = 0;
+    for( i = 0; i < psDec->LPC_order; i++ ) {
+        NLSF_acc_Q15 += NLSF_step_Q15;
+        psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15;
+    }
+    psDec->sCNG.CNG_smth_Gain_Q16 = 0;
+    psDec->sCNG.rand_seed = 3176576;
+}
+
+/* Updates CNG estimate, and applies the CNG when packet was lost   */
+void silk_CNG(
+    silk_decoder_state          *psDec,             /* I/O  Decoder state                               */
+    silk_decoder_control        *psDecCtrl,         /* I/O  Decoder control                             */
+    opus_int16                   frame[],           /* I/O  Signal data                                 */
+    opus_int                     length              /* I    Length of residual                          */
+)
+{
+    opus_int   i, j, 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 ];
+    silk_CNG_struct *psCNG = &psDec->sCNG;
+
+    if( psDec->fs_kHz != psCNG->fs_kHz ) {
+        /* Reset state */
+        silk_CNG_Reset( psDec );
+
+        psCNG->fs_kHz = psDec->fs_kHz;
+    }
+    if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) {
+        /* Update CNG parameters */
+
+        /* Smoothing of LSF's  */
+        for( i = 0; i < psDec->LPC_order; i++ ) {
+            psCNG->CNG_smth_NLSF_Q15[ i ] += silk_SMULWB( psDec->prevNLSF_Q15[ i ] - psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 );
+        }
+        /* Find the subframe with the highest gain */
+        max_Gain_Q16 = 0;
+        subfr        = 0;
+        for( i = 0; i < psDec->nb_subfr; i++ ) {
+            if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) {
+                max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
+                subfr        = i;
+            }
+        }
+        /* Update CNG excitation buffer with excitation from this subframe */
+        silk_memmove( &psCNG->CNG_exc_buf_Q10[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q10, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) );
+        silk_memcpy(   psCNG->CNG_exc_buf_Q10, &psDec->exc_Q10[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) );
+
+        /* Smooth gains */
+        for( i = 0; i < psDec->nb_subfr; i++ ) {
+            psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
+        }
+    }
+
+    /* Add CNG when packet is lost or during DTX */
+    if( psDec->lossCnt ) {
+
+        /* Generate CNG excitation */
+        silk_CNG_exc( CNG_sig_Q10 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q10, psCNG->CNG_smth_Gain_Q16, length, &psCNG->rand_seed );
+
+        /* Convert CNG NLSF to filter representation */
+        silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
+
+        /* 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 */
+            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 ] );
+            sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i -  4 ], A_Q12[ 3 ] );
+            sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i -  5 ], A_Q12[ 4 ] );
+            sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i -  6 ], A_Q12[ 5 ] );
+            sum_Q6 = silk_SMLAWB( sum_Q6, CNG_sig_Q10[ MAX_LPC_ORDER + i -  7 ], A_Q12[ 6 ] );
+            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 ] );
+            }
+
+            /* Update states */
+            CNG_sig_Q10[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q10[ MAX_LPC_ORDER + i ], sum_Q6, 4 );
+
+            frame[ i ] = silk_ADD_SAT16( frame[ i ], silk_RSHIFT_ROUND( sum_Q6, 6 ) );
+        }
+        silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q10[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+    } else {
+        silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order *  sizeof( opus_int32 ) );
+    }
+}
--- /dev/null
+++ b/silk/HP_variable_cutoff.c
@@ -1,0 +1,78 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef FIXED_POINT
+#include "main_FIX.h"
+#else
+#include "main_FLP.h"
+#endif
+#include "tuning_parameters.h"
+
+/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
+void silk_HP_variable_cutoff(
+    silk_encoder_state_Fxx          state_Fxx[],        /* I/O  Encoder states                          */
+    const opus_int                   nChannels           /* I    Number of channels                      */
+)
+{
+   opus_int   quality_Q15;
+   opus_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7;
+   silk_encoder_state *psEncC1 = &state_Fxx[ 0 ].sCmn;
+
+   /* Adaptive cutoff frequency: estimate low end of pitch frequency range */
+   if( psEncC1->prevSignalType == TYPE_VOICED ) {
+      /* difference, in log domain */
+      pitch_freq_Hz_Q16 = silk_DIV32_16( silk_LSHIFT( silk_MUL( psEncC1->fs_kHz, 1000 ), 16 ), psEncC1->prevLag );
+      pitch_freq_log_Q7 = silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 );
+
+      /* adjustment based on quality */
+      quality_Q15 = psEncC1->input_quality_bands_Q15[ 0 ];
+      pitch_freq_log_Q7 = silk_SMLAWB( pitch_freq_log_Q7, silk_SMULWB( silk_LSHIFT( -quality_Q15, 2 ), quality_Q15 ),
+            pitch_freq_log_Q7 - ( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ) ) );
+
+      /* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */
+      delta_freq_Q7 = pitch_freq_log_Q7 - silk_RSHIFT( psEncC1->variable_HP_smth1_Q15, 8 );
+      if( delta_freq_Q7 < 0 ) {
+         /* less smoothing for decreasing pitch frequency, to track something close to the minimum */
+         delta_freq_Q7 = silk_MUL( delta_freq_Q7, 3 );
+      }
+
+      /* limit delta, to reduce impact of outliers in pitch estimation */
+      delta_freq_Q7 = silk_LIMIT_32( delta_freq_Q7, -SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) );
+
+      /* update smoother */
+      psEncC1->variable_HP_smth1_Q15 = silk_SMLAWB( psEncC1->variable_HP_smth1_Q15,
+            silk_SMULBB( psEncC1->speech_activity_Q8, delta_freq_Q7 ), SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) );
+
+      /* limit frequency range */
+      psEncC1->variable_HP_smth1_Q15 = silk_LIMIT_32( psEncC1->variable_HP_smth1_Q15,
+            silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ),
+            silk_LSHIFT( silk_lin2log( VARIABLE_HP_MAX_CUTOFF_HZ ), 8 ) );
+   }
+}
--- /dev/null
+++ b/silk/Inlines.h
@@ -1,0 +1,185 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+/*! \file silk_Inlines.h
+ *  \brief silk_Inlines.h defines inline signal processing functions.
+ */
+
+#ifndef _SILK_FIX_INLINES_H_
+#define _SILK_FIX_INLINES_H_
+
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+
+/* count leading zeros of opus_int64 */
+static inline opus_int32 silk_CLZ64(opus_int64 in)
+{
+    opus_int32 in_upper;
+
+    in_upper = (opus_int32)silk_RSHIFT64(in, 32);
+    if (in_upper == 0) {
+        /* Search in the lower 32 bits */
+        return 32 + silk_CLZ32( (opus_int32) in );
+    } else {
+        /* Search in the upper 32 bits */
+        return silk_CLZ32( in_upper );
+    }
+}
+
+/* get number of leading zeros and fractional part (the bits right after the leading one */
+static inline void silk_CLZ_FRAC(opus_int32 in,            /* I: input */
+                                    opus_int32 *lz,           /* O: number of leading zeros */
+                                    opus_int32 *frac_Q7)      /* O: the 7 bits right after the leading one */
+{
+    opus_int32 lzeros = silk_CLZ32(in);
+
+    * lz = lzeros;
+    * frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f;
+}
+
+/* Approximation of square root                                          */
+/* Accuracy: < +/- 10%  for output values > 15                           */
+/*           < +/- 2.5% for output values > 120                          */
+static inline opus_int32 silk_SQRT_APPROX(opus_int32 x)
+{
+    opus_int32 y, lz, frac_Q7;
+
+    if( x <= 0 ) {
+        return 0;
+    }
+
+    silk_CLZ_FRAC(x, &lz, &frac_Q7);
+
+    if( lz & 1 ) {
+        y = 32768;
+    } else {
+        y = 46214;        /* 46214 = sqrt(2) * 32768 */
+    }
+
+    /* get scaling right */
+    y >>= silk_RSHIFT(lz, 1);
+
+    /* increment using fractional part of input */
+    y = silk_SMLAWB(y, y, silk_SMULBB(213, frac_Q7));
+
+    return y;
+}
+
+/* Divide two int32 values and return result as int32 in a given Q-domain */
+static inline opus_int32 silk_DIV32_varQ(    /* O    returns a good approximation of "(a32 << Qres) / b32" */
+    const opus_int32     a32,            /* I    numerator (Q0)                  */
+    const opus_int32     b32,            /* I    denominator (Q0)                */
+    const opus_int       Qres            /* I    Q-domain of result (>= 0)       */
+)
+{
+    opus_int   a_headrm, b_headrm, lshift;
+    opus_int32 b32_inv, a32_nrm, b32_nrm, result;
+
+    silk_assert( b32 != 0 );
+    silk_assert( Qres >= 0 );
+
+    /* Compute number of bits head room and normalize inputs */
+    a_headrm = silk_CLZ32( silk_abs(a32) ) - 1;
+    a32_nrm = silk_LSHIFT(a32, a_headrm);                                    /* Q: a_headrm                    */
+    b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
+    b32_nrm = silk_LSHIFT(b32, b_headrm);                                    /* Q: b_headrm                    */
+
+    /* Inverse of b32, with 14 bits of precision */
+    b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) );  /* Q: 29 + 16 - b_headrm        */
+
+    /* First approximation */
+    result = silk_SMULWB(a32_nrm, b32_inv);                                  /* Q: 29 + a_headrm - b_headrm    */
+
+    /* Compute residual by subtracting product of denominator and first approximation */
+    a32_nrm -= silk_LSHIFT( silk_SMMUL(b32_nrm, result), 3 );           /* Q: a_headrm                    */
+
+    /* Refinement */
+    result = silk_SMLAWB(result, a32_nrm, b32_inv);                          /* Q: 29 + a_headrm - b_headrm    */
+
+    /* Convert to Qres domain */
+    lshift = 29 + a_headrm - b_headrm - Qres;
+    if( lshift < 0 ) {
+        return silk_LSHIFT_SAT32(result, -lshift);
+    } else {
+        if( lshift < 32){
+            return silk_RSHIFT(result, lshift);
+        } else {
+            /* Avoid undefined result */
+            return 0;
+        }
+    }
+}
+
+/* Invert int32 value and return result as int32 in a given Q-domain */
+static inline opus_int32 silk_INVERSE32_varQ(    /* O    returns a good approximation of "(1 << Qres) / b32" */
+    const opus_int32     b32,                /* I    denominator (Q0)                */
+    const opus_int       Qres                /* I    Q-domain of result (> 0)        */
+)
+{
+    opus_int   b_headrm, lshift;
+    opus_int32 b32_inv, b32_nrm, err_Q32, result;
+
+    silk_assert( b32 != 0 );
+    silk_assert( Qres > 0 );
+
+    /* Compute number of bits head room and normalize input */
+    b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
+    b32_nrm = silk_LSHIFT(b32, b_headrm);                                    /* Q: b_headrm                */
+
+    /* Inverse of b32, with 14 bits of precision */
+    b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) );  /* Q: 29 + 16 - b_headrm    */
+
+    /* First approximation */
+    result = silk_LSHIFT(b32_inv, 16);                                       /* Q: 61 - b_headrm            */
+
+    /* Compute residual by subtracting product of denominator and first approximation from one */
+    err_Q32 = silk_LSHIFT( (1<<29)-silk_SMULWB(b32_nrm, b32_inv), 3 );         /* Q32                        */
+
+    /* Refinement */
+    result = silk_SMLAWW(result, err_Q32, b32_inv);                          /* Q: 61 - b_headrm            */
+
+    /* Convert to Qres domain */
+    lshift = 61 - b_headrm - Qres;
+    if( lshift <= 0 ) {
+        return silk_LSHIFT_SAT32(result, -lshift);
+    } else {
+        if( lshift < 32){
+            return silk_RSHIFT(result, lshift);
+        }else{
+            /* Avoid undefined result */
+            return 0;
+        }
+    }
+}
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /*_SILK_FIX_INLINES_H_*/
--- /dev/null
+++ b/silk/LPC_analysis_filter.c
@@ -1,0 +1,83 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/*******************************************/
+/* LPC analysis filter                     */
+/* NB! State is kept internally and the    */
+/* filter always starts with zero state    */
+/* first d output samples are set to zero  */
+/*******************************************/
+
+void silk_LPC_analysis_filter(
+    opus_int16            *out,           /* O:   Output signal                               */
+    const opus_int16      *in,            /* I:   Input signal                                */
+    const opus_int16      *B,             /* I:   MA prediction coefficients, Q12 [order]     */
+    const opus_int32      len,            /* I:   Signal length                               */
+    const opus_int32      d               /* I:   Filter order                                */
+)
+{
+    opus_int         ix, j;
+    opus_int32       out32_Q12, out32;
+    const opus_int16 *in_ptr;
+
+    silk_assert( d >= 6 );
+    silk_assert( (d & 1) == 0 );
+    silk_assert( d <= len );
+
+    for ( ix = d; ix < len; ix++) {
+        in_ptr = &in[ ix - 1 ];
+
+        out32_Q12 = silk_SMULBB(            in_ptr[  0 ], B[ 0 ] );
+        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
+        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
+        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
+        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
+        out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
+        for( j = 6; j < d; j += 2 ) {
+            out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -j     ], B[ j     ] );
+            out32_Q12 = silk_SMLABB( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
+        }
+
+        /* Subtract prediction */
+        out32_Q12 = silk_SUB32( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );
+
+        /* Scale to Q0 */
+        out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
+
+        /* Saturate output */
+        out[ ix ] = ( opus_int16 )silk_SAT16( out32 );
+    }
+
+    /* Set first d output samples to zero */
+    silk_memset( out, 0, d * sizeof( opus_int16 ) );
+}
--- /dev/null
+++ b/silk/LPC_inv_pred_gain.c
@@ -1,0 +1,150 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+#define QA          16
+#define A_LIMIT     SILK_FIX_CONST( 0.99975, QA )
+
+/* 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                            */
+)
+{
+    opus_int   k, n, headrm;
+    opus_int32 rc_Q31, rc_mult1_Q30, rc_mult2_Q16, tmp_QA;
+    opus_int32 *Aold_QA, *Anew_QA;
+
+    Anew_QA = A_QA[ order & 1 ];
+
+    *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 ) ) {
+            return 1;
+        }
+
+        /* Set RC equal to negated AR coef */
+        rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA );
+
+        /* rc_mult1_Q30 range: [ 1 : 2^30-1 ] */
+        rc_mult1_Q30 = ( silk_int32_MAX >> 1 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+        silk_assert( rc_mult1_Q30 > ( 1 << 15 ) );                   /* reduce A_LIMIT if fails */
+        silk_assert( rc_mult1_Q30 < ( 1 << 30 ) );
+
+        /* rc_mult2_Q16 range: [ 2^16 : silk_int32_MAX ] */
+        rc_mult2_Q16 = silk_INVERSE32_varQ( rc_mult1_Q30, 46 );      /* 16 = 46 - 30 */
+
+        /* 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 ) );
+
+        /* Swap pointers */
+        Aold_QA = Anew_QA;
+        Anew_QA = A_QA[ k & 1 ];
+
+        /* Update AR coefficient */
+        headrm = silk_CLZ32( rc_mult2_Q16 ) - 1;
+        rc_mult2_Q16 = silk_LSHIFT( rc_mult2_Q16, headrm );          /* Q: 16 + headrm */
+        for( n = 0; n < k; n++ ) {
+            tmp_QA = Aold_QA[ n ] - silk_LSHIFT( silk_SMMUL( Aold_QA[ k - n - 1 ], rc_Q31 ), 1 );
+            Anew_QA[ n ] = silk_LSHIFT( silk_SMMUL( tmp_QA, rc_mult2_Q16 ), 16 - headrm );
+        }
+    }
+
+    /* Check for stability */
+    if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
+        return 1;
+    }
+
+    /* Set RC equal to negated AR coef */
+    rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA );
+
+    /* Range: [ 1 : 2^30 ] */
+    rc_mult1_Q30 = ( silk_int32_MAX >> 1 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+
+    /* 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 );
+
+    return 0;
+}
+
+/* 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  */
+    const opus_int16     *A_Q12,                 /* I:   Prediction coefficients, Q12 [order]        */
+    const opus_int       order                   /* I:   Prediction order                            */
+)
+{
+    opus_int   k;
+    opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
+    opus_int32 *Anew_QA;
+
+    Anew_QA = Atmp_QA[ order & 1 ];
+
+    /* Increase Q domain of the AR coefficients */
+    for( k = 0; k < order; k++ ) {
+        Anew_QA[ k ] = silk_LSHIFT( (opus_int32)A_Q12[ k ], QA - 12 );
+    }
+
+    return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order );
+}
+
+/* For input in Q24 domain */
+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]        */
+    const opus_int       order                   /* I:   Prediction order                            */
+)
+{
+    opus_int   k;
+    opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
+    opus_int32 *Anew_QA;
+
+    Anew_QA = Atmp_QA[ order & 1 ];
+
+    /* Increase Q domain of the AR coefficients */
+    for( k = 0; k < order; k++ ) {
+        Anew_QA[ k ] = silk_RSHIFT_ROUND( A_Q24[ k ], 24 - QA );
+    }
+
+    return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order );
+}
+
--- /dev/null
+++ b/silk/LP_variable_cutoff.c
@@ -1,0 +1,136 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+
+    Elliptic/Cauer filters designed with 0.1 dB passband ripple,
+        80 dB minimum stopband attenuation, and
+        [0.95 : 0.15 : 0.35] normalized cut off frequencies.
+
+*/
+#include "main.h"
+
+/* Helper function, interpolates the filter taps */
+static inline void silk_LP_interpolate_filter_taps(
+    opus_int32           B_Q28[ TRANSITION_NB ],
+    opus_int32           A_Q28[ TRANSITION_NA ],
+    const opus_int       ind,
+    const opus_int32     fac_Q16
+)
+{
+    opus_int nb, na;
+
+    if( ind < TRANSITION_INT_NUM - 1 ) {
+        if( fac_Q16 > 0 ) {
+            if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */
+                /* Piece-wise linear interpolation of B and A */
+                for( nb = 0; nb < TRANSITION_NB; nb++ ) {
+                    B_Q28[ nb ] = silk_SMLAWB(
+                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
+                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
+                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
+                        fac_Q16 );
+                }
+                for( na = 0; na < TRANSITION_NA; na++ ) {
+                    A_Q28[ na ] = silk_SMLAWB(
+                        silk_Transition_LP_A_Q28[ ind     ][ na ],
+                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
+                        silk_Transition_LP_A_Q28[ ind     ][ na ],
+                        fac_Q16 );
+                }
+            } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */
+                silk_assert( fac_Q16 - ( 1 << 16 ) == silk_SAT16( fac_Q16 - ( 1 << 16 ) ) );
+                /* Piece-wise linear interpolation of B and A */
+                for( nb = 0; nb < TRANSITION_NB; nb++ ) {
+                    B_Q28[ nb ] = silk_SMLAWB(
+                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
+                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
+                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
+                        fac_Q16 - ( 1 << 16 ) );
+                }
+                for( na = 0; na < TRANSITION_NA; na++ ) {
+                    A_Q28[ na ] = silk_SMLAWB(
+                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
+                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
+                        silk_Transition_LP_A_Q28[ ind     ][ na ],
+                        fac_Q16 - ( 1 << 16 ) );
+                }
+            }
+        } else {
+            silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) );
+            silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) );
+        }
+    } else {
+        silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) );
+        silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) );
+    }
+}
+
+/* Low-pass filter with variable cutoff frequency based on  */
+/* piece-wise linear interpolation between elliptic filters */
+/* Start by setting psEncC->mode <> 0;                      */
+/* Deactivate by setting psEncC->mode = 0;                  */
+void silk_LP_variable_cutoff(
+    silk_LP_state           *psLP,              /* I/O  LP filter state                             */
+    opus_int16                   *frame,         /* I/O  Low-pass filtered output                   */
+    const opus_int               frame_length        /* I    Frame length                                */
+)
+{
+    opus_int32   B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0;
+    opus_int     ind = 0;
+
+    silk_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES );
+
+    /* Run filter if needed */
+    if( psLP->mode != 0 ) {
+        /* Calculate index and interpolation factor for interpolation */
+#if( TRANSITION_INT_STEPS == 64 )
+        fac_Q16 = silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 );
+#else
+        fac_Q16 = silk_DIV32_16( silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES );
+#endif
+        ind      = silk_RSHIFT( fac_Q16, 16 );
+        fac_Q16 -= silk_LSHIFT( ind, 16 );
+
+        silk_assert( ind >= 0 );
+        silk_assert( ind < TRANSITION_INT_NUM );
+
+        /* Interpolate filter coefficients */
+        silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 );
+
+        /* Update transition frame number for next frame */
+        psLP->transition_frame_no = silk_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES );
+
+        /* ARMA low-pass filtering */
+        silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
+        silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1);
+    }
+}
--- /dev/null
+++ b/silk/MacroCount.h
@@ -1,0 +1,719 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef _SIGPROCFIX_API_MACROCOUNT_H_
+#define _SIGPROCFIX_API_MACROCOUNT_H_
+#include <stdio.h>
+
+#ifdef    silk_MACRO_COUNT
+#define varDefine opus_int64 ops_count = 0;
+
+extern opus_int64 ops_count;
+
+static inline opus_int64 silk_SaveCount(){
+    return(ops_count);
+}
+
+static inline opus_int64 silk_SaveResetCount(){
+    opus_int64 ret;
+
+    ret = ops_count;
+    ops_count = 0;
+    return(ret);
+}
+
+static inline silk_PrintCount(){
+    printf("ops_count = %d \n ", (opus_int32)ops_count);
+}
+
+#undef silk_MUL
+static inline opus_int32 silk_MUL(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = a32 * b32;
+    return ret;
+}
+
+#undef silk_MUL_uint
+static inline opus_uint32 silk_MUL_uint(opus_uint32 a32, opus_uint32 b32){
+    opus_uint32 ret;
+    ops_count += 4;
+    ret = a32 * b32;
+    return ret;
+}
+#undef silk_MLA
+static inline opus_int32 silk_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = a32 + b32 * c32;
+    return ret;
+}
+
+#undef silk_MLA_uint
+static inline opus_int32 silk_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){
+    opus_uint32 ret;
+    ops_count += 4;
+    ret = a32 + b32 * c32;
+    return ret;
+}
+
+#undef silk_SMULWB
+static inline opus_int32 silk_SMULWB(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 5;
+    ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
+    return ret;
+}
+#undef    silk_SMLAWB
+static inline opus_int32 silk_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 5;
+    ret = ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)));
+    return ret;
+}
+
+#undef silk_SMULWT
+static inline opus_int32 silk_SMULWT(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
+    return ret;
+}
+#undef silk_SMLAWT
+static inline opus_int32 silk_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
+    return ret;
+}
+
+#undef silk_SMULBB
+static inline opus_int32 silk_SMULBB(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = (opus_int32)((opus_int16)a32) * (opus_int32)((opus_int16)b32);
+    return ret;
+}
+#undef silk_SMLABB
+static inline opus_int32 silk_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
+    return ret;
+}
+
+#undef silk_SMULBT
+static inline opus_int32 silk_SMULBT(opus_int32 a32, opus_int32 b32 ){
+    opus_int32 ret;
+    ops_count += 4;
+    ret = ((opus_int32)((opus_int16)a32)) * (b32 >> 16);
+    return ret;
+}
+
+#undef silk_SMLABT
+static inline opus_int32 silk_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
+    return ret;
+}
+
+#undef silk_SMULTT
+static inline opus_int32 silk_SMULTT(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = (a32 >> 16) * (b32 >> 16);
+    return ret;
+}
+
+#undef    silk_SMLATT
+static inline opus_int32 silk_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a32 + (b32 >> 16) * (c32 >> 16);
+    return ret;
+}
+
+
+/* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
+#undef    silk_MLA_ovflw
+#define silk_MLA_ovflw silk_MLA
+
+#undef silk_SMLABB_ovflw
+#define silk_SMLABB_ovflw silk_SMLABB
+
+#undef silk_SMLABT_ovflw
+#define silk_SMLABT_ovflw silk_SMLABT
+
+#undef silk_SMLATT_ovflw
+#define silk_SMLATT_ovflw silk_SMLATT
+
+#undef silk_SMLAWB_ovflw
+#define silk_SMLAWB_ovflw silk_SMLAWB
+
+#undef silk_SMLAWT_ovflw
+#define silk_SMLAWT_ovflw silk_SMLAWT
+
+#undef silk_SMULL
+static inline opus_int64 silk_SMULL(opus_int32 a32, opus_int32 b32){
+    opus_int64 ret;
+    ops_count += 8;
+    ret = ((opus_int64)(a32) * /*(opus_int64)*/(b32));
+    return ret;
+}
+
+#undef    silk_SMLAL
+static inline opus_int64 silk_SMLAL(opus_int64 a64, opus_int32 b32, opus_int32 c32){
+    opus_int64 ret;
+    ops_count += 8;
+    ret = a64 + ((opus_int64)(b32) * /*(opus_int64)*/(c32));
+    return ret;
+}
+#undef    silk_SMLALBB
+static inline opus_int64 silk_SMLALBB(opus_int64 a64, opus_int16 b16, opus_int16 c16){
+    opus_int64 ret;
+    ops_count += 4;
+    ret = a64 + ((opus_int64)(b16) * /*(opus_int64)*/(c16));
+    return ret;
+}
+
+#undef    SigProcFIX_CLZ16
+static inline opus_int32 SigProcFIX_CLZ16(opus_int16 in16)
+{
+    opus_int32 out32 = 0;
+    ops_count += 10;
+    if( in16 == 0 ) {
+        return 16;
+    }
+    /* test nibbles */
+    if( in16 & 0xFF00 ) {
+        if( in16 & 0xF000 ) {
+            in16 >>= 12;
+        } else {
+            out32 += 4;
+            in16 >>= 8;
+        }
+    } else {
+        if( in16 & 0xFFF0 ) {
+            out32 += 8;
+            in16 >>= 4;
+        } else {
+            out32 += 12;
+        }
+    }
+    /* test bits and return */
+    if( in16 & 0xC ) {
+        if( in16 & 0x8 )
+            return out32 + 0;
+        else
+            return out32 + 1;
+    } else {
+        if( in16 & 0xE )
+            return out32 + 2;
+        else
+            return out32 + 3;
+    }
+}
+
+#undef SigProcFIX_CLZ32
+static inline opus_int32 SigProcFIX_CLZ32(opus_int32 in32)
+{
+    /* test highest 16 bits and convert to opus_int16 */
+    ops_count += 2;
+    if( in32 & 0xFFFF0000 ) {
+        return SigProcFIX_CLZ16((opus_int16)(in32 >> 16));
+    } else {
+        return SigProcFIX_CLZ16((opus_int16)in32) + 16;
+    }
+}
+
+#undef silk_DIV32
+static inline opus_int32 silk_DIV32(opus_int32 a32, opus_int32 b32){
+    ops_count += 64;
+    return a32 / b32;
+}
+
+#undef silk_DIV32_16
+static inline opus_int32 silk_DIV32_16(opus_int32 a32, opus_int32 b32){
+    ops_count += 32;
+    return a32 / b32;
+}
+
+#undef silk_SAT8
+static inline opus_int8 silk_SAT8(opus_int64 a){
+    opus_int8 tmp;
+    ops_count += 1;
+    tmp = (opus_int8)((a) > silk_int8_MAX ? silk_int8_MAX  : \
+                    ((a) < silk_int8_MIN ? silk_int8_MIN  : (a)));
+    return(tmp);
+}
+
+#undef silk_SAT16
+static inline opus_int16 silk_SAT16(opus_int64 a){
+    opus_int16 tmp;
+    ops_count += 1;
+    tmp = (opus_int16)((a) > silk_int16_MAX ? silk_int16_MAX  : \
+                     ((a) < silk_int16_MIN ? silk_int16_MIN  : (a)));
+    return(tmp);
+}
+#undef silk_SAT32
+static inline opus_int32 silk_SAT32(opus_int64 a){
+    opus_int32 tmp;
+    ops_count += 1;
+    tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX  : \
+                     ((a) < silk_int32_MIN ? silk_int32_MIN  : (a)));
+    return(tmp);
+}
+#undef silk_POS_SAT32
+static inline opus_int32 silk_POS_SAT32(opus_int64 a){
+    opus_int32 tmp;
+    ops_count += 1;
+    tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : (a));
+    return(tmp);
+}
+
+#undef silk_ADD_POS_SAT8
+static inline opus_int8 silk_ADD_POS_SAT8(opus_int64 a, opus_int64 b){
+    opus_int8 tmp;
+    ops_count += 1;
+    tmp = (opus_int8)((((a)+(b)) & 0x80) ? silk_int8_MAX  : ((a)+(b)));
+    return(tmp);
+}
+#undef silk_ADD_POS_SAT16
+static inline opus_int16 silk_ADD_POS_SAT16(opus_int64 a, opus_int64 b){
+    opus_int16 tmp;
+    ops_count += 1;
+    tmp = (opus_int16)((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)));
+    return(tmp);
+}
+
+#undef silk_ADD_POS_SAT32
+static inline opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
+    opus_int32 tmp;
+    ops_count += 1;
+    tmp = (opus_int32)((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)));
+    return(tmp);
+}
+
+#undef silk_ADD_POS_SAT64
+static inline opus_int64 silk_ADD_POS_SAT64(opus_int64 a, opus_int64 b){
+    opus_int64 tmp;
+    ops_count += 1;
+    tmp = ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)));
+    return(tmp);
+}
+
+#undef    silk_LSHIFT8
+static inline opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
+    opus_int8 ret;
+    ops_count += 1;
+    ret = a << shift;
+    return ret;
+}
+#undef    silk_LSHIFT16
+static inline opus_int16 silk_LSHIFT16(opus_int16 a, opus_int32 shift){
+    opus_int16 ret;
+    ops_count += 1;
+    ret = a << shift;
+    return ret;
+}
+#undef    silk_LSHIFT32
+static inline opus_int32 silk_LSHIFT32(opus_int32 a, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a << shift;
+    return ret;
+}
+#undef    silk_LSHIFT64
+static inline opus_int64 silk_LSHIFT64(opus_int64 a, opus_int shift){
+    ops_count += 1;
+    return a << shift;
+}
+
+#undef    silk_LSHIFT_ovflw
+static inline opus_int32 silk_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){
+    ops_count += 1;
+    return a << shift;
+}
+
+#undef    silk_LSHIFT_uint
+static inline opus_uint32 silk_LSHIFT_uint(opus_uint32 a, opus_int32 shift){
+    opus_uint32 ret;
+    ops_count += 1;
+    ret = a << shift;
+    return ret;
+}
+
+#undef    silk_RSHIFT8
+static inline opus_int8 silk_RSHIFT8(opus_int8 a, opus_int32 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+#undef    silk_RSHIFT16
+static inline opus_int16 silk_RSHIFT16(opus_int16 a, opus_int32 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+#undef    silk_RSHIFT32
+static inline opus_int32 silk_RSHIFT32(opus_int32 a, opus_int32 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+#undef    silk_RSHIFT64
+static inline opus_int64 silk_RSHIFT64(opus_int64 a, opus_int64 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+
+#undef    silk_RSHIFT_uint
+static inline opus_uint32 silk_RSHIFT_uint(opus_uint32 a, opus_int32 shift){
+    ops_count += 1;
+    return a >> shift;
+}
+
+#undef    silk_ADD_LSHIFT
+static inline opus_int32 silk_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + (b << shift);
+    return ret;                /* shift >= 0*/
+}
+#undef    silk_ADD_LSHIFT32
+static inline opus_int32 silk_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + (b << shift);
+    return ret;                /* shift >= 0*/
+}
+#undef    silk_ADD_LSHIFT_uint
+static inline opus_uint32 silk_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
+    opus_uint32 ret;
+    ops_count += 1;
+    ret = a + (b << shift);
+    return ret;                /* shift >= 0*/
+}
+#undef    silk_ADD_RSHIFT
+static inline opus_int32 silk_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + (b >> shift);
+    return ret;                /* shift  > 0*/
+}
+#undef    silk_ADD_RSHIFT32
+static inline opus_int32 silk_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + (b >> shift);
+    return ret;                /* shift  > 0*/
+}
+#undef    silk_ADD_RSHIFT_uint
+static inline opus_uint32 silk_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
+    opus_uint32 ret;
+    ops_count += 1;
+    ret = a + (b >> shift);
+    return ret;                /* shift  > 0*/
+}
+#undef    silk_SUB_LSHIFT32
+static inline opus_int32 silk_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a - (b << shift);
+    return ret;                /* shift >= 0*/
+}
+#undef    silk_SUB_RSHIFT32
+static inline opus_int32 silk_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a - (b >> shift);
+    return ret;                /* shift  > 0*/
+}
+
+#undef    silk_RSHIFT_ROUND
+static inline opus_int32 silk_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){
+    opus_int32 ret;
+    ops_count += 3;
+    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+    return ret;
+}
+
+#undef    silk_RSHIFT_ROUND64
+static inline opus_int64 silk_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){
+    opus_int64 ret;
+    ops_count += 6;
+    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+    return ret;
+}
+
+#undef    silk_abs_int64
+static inline opus_int64 silk_abs_int64(opus_int64 a){
+    ops_count += 1;
+    return (((a) >  0)  ? (a) : -(a));            /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN*/
+}
+
+#undef    silk_abs_int32
+static inline opus_int32 silk_abs_int32(opus_int32 a){
+    ops_count += 1;
+    return abs(a);
+}
+
+
+#undef silk_min
+static silk_min(a, b){
+    ops_count += 1;
+    return (((a) < (b)) ? (a) :  (b));
+}
+#undef silk_max
+static silk_max(a, b){
+    ops_count += 1;
+    return (((a) > (b)) ? (a) :  (b));
+}
+#undef silk_sign
+static silk_sign(a){
+    ops_count += 1;
+    return ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ));
+}
+
+#undef    silk_ADD16
+static inline opus_int16 silk_ADD16(opus_int16 a, opus_int16 b){
+    opus_int16 ret;
+    ops_count += 1;
+    ret = a + b;
+    return ret;
+}
+
+#undef    silk_ADD32
+static inline opus_int32 silk_ADD32(opus_int32 a, opus_int32 b){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a + b;
+    return ret;
+}
+
+#undef    silk_ADD64
+static inline opus_int64 silk_ADD64(opus_int64 a, opus_int64 b){
+    opus_int64 ret;
+    ops_count += 2;
+    ret = a + b;
+    return ret;
+}
+
+#undef    silk_SUB16
+static inline opus_int16 silk_SUB16(opus_int16 a, opus_int16 b){
+    opus_int16 ret;
+    ops_count += 1;
+    ret = a - b;
+    return ret;
+}
+
+#undef    silk_SUB32
+static inline opus_int32 silk_SUB32(opus_int32 a, opus_int32 b){
+    opus_int32 ret;
+    ops_count += 1;
+    ret = a - b;
+    return ret;
+}
+
+#undef    silk_SUB64
+static inline opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){
+    opus_int64 ret;
+    ops_count += 2;
+    ret = a - b;
+    return ret;
+}
+
+#undef silk_ADD_SAT16
+static inline opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) {
+    opus_int16 res;
+    /* Nb will be counted in AKP_add32 and silk_SAT16*/
+    res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
+    return res;
+}
+
+#undef silk_ADD_SAT32
+static inline opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){
+    opus_int32 res;
+    ops_count += 1;
+    res =    ((((a32) + (b32)) & 0x80000000) == 0 ?                                    \
+            ((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) :    \
+            ((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
+    return res;
+}
+
+#undef silk_ADD_SAT64
+static inline opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) {
+    opus_int64 res;
+    ops_count += 1;
+    res =    ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ?                                \
+            ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) :    \
+            ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
+    return res;
+}
+
+#undef silk_SUB_SAT16
+static inline opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) {
+    opus_int16 res;
+    silk_assert(0);
+    /* Nb will be counted in sub-macros*/
+    res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
+    return res;
+}
+
+#undef silk_SUB_SAT32
+static inline opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) {
+    opus_int32 res;
+    ops_count += 1;
+    res =     ((((a32)-(b32)) & 0x80000000) == 0 ?                                            \
+            (( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) :    \
+            ((((a32)^0x80000000) & (b32)  & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
+    return res;
+}
+
+#undef silk_SUB_SAT64
+static inline opus_int64 silk_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) {
+    opus_int64 res;
+    ops_count += 1;
+    res =    ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ?                                                        \
+            (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) :    \
+            ((((a64)^0x8000000000000000LL) & (b64)  & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
+
+    return res;
+}
+
+#undef    silk_SMULWW
+static inline opus_int32 silk_SMULWW(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    /* Nb will be counted in sub-macros*/
+    ret = silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16));
+    return ret;
+}
+
+#undef    silk_SMLAWW
+static inline opus_int32 silk_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    /* Nb will be counted in sub-macros*/
+    ret = silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16));
+    return ret;
+}
+
+#undef    silk_min_int
+static inline opus_int silk_min_int(opus_int a, opus_int b)
+{
+    ops_count += 1;
+    return (((a) < (b)) ? (a) : (b));
+}
+
+#undef    silk_min_16
+static inline opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
+{
+    ops_count += 1;
+    return (((a) < (b)) ? (a) : (b));
+}
+#undef    silk_min_32
+static inline opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
+{
+    ops_count += 1;
+    return (((a) < (b)) ? (a) : (b));
+}
+#undef    silk_min_64
+static inline opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
+{
+    ops_count += 1;
+    return (((a) < (b)) ? (a) : (b));
+}
+
+/* silk_min() versions with typecast in the function call */
+#undef    silk_max_int
+static inline opus_int silk_max_int(opus_int a, opus_int b)
+{
+    ops_count += 1;
+    return (((a) > (b)) ? (a) : (b));
+}
+#undef    silk_max_16
+static inline opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
+{
+    ops_count += 1;
+    return (((a) > (b)) ? (a) : (b));
+}
+#undef    silk_max_32
+static inline opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
+{
+    ops_count += 1;
+    return (((a) > (b)) ? (a) : (b));
+}
+
+#undef    silk_max_64
+static inline opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
+{
+    ops_count += 1;
+    return (((a) > (b)) ? (a) : (b));
+}
+
+
+#undef silk_LIMIT_int
+static inline opus_int silk_LIMIT_int(opus_int a, opus_int limit1, opus_int limit2)
+{
+    opus_int ret;
+    ops_count += 6;
+
+    ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+        : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+
+    return(ret);
+}
+
+#undef silk_LIMIT_16
+static inline opus_int16 silk_LIMIT_16(opus_int16 a, opus_int16 limit1, opus_int16 limit2)
+{
+    opus_int16 ret;
+    ops_count += 6;
+
+    ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+        : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+
+return(ret);
+}
+
+
+#undef silk_LIMIT_32
+static inline opus_int silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
+{
+    opus_int32 ret;
+    ops_count += 6;
+
+    ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+        : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
+    return(ret);
+}
+
+#else
+#define exVarDefine
+#define varDefine
+#define silk_SaveCount()
+
+#endif
+#endif
+
--- /dev/null
+++ b/silk/MacroDebug.h
@@ -1,0 +1,552 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef _SIGPROCFIX_API_DEBUG_H_
+#define _SIGPROCFIX_API_DEBUG_H_
+
+/* Redefine macro functions with extensive assertion in Win32_DEBUG mode.
+   As function can't be undefined, this file can't work with SigProcFIX_MacroCount.h */
+
+#if 0 && defined (_WIN32) && defined (_DEBUG) && !defined (silk_MACRO_COUNT)
+
+#undef    silk_ADD16
+static inline opus_int16 silk_ADD16(opus_int16 a, opus_int16 b){
+    opus_int16 ret;
+
+    ret = a + b;
+    silk_assert( ret == silk_ADD_SAT16( a, b ));
+    return ret;
+}
+
+#undef    silk_ADD32
+static inline opus_int32 silk_ADD32(opus_int32 a, opus_int32 b){
+    opus_int32 ret;
+
+    ret = a + b;
+    silk_assert( ret == silk_ADD_SAT32( a, b ));
+    return ret;
+}
+
+#undef    silk_ADD64
+static inline opus_int64 silk_ADD64(opus_int64 a, opus_int64 b){
+    opus_int64 ret;
+
+    ret = a + b;
+    silk_assert( ret == silk_ADD_SAT64( a, b ));
+    return ret;
+}
+
+#undef    silk_SUB16
+static inline opus_int16 silk_SUB16(opus_int16 a, opus_int16 b){
+    opus_int16 ret;
+
+    ret = a - b;
+    silk_assert( ret == silk_SUB_SAT16( a, b ));
+    return ret;
+}
+
+#undef    silk_SUB32
+static inline opus_int32 silk_SUB32(opus_int32 a, opus_int32 b){
+    opus_int32 ret;
+
+    ret = a - b;
+    silk_assert( ret == silk_SUB_SAT32( a, b ));
+    return ret;
+}
+
+#undef    silk_SUB64
+static inline opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){
+    opus_int64 ret;
+
+    ret = a - b;
+    silk_assert( ret == silk_SUB_SAT64( a, b ));
+    return ret;
+}
+
+#undef silk_ADD_SAT16
+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 ) );
+    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 ?                                    \
+            ((((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 ) );
+    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 ?                                \
+            ((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) :    \
+            ((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
+    if( res != a64 + b64 ) {
+        /* Check that we saturated to the correct extreme value */
+        silk_assert( ( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
+                    ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) );
+    } else {
+        /* Saturation not necessary */
+        silk_assert( res == a64 + b64 );
+    }
+    return res;
+}
+
+#undef silk_SUB_SAT16
+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 ) );
+    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 ?                                            \
+            (( (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 ) );
+    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 ?                                                        \
+            (( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) :    \
+            ((((a64)^0x8000000000000000LL) & (b64)  & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
+
+    if( res != a64 - b64 ) {
+        /* Check that we saturated to the correct extreme value */
+        silk_assert( ( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
+                    ( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) );
+    } else {
+        /* Saturation not necessary */
+        silk_assert( res == a64 - b64 );
+    }
+    return res;
+}
+
+#undef silk_MUL
+static inline opus_int32 silk_MUL(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    opus_int64 ret64; /* Will easily show how many bits that are needed */
+    ret = a32 * b32;
+    ret64 = (opus_int64)a32 * (opus_int64)b32;
+    silk_assert((opus_int64)ret == ret64 );        /* Check output overflow */
+    return ret;
+}
+
+#undef silk_MUL_uint
+static inline opus_uint32 silk_MUL_uint(opus_uint32 a32, opus_uint32 b32){
+    opus_uint32 ret;
+    ret = a32 * b32;
+    silk_assert((opus_uint64)ret == (opus_uint64)a32 * (opus_uint64)b32);        /* Check output overflow */
+    return ret;
+}
+#undef silk_MLA
+static inline opus_int32 silk_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ret = a32 + b32 * c32;
+    silk_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32);    /* Check output overflow */
+    return ret;
+}
+
+#undef silk_MLA_uint
+static inline opus_int32 silk_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){
+    opus_uint32 ret;
+    ret = a32 + b32 * c32;
+    silk_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32);    /* Check output overflow */
+    return ret;
+}
+
+#undef    silk_SMULWB
+static inline opus_int32 silk_SMULWB(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
+    silk_assert((opus_int64)ret == ((opus_int64)a32 * (opus_int16)b32) >> 16);
+    return ret;
+}
+#undef    silk_SMLAWB
+static inline opus_int32 silk_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ret = silk_ADD32( a32, silk_SMULWB( b32, c32 ) );
+    silk_assert(silk_ADD32( a32, silk_SMULWB( b32, c32 ) ) == silk_ADD_SAT32( a32, silk_SMULWB( b32, c32 ) ));
+    return ret;
+}
+
+#undef silk_SMULWT
+static inline opus_int32 silk_SMULWT(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret;
+    ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
+    silk_assert((opus_int64)ret == ((opus_int64)a32 * (b32 >> 16)) >> 16);
+    return ret;
+}
+#undef silk_SMLAWT
+static inline opus_int32 silk_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
+    silk_assert((opus_int64)ret == (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16));
+    return ret;
+}
+
+#undef silk_SMULL
+static inline opus_int64 silk_SMULL(opus_int64 a64, opus_int64 b64){
+    opus_int64 ret64;
+    ret64 = a64 * b64;
+    if( b64 != 0 ) {
+        silk_assert( a64 == (ret64 / b64) );
+    } else if( a64 != 0 ) {
+        silk_assert( b64 == (ret64 / a64) );
+    }
+    return ret64;
+}
+
+/* no checking needed for silk_SMULBB */
+#undef    silk_SMLABB
+static inline opus_int32 silk_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
+    silk_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32);
+    return ret;
+}
+
+/* no checking needed for silk_SMULBT */
+#undef    silk_SMLABT
+static inline opus_int32 silk_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
+    silk_assert((opus_int64)ret == (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16));
+    return ret;
+}
+
+/* no checking needed for silk_SMULTT */
+#undef    silk_SMLATT
+static inline opus_int32 silk_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret;
+    ret = a32 + (b32 >> 16) * (c32 >> 16);
+    silk_assert((opus_int64)ret == (opus_int64)a32 + (b32 >> 16) * (c32 >> 16));
+    return ret;
+}
+
+#undef    silk_SMULWW
+static inline opus_int32 silk_SMULWW(opus_int32 a32, opus_int32 b32){
+    opus_int32 ret, tmp1, tmp2;
+    opus_int64 ret64;
+
+    ret  = silk_SMULWB( a32, b32 );
+    tmp1 = silk_RSHIFT_ROUND( b32, 16 );
+    tmp2 = silk_MUL( a32, tmp1 );
+
+    silk_assert( (opus_int64)tmp2 == (opus_int64) a32 * (opus_int64) tmp1 );
+
+    tmp1 = ret;
+    ret  = silk_ADD32( tmp1, tmp2 );
+    silk_assert( silk_ADD32( tmp1, tmp2 ) == silk_ADD_SAT32( tmp1, tmp2 ) );
+
+    ret64 = silk_RSHIFT64( silk_SMULL( a32, b32 ), 16 );
+    silk_assert( (opus_int64)ret == ret64 );
+
+    return ret;
+}
+
+#undef    silk_SMLAWW
+static inline opus_int32 silk_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){
+    opus_int32 ret, tmp;
+
+    tmp = silk_SMULWW( b32, c32 );
+    ret = silk_ADD32( a32, tmp );
+    silk_assert( ret == silk_ADD_SAT32( a32, tmp ) );
+    return ret;
+}
+
+/* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
+#undef    silk_MLA_ovflw
+#define silk_MLA_ovflw(a32, b32, c32)    ((a32) + ((b32) * (c32)))
+#undef    silk_SMLABB_ovflw
+#define silk_SMLABB_ovflw(a32, b32, c32)    ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))
+
+/* no checking needed for silk_SMULL
+   no checking needed for silk_SMLAL
+   no checking needed for silk_SMLALBB
+   no checking needed for SigProcFIX_CLZ16
+   no checking needed for SigProcFIX_CLZ32*/
+
+#undef silk_DIV32
+static inline opus_int32 silk_DIV32(opus_int32 a32, opus_int32 b32){
+    silk_assert( b32 != 0 );
+    return a32 / b32;
+}
+
+#undef silk_DIV32_16
+static inline opus_int32 silk_DIV32_16(opus_int32 a32, opus_int32 b32){
+    silk_assert( b32 != 0 );
+    silk_assert( b32 <= silk_int16_MAX );
+    silk_assert( b32 >= silk_int16_MIN );
+    return a32 / b32;
+}
+
+/* no checking needed for silk_SAT8
+   no checking needed for silk_SAT16
+   no checking needed for silk_SAT32
+   no checking needed for silk_POS_SAT32
+   no checking needed for silk_ADD_POS_SAT8
+   no checking needed for silk_ADD_POS_SAT16
+   no checking needed for silk_ADD_POS_SAT32
+   no checking needed for silk_ADD_POS_SAT64 */
+#undef    silk_LSHIFT8
+static inline opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
+    opus_int8 ret;
+    ret = a << shift;
+    silk_assert(shift >= 0);
+    silk_assert(shift < 8);
+    silk_assert((opus_int64)ret == ((opus_int64)a) << shift);
+    return ret;
+}
+#undef    silk_LSHIFT16
+static inline opus_int16 silk_LSHIFT16(opus_int16 a, opus_int32 shift){
+    opus_int16 ret;
+    ret = a << shift;
+    silk_assert(shift >= 0);
+    silk_assert(shift < 16);
+    silk_assert((opus_int64)ret == ((opus_int64)a) << shift);
+    return ret;
+}
+#undef    silk_LSHIFT32
+static inline opus_int32 silk_LSHIFT32(opus_int32 a, opus_int32 shift){
+    opus_int32 ret;
+    ret = a << shift;
+    silk_assert(shift >= 0);
+    silk_assert(shift < 32);
+    silk_assert((opus_int64)ret == ((opus_int64)a) << shift);
+    return ret;
+}
+#undef    silk_LSHIFT64
+static inline opus_int64 silk_LSHIFT64(opus_int64 a, opus_int shift){
+    silk_assert(shift >= 0);
+    silk_assert(shift < 64);
+    return a << shift;
+}
+
+#undef    silk_LSHIFT_ovflw
+static inline opus_int32 silk_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){
+    silk_assert(shift >= 0);            /* no check for overflow */
+    return a << shift;
+}
+
+#undef    silk_LSHIFT_uint
+static inline opus_uint32 silk_LSHIFT_uint(opus_uint32 a, opus_int32 shift){
+    opus_uint32 ret;
+    ret = a << shift;
+    silk_assert(shift >= 0);
+    silk_assert((opus_int64)ret == ((opus_int64)a) << shift);
+    return ret;
+}
+
+#undef    silk_RSHIFT8
+static inline opus_int8 silk_RSHIFT8(opus_int8 a, opus_int32 shift){
+    silk_assert(shift >=  0);
+    silk_assert(shift < 8);
+    return a >> shift;
+}
+#undef    silk_RSHIFT16
+static inline opus_int16 silk_RSHIFT16(opus_int16 a, opus_int32 shift){
+    silk_assert(shift >=  0);
+    silk_assert(shift < 16);
+    return a >> shift;
+}
+#undef    silk_RSHIFT32
+static inline opus_int32 silk_RSHIFT32(opus_int32 a, opus_int32 shift){
+    silk_assert(shift >=  0);
+    silk_assert(shift < 32);
+    return a >> shift;
+}
+#undef    silk_RSHIFT64
+static inline opus_int64 silk_RSHIFT64(opus_int64 a, opus_int64 shift){
+    silk_assert(shift >=  0);
+    silk_assert(shift <= 63);
+    return a >> shift;
+}
+
+#undef    silk_RSHIFT_uint
+static inline opus_uint32 silk_RSHIFT_uint(opus_uint32 a, opus_int32 shift){
+    silk_assert(shift >=  0);
+    silk_assert(shift <= 32);
+    return a >> shift;
+}
+
+#undef    silk_ADD_LSHIFT
+static inline opus_int32 silk_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    silk_assert(shift >= 0);
+    silk_assert(shift <= 31);
+    ret = a + (b << shift);
+    silk_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift));
+    return ret;                /* shift >= 0 */
+}
+#undef    silk_ADD_LSHIFT32
+static inline opus_int32 silk_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    silk_assert(shift >= 0);
+    silk_assert(shift <= 31);
+    ret = a + (b << shift);
+    silk_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift));
+    return ret;                /* shift >= 0 */
+}
+#undef    silk_ADD_LSHIFT_uint
+static inline opus_uint32 silk_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
+    opus_uint32 ret;
+    silk_assert(shift >= 0);
+    silk_assert(shift <= 32);
+    ret = a + (b << shift);
+    silk_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) << shift));
+    return ret;                /* shift >= 0 */
+}
+#undef    silk_ADD_RSHIFT
+static inline opus_int32 silk_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    silk_assert(shift >= 0);
+    silk_assert(shift <= 31);
+    ret = a + (b >> shift);
+    silk_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift));
+    return ret;                /* shift  > 0 */
+}
+#undef    silk_ADD_RSHIFT32
+static inline opus_int32 silk_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    silk_assert(shift >= 0);
+    silk_assert(shift <= 31);
+    ret = a + (b >> shift);
+    silk_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift));
+    return ret;                /* shift  > 0 */
+}
+#undef    silk_ADD_RSHIFT_uint
+static inline opus_uint32 silk_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
+    opus_uint32 ret;
+    silk_assert(shift >= 0);
+    silk_assert(shift <= 32);
+    ret = a + (b >> shift);
+    silk_assert((opus_int64)ret == (opus_int64)a + (((opus_int64)b) >> shift));
+    return ret;                /* shift  > 0 */
+}
+#undef    silk_SUB_LSHIFT32
+static inline opus_int32 silk_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    silk_assert(shift >= 0);
+    silk_assert(shift <= 31);
+    ret = a - (b << shift);
+    silk_assert((opus_int64)ret == (opus_int64)a - (((opus_int64)b) << shift));
+    return ret;                /* shift >= 0 */
+}
+#undef    silk_SUB_RSHIFT32
+static inline opus_int32 silk_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
+    opus_int32 ret;
+    silk_assert(shift >= 0);
+    silk_assert(shift <= 31);
+    ret = a - (b >> shift);
+    silk_assert((opus_int64)ret == (opus_int64)a - (((opus_int64)b) >> shift));
+    return ret;                /* shift  > 0 */
+}
+
+#undef    silk_RSHIFT_ROUND
+static inline opus_int32 silk_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){
+    opus_int32 ret;
+    silk_assert(shift > 0);        /* the marco definition can't handle a shift of zero */
+    silk_assert(shift < 32);
+    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+    silk_assert((opus_int64)ret == ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift);
+    return ret;
+}
+
+#undef    silk_RSHIFT_ROUND64
+static inline opus_int64 silk_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){
+    opus_int64 ret;
+    silk_assert(shift > 0);        /* the marco definition can't handle a shift of zero */
+    silk_assert(shift < 64);
+    ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
+    return ret;
+}
+
+/* silk_abs is used on floats also, so doesn't work... */
+/*#undef    silk_abs
+static inline opus_int32 silk_abs(opus_int32 a){
+    silk_assert(a != 0x80000000);
+    return (((a) >  0)  ? (a) : -(a));            // Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN
+}*/
+
+#undef    silk_abs_int64
+static inline opus_int64 silk_abs_int64(opus_int64 a){
+    silk_assert(a != 0x8000000000000000);
+    return (((a) >  0)  ? (a) : -(a));            /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
+}
+
+#undef    silk_abs_int32
+static inline opus_int32 silk_abs_int32(opus_int32 a){
+    silk_assert(a != 0x80000000);
+    return abs(a);
+}
+
+#undef    silk_CHECK_FIT8
+static inline opus_int8 silk_CHECK_FIT8( opus_int64 a ){
+    opus_int8 ret;
+    ret = (opus_int8)a;
+    silk_assert( (opus_int64)ret == a );
+    return( ret );
+}
+
+#undef    silk_CHECK_FIT16
+static inline opus_int16 silk_CHECK_FIT16( opus_int64 a ){
+    opus_int16 ret;
+    ret = (opus_int16)a;
+    silk_assert( (opus_int64)ret == a );
+    return( ret );
+}
+
+#undef    silk_CHECK_FIT32
+static inline opus_int32 silk_CHECK_FIT32( opus_int64 a ){
+    opus_int32 ret;
+    ret = (opus_int32)a;
+    silk_assert( (opus_int64)ret == a );
+    return( ret );
+}
+
+/* no checking for silk_NSHIFT_MUL_32_32
+   no checking for silk_NSHIFT_MUL_16_16
+   no checking needed for silk_min
+   no checking needed for silk_max
+   no checking needed for silk_sign
+*/
+
+#endif
+#endif
--- /dev/null
+++ b/silk/NLSF2A.c
@@ -1,0 +1,175 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* conversion between prediction filter coefficients and LSFs   */
+/* order should be even                                         */
+/* a piecewise linear approximation maps LSF <-> cos(LSF)       */
+/* therefore the result is not accurate LSFs, but the two       */
+/* functions are accurate inverses of each other                */
+
+#include "SigProc_FIX.h"
+#include "tables.h"
+
+#define QA      16
+
+/* helper function for NLSF2A(..) */
+static inline void silk_NLSF2A_find_poly(
+    opus_int32          *out,      /* O    intermediate polynomial, QA [dd+1]        */
+    const opus_int32    *cLSF,     /* I    vector of interleaved 2*cos(LSFs), QA [d] */
+    opus_int            dd         /* I    polynomial order (= 1/2 * filter order)   */
+)
+{
+    opus_int   k, n;
+    opus_int32 ftmp;
+
+    out[0] = silk_LSHIFT( 1, QA );
+    out[1] = -cLSF[0];
+    for( k = 1; k < dd; k++ ) {
+        ftmp = cLSF[2*k];            /* QA*/
+        out[k+1] = silk_LSHIFT( out[k-1], 1 ) - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[k] ), QA );
+        for( n = k; n > 1; n-- ) {
+            out[n] += out[n-2] - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[n-1] ), QA );
+        }
+        out[1] -= ftmp;
+    }
+}
+
+/* compute whitening filter coefficients from normalized line spectral frequencies */
+void silk_NLSF2A(
+    opus_int16        *a_Q12,            /* O    monic whitening filter coefficients in Q12,  [ d ]  */
+    const opus_int16  *NLSF,             /* I    normalized line spectral frequencies in Q15, [ d ]  */
+    const opus_int    d                  /* I    filter order (should be even)                       */
+)
+{
+    opus_int   k, i, dd;
+    opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ];
+    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;
+
+    silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
+
+    /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
+    for( k = 0; k < d; k++ ) {
+        silk_assert(NLSF[k] >= 0 );
+        silk_assert(NLSF[k] <= 32767 );
+
+        /* f_int on a scale 0-127 (rounded down) */
+        f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
+
+        /* f_frac, range: 0..255 */
+        f_frac = NLSF[k] - silk_LSHIFT( f_int, 15 - 7 );
+
+        silk_assert(f_int >= 0);
+        silk_assert(f_int < LSF_COS_TAB_SZ_FIX );
+
+        /* Read start and end value from table */
+        cos_val = silk_LSFCosTab_FIX_Q12[ f_int ];                /* Q12 */
+        delta   = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val;  /* Q12, with a range of 0..200 */
+
+        /* Linear interpolation */
+        cos_LSF_QA[k] = silk_RSHIFT_ROUND( silk_LSHIFT( cos_val, 8 ) + silk_MUL( delta, f_frac ), 20 - QA ); /* QA */
+    }
+
+    dd = silk_RSHIFT( d, 1 );
+
+    /* generate even and odd polynomials using convolution */
+    silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd );
+    silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd );
+
+    /* convert even and odd polynomials to opus_int32 Q12 filter coefs */
+    for( k = 0; k < dd; k++ ) {
+        Ptmp = P[ k+1 ] + P[ k ];
+        Qtmp = Q[ k+1 ] - Q[ k ];
+
+        /* the Ptmp and Qtmp values at this stage need to fit in int32 */
+        a32_QA1[ k ]     = -Qtmp - Ptmp;        /* QA+1 */
+        a32_QA1[ d-k-1 ] =  Qtmp - Ptmp;        /* QA+1 */
+    }
+
+    /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
+    for( i = 0; i < 10; i++ ) {
+        /* Find maximum absolute value and its index */
+        maxabs = 0;
+        for( k = 0; k < d; k++ ) {
+            absval = silk_abs( a32_QA1[k] );
+            if( absval > maxabs ) {
+                maxabs = absval;
+                idx    = k;
+            }
+        }
+        maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 );       /* QA+1 -> Q12 */
+
+        if( maxabs > silk_int16_MAX ) {
+            /* Reduce magnitude of prediction coefficients */
+            maxabs = silk_min( maxabs, 163838 );  /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
+            sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
+                                        silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
+            silk_bwexpander_32( a32_QA1, d, sc_Q16 );
+        } else {
+            break;
+        }
+    }
+
+    if( i == 10 ) {
+        /* Reached the last iteration, clip the coefficients */
+        for( k = 0; k < d; k++ ) {
+            a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) ); /* QA+1 -> Q12 */
+            a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 );
+        }
+    } else {
+        for( k = 0; k < d; k++ ) {
+            a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );       /* QA+1 -> Q12 */
+        }
+    }
+
+    for( i = 1; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
+        if( silk_LPC_inverse_pred_gain( &invGain_Q30, a_Q12, d ) == 1 ) {
+            /* 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 */
+            for( k = 0; k < d; k++ ) {
+                a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );  /* QA+1 -> Q12 */
+            }
+        } else {
+            break;
+        }
+    }
+
+    if( i == MAX_LPC_STABILIZE_ITERATIONS ) {
+        /* Reached the last iteration, set coefficients to zero */
+        for( k = 0; k < d; k++ ) {
+            a_Q12[ k ] = 0;
+        }
+    }
+}
+
--- /dev/null
+++ b/silk/NLSF_VQ.c
@@ -1,0 +1,68 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
+void silk_NLSF_VQ(
+    opus_int32                   err_Q26[],              /* O    Quantization errors [K]                     */
+    const opus_int16             in_Q15[],               /* I    Input vectors to be quantized [LPC_order]   */
+    const opus_uint8             pCB_Q8[],               /* I    Codebook vectors [K*LPC_order]              */
+    const opus_int               K,                      /* I    Number of codebook vectors                  */
+    const opus_int               LPC_order               /* I    Number of LPCs                              */
+)
+{
+    opus_int        i, m;
+    opus_int32      diff_Q15, sum_error_Q30, sum_error_Q26;
+
+    silk_assert( LPC_order <= 16 );
+    silk_assert( ( LPC_order & 1 ) == 0 );
+
+    /* Loop over codebook */
+    for( i = 0; i < K; i++ ) {
+        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 ]*/
+            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 ]*/
+            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 );
+
+            silk_assert( sum_error_Q26 >= 0 );
+            silk_assert( sum_error_Q30 >= 0 );
+        }
+        err_Q26[ i ] = sum_error_Q26;
+    }
+}
--- /dev/null
+++ b/silk/NLSF_VQ_weights_laroia.c
@@ -1,0 +1,80 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "define.h"
+#include "SigProc_FIX.h"
+
+/*
+R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP
+Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech,
+Signal Processing, pp. 641-644, 1991.
+*/
+
+/* Laroia low complexity NLSF weights */
+void silk_NLSF_VQ_weights_laroia(
+    opus_int16           *pNLSFW_Q_OUT,      /* O: Pointer to input vector weights           [D x 1]     */
+    const opus_int16     *pNLSF_Q15,         /* I: Pointer to input vector                   [D x 1]     */
+    const opus_int       D                   /* I: Input vector dimension (even)                         */
+)
+{
+    opus_int   k;
+    opus_int32 tmp1_int, tmp2_int;
+
+    silk_assert( D > 0 );
+    silk_assert( ( D & 1 ) == 0 );
+
+    /* First value */
+    tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
+    tmp1_int = silk_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int );
+    tmp2_int = silk_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 );
+    tmp2_int = silk_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp2_int );
+    pNLSFW_Q_OUT[ 0 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+    silk_assert( pNLSFW_Q_OUT[ 0 ] > 0 );
+
+    /* Main loop */
+    for( k = 1; k < D - 1; k += 2 ) {
+        tmp1_int = silk_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 );
+        tmp1_int = silk_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int );
+        pNLSFW_Q_OUT[ k ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+        silk_assert( pNLSFW_Q_OUT[ k ] > 0 );
+
+        tmp2_int = silk_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 );
+        tmp2_int = silk_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp2_int );
+        pNLSFW_Q_OUT[ k + 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+        silk_assert( pNLSFW_Q_OUT[ k + 1 ] > 0 );
+    }
+
+    /* Last value */
+    tmp1_int = silk_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 );
+    tmp1_int = silk_DIV32_16( 1 << ( 15 + NLSF_W_Q ), tmp1_int );
+    pNLSFW_Q_OUT[ D - 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
+    silk_assert( pNLSFW_Q_OUT[ D - 1 ] > 0 );
+}
--- /dev/null
+++ b/silk/NLSF_decode.c
@@ -1,0 +1,101 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Predictive dequantizer for NLSF residuals */
+void silk_NLSF_residual_dequant(                            /* O    Returns RD value in Q30                     */
+          opus_int16         x_Q10[],                        /* O    Output [ order ]                            */
+    const opus_int8          indices[],                      /* I    Quantization indices [ order ]              */
+    const opus_uint8         pred_coef_Q8[],                 /* I    Backward predictor coefs [ order ]          */
+    const opus_int           quant_step_size_Q16,            /* I    Quantization step size                      */
+    const opus_int16         order                           /* I    Number of input values                      */
+)
+{
+    opus_int     i, out_Q10, pred_Q10;
+
+    out_Q10 = 0;
+    for( i = order-1; i >= 0; i-- ) {
+        pred_Q10 = silk_RSHIFT( silk_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 );
+        out_Q10  = silk_LSHIFT( indices[ i ], 10 );
+        if( out_Q10 > 0 ) {
+            out_Q10 = silk_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+        } else if( out_Q10 < 0 ) {
+            out_Q10 = silk_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+        }
+        out_Q10  = silk_SMLAWB( pred_Q10, out_Q10, quant_step_size_Q16 );
+        x_Q10[ i ] = out_Q10;
+    }
+}
+
+
+/***********************/
+/* NLSF vector decoder */
+/***********************/
+void silk_NLSF_decode(
+          opus_int16             *pNLSF_Q15,             /* O    Quantized NLSF vector [ LPC_ORDER ]     */
+          opus_int8              *NLSFIndices,           /* I    Codebook path vector [ LPC_ORDER + 1 ]  */
+    const silk_NLSF_CB_struct   *psNLSF_CB              /* I    Codebook object                         */
+)
+{
+    opus_int         i;
+    opus_uint8       pred_Q8[  MAX_LPC_ORDER ];
+    opus_int16       ec_ix[    MAX_LPC_ORDER ];
+    opus_int16       res_Q10[  MAX_LPC_ORDER ];
+    opus_int16       W_tmp_QW[ MAX_LPC_ORDER ];
+    opus_int32       W_tmp_Q9, NLSF_Q15_tmp;
+    const opus_uint8 *pCB_element;
+
+    /* 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 );
+    }
+
+    /* Unpack entropy table indices and predictor for current CB1 index */
+    silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
+
+    /* Trellis dequantizer */
+    silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
+
+    /* Weights from codebook vector */
+    silk_NLSF_VQ_weights_laroia( W_tmp_QW, pNLSF_Q15, psNLSF_CB->order );
+
+    /* 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 ) );
+        pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
+    }
+
+    /* NLSF stabilization */
+    silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
+}
--- /dev/null
+++ b/silk/NLSF_del_dec_quant.c
@@ -1,0 +1,205 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Delayed-decision quantizer for NLSF residuals */
+opus_int32 silk_NLSF_del_dec_quant(                      /* O    Returns RD value in Q25                     */
+    opus_int8                    indices[],              /* O    Quantization indices [ order ]              */
+    const opus_int16             x_Q10[],                /* I    Input [ order ]                             */
+    const opus_int16             w_Q5[],                 /* I    Weights [ order ]                           */
+    const opus_uint8             pred_coef_Q8[],         /* I    Backward predictor coefs [ order ]          */
+    const opus_int16             ec_ix[],                /* I    Indices to entropy coding tables [ order ]  */
+    const opus_uint8             ec_rates_Q5[],          /* I    Rates []                                    */
+    const opus_int               quant_step_size_Q16,    /* I    Quantization step size                      */
+    const opus_int16             inv_quant_step_size_Q6, /* I    Inverse quantization step size              */
+    const opus_int32             mu_Q20,                 /* I    R/D tradeoff                                */
+    const opus_int16             order                   /* I    Number of input values                      */
+)
+{
+    opus_int         i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10;
+    opus_int         pred_Q10, diff_Q10, out0_Q10, out1_Q10, rate0_Q5, rate1_Q5;
+    opus_int32       RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25, pred_coef_Q16;
+    opus_int         ind_sort[         NLSF_QUANT_DEL_DEC_STATES ];
+    opus_int8        ind[              NLSF_QUANT_DEL_DEC_STATES ][ MAX_LPC_ORDER ];
+    opus_int16       prev_out_Q10[ 2 * NLSF_QUANT_DEL_DEC_STATES ];
+    opus_int32       RD_Q25[       2 * NLSF_QUANT_DEL_DEC_STATES ];
+    opus_int32       RD_min_Q25[       NLSF_QUANT_DEL_DEC_STATES ];
+    opus_int32       RD_max_Q25[       NLSF_QUANT_DEL_DEC_STATES ];
+    const opus_uint8 *rates_Q5;
+
+    silk_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 );     /* must be power of two */
+
+    nStates = 1;
+    RD_Q25[ 0 ] = 0;
+    prev_out_Q10[ 0 ] = 0;
+    for( i = order - 1; ; i-- ) {
+        rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ];
+        pred_coef_Q16 = silk_LSHIFT( (opus_int32)pred_coef_Q8[ i ], 8 );
+        in_Q10 = x_Q10[ i ];
+        for( j = 0; j < nStates; j++ ) {
+            pred_Q10 = silk_SMULWB( pred_coef_Q16, prev_out_Q10[ j ] );
+            res_Q10  = silk_SUB16( in_Q10, pred_Q10 );
+            ind_tmp  = silk_SMULWB( inv_quant_step_size_Q6, res_Q10 );
+            ind_tmp  = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 );
+            ind[ j ][ i ] = (opus_int8)ind_tmp;
+
+            /* compute outputs for ind_tmp and ind_tmp + 1 */
+            out0_Q10 = silk_LSHIFT( ind_tmp, 10 );
+            out1_Q10 = silk_ADD16( out0_Q10, 1024 );
+            if( ind_tmp > 0 ) {
+                out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+                out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+            } else if( ind_tmp == 0 ) {
+                out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+            } else if( ind_tmp == -1 ) {
+                out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+            } else {
+                out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+                out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
+            }
+            out0_Q10  = silk_SMULWB( out0_Q10, quant_step_size_Q16 );
+            out1_Q10  = silk_SMULWB( out1_Q10, quant_step_size_Q16 );
+            out0_Q10  = silk_ADD16( out0_Q10, pred_Q10 );
+            out1_Q10  = silk_ADD16( out1_Q10, pred_Q10 );
+            prev_out_Q10[ j           ] = out0_Q10;
+            prev_out_Q10[ j + nStates ] = out1_Q10;
+
+            /* compute RD for ind_tmp and ind_tmp + 1 */
+            if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) {
+                if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) {
+                    rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ];
+                    rate1_Q5 = 280;
+                } else {
+                    rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp );
+                    rate1_Q5 = silk_ADD16( rate0_Q5, 43 );
+                }
+            } else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) {
+                if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) {
+                    rate0_Q5 = 280;
+                    rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ];
+                } else {
+                    rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp );
+                    rate1_Q5 = silk_SUB16( rate0_Q5, 43 );
+                }
+            } else {
+                rate0_Q5 = rates_Q5[ ind_tmp +     NLSF_QUANT_MAX_AMPLITUDE ];
+                rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ];
+            }
+            RD_tmp_Q25            = RD_Q25[ j ];
+            diff_Q10              = silk_SUB16( in_Q10, out0_Q10 );
+            RD_Q25[ j ]           = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 );
+            diff_Q10              = silk_SUB16( in_Q10, out1_Q10 );
+            RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 );
+        }
+
+        if( nStates < NLSF_QUANT_DEL_DEC_STATES ) {
+            /* double number of states and copy */
+            for( j = 0; j < nStates; j++ ) {
+                ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1;
+            }
+            nStates = silk_LSHIFT( nStates, 1 );
+            for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
+                ind[ j ][ i ] = ind[ j - nStates ][ i ];
+            }
+        } else if( i > 0 ) {
+            /* sort lower and upper half of RD_Q25, pairwise */
+            for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
+                if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) {
+                    RD_max_Q25[ j ]                         = RD_Q25[ j ];
+                    RD_min_Q25[ j ]                         = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ];
+                    RD_Q25[ j ]                             = RD_min_Q25[ j ];
+                    RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ];
+                    /* swap prev_out values */
+                    out0_Q10 = prev_out_Q10[ j ];
+                    prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ];
+                    prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10;
+                    ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES;
+                } else {
+                    RD_min_Q25[ j ] = RD_Q25[ j ];
+                    RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ];
+                    ind_sort[ j ] = j;
+                }
+            }
+            /* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */
+            /* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */
+            while( 1 ) {
+                min_max_Q25 = silk_int32_MAX;
+                max_min_Q25 = 0;
+                ind_min_max = 0;
+                ind_max_min = 0;
+                for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
+                    if( min_max_Q25 > RD_max_Q25[ j ] ) {
+                        min_max_Q25 = RD_max_Q25[ j ];
+                        ind_min_max = j;
+                    }
+                    if( max_min_Q25 < RD_min_Q25[ j ] ) {
+                        max_min_Q25 = RD_min_Q25[ j ];
+                        ind_max_min = j;
+                    }
+                }
+                if( min_max_Q25 >= max_min_Q25 ) {
+                    break;
+                }
+                /* copy ind_min_max to ind_max_min */
+                ind_sort[     ind_max_min ] = ind_sort[     ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES;
+                RD_Q25[       ind_max_min ] = RD_Q25[       ind_min_max + NLSF_QUANT_DEL_DEC_STATES ];
+                prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ];
+                RD_min_Q25[   ind_max_min ] = 0;
+                RD_max_Q25[   ind_min_max ] = silk_int32_MAX;
+                silk_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) );
+            }
+            /* increment index if it comes from the upper half */
+            for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
+                ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 );
+            }
+        } else {  /* i == 0 */
+            /* last sample: find winner, copy indices and return RD value */
+            ind_tmp = 0;
+            min_Q25 = silk_int32_MAX;
+            for( j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++ ) {
+                if( min_Q25 > RD_Q25[ j ] ) {
+                    min_Q25 = RD_Q25[ j ];
+                    ind_tmp = j;
+                }
+            }
+            for( j = 0; j < order; j++ ) {
+                indices[ j ] = ind[ ind_tmp & ( NLSF_QUANT_DEL_DEC_STATES - 1 ) ][ j ];
+                silk_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT );
+                silk_assert( indices[ j ] <=  NLSF_QUANT_MAX_AMPLITUDE_EXT );
+            }
+            indices[ 0 ] += silk_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 );
+            silk_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT );
+            silk_assert( min_Q25 >= 0 );
+            return min_Q25;
+        }
+    }
+}
--- /dev/null
+++ b/silk/NLSF_encode.c
@@ -1,0 +1,187 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+#define STORE_LSF_DATA_FOR_TRAINING          0
+
+/***********************/
+/* NLSF vector encoder */
+/***********************/
+opus_int32 silk_NLSF_encode(                                 /* O    Returns RD value in Q25                 */
+          opus_int8                  *NLSFIndices,           /* I    Codebook path vector [ LPC_ORDER + 1 ]  */
+          opus_int16                 *pNLSF_Q15,             /* I/O  Quantized NLSF vector [ LPC_ORDER ]     */
+    const silk_NLSF_CB_struct       *psNLSF_CB,             /* I    Codebook object                         */
+    const opus_int16                 *pW_QW,                 /* I    NLSF weight vector [ LPC_ORDER ]        */
+    const opus_int                   NLSF_mu_Q20,            /* I    Rate weight for the RD optimization     */
+    const opus_int                   nSurvivors,             /* I    Max survivors after first stage         */
+    const opus_int                   signalType              /* I    Signal type: 0/1/2                      */
+)
+{
+    opus_int         i, s, ind1, bestIndex, prob_Q8, bits_q7;
+    opus_int32       W_tmp_Q9;
+    opus_int32       err_Q26[      NLSF_VQ_MAX_VECTORS ];
+    opus_int32       RD_Q25[       NLSF_VQ_MAX_SURVIVORS ];
+    opus_int         tempIndices1[ NLSF_VQ_MAX_SURVIVORS ];
+    opus_int8        tempIndices2[ NLSF_VQ_MAX_SURVIVORS * MAX_LPC_ORDER ];
+    opus_int16       res_Q15[      MAX_LPC_ORDER ];
+    opus_int16       res_Q10[      MAX_LPC_ORDER ];
+    opus_int16       NLSF_tmp_Q15[ MAX_LPC_ORDER ];
+    opus_int16       W_tmp_QW[     MAX_LPC_ORDER ];
+    opus_int16       W_adj_Q5[     MAX_LPC_ORDER ];
+    opus_uint8       pred_Q8[      MAX_LPC_ORDER ];
+    opus_int16       ec_ix[        MAX_LPC_ORDER ];
+    const opus_uint8 *pCB_element, *iCDF_ptr;
+
+#if STORE_LSF_DATA_FOR_TRAINING
+    opus_int16       pNLSF_Q15_orig[MAX_LPC_ORDER ];
+    DEBUG_STORE_DATA( NLSF.dat,    pNLSF_Q15,    psNLSF_CB->order * sizeof( opus_int16 ) );
+    DEBUG_STORE_DATA( WNLSF.dat,   pW_Q5,        psNLSF_CB->order * sizeof( opus_int16 ) );
+    DEBUG_STORE_DATA( NLSF_mu.dat, &NLSF_mu_Q20,                    sizeof( opus_int   ) );
+    DEBUG_STORE_DATA( sigType.dat, &signalType,                     sizeof( opus_int   ) );
+    silk_memcpy(pNLSF_Q15_orig, pNLSF_Q15, sizeof( pNLSF_Q15_orig ));
+#endif
+
+    silk_assert( nSurvivors <= NLSF_VQ_MAX_SURVIVORS );
+    silk_assert( signalType >= 0 && signalType <= 2 );
+    silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
+
+    /* NLSF stabilization */
+    silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
+
+    /* First stage: VQ */
+    silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order );
+
+    /* Sort the quantization errors */
+    silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
+
+    /* Loop over survivors */
+    for( s = 0; s < nSurvivors; s++ ) {
+        ind1 = tempIndices1[ s ];
+
+        /* 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 );
+            res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ];
+        }
+
+        /* Weights from codebook vector */
+        silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order );
+
+        /* 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 );
+        }
+
+        /* 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 ] );
+        }
+
+        /* Unpack entropy table indices and predictor for current CB1 index */
+        silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 );
+
+        /* Trellis quantizer */
+        RD_Q25[ s ] = silk_NLSF_del_dec_quant( &tempIndices2[ s * MAX_LPC_ORDER ], res_Q10, W_adj_Q5, pred_Q8, ec_ix,
+            psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order );
+
+        /* Add rate for first stage */
+        iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ];
+        if( ind1 == 0 ) {
+            prob_Q8 = 256 - iCDF_ptr[ ind1 ];
+        } else {
+            prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ];
+        }
+        bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 );
+        RD_Q25[ s ] = silk_SMLABB( RD_Q25[ s ], bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) );
+    }
+
+    /* Find the lowest rate-distortion error */
+    silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 );
+
+    NLSFIndices[ 0 ] = ( opus_int8 )tempIndices1[ bestIndex ];
+    silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) );
+
+    /* Decode */
+    silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB );
+
+#if STORE_LSF_DATA_FOR_TRAINING
+    {
+        /* code for training the codebooks */
+        opus_int32 RD_dec_Q22, Dist_Q22_dec, Rate_Q7, diff_Q15;
+        ind1 = NLSFIndices[ 0 ];
+        silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 );
+
+        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 );
+        }
+        silk_NLSF_VQ_weights_laroia( W_tmp_QW, NLSF_tmp_Q15, psNLSF_CB->order );
+        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_Q15[ i ] = pNLSF_Q15_orig[ i ] - NLSF_tmp_Q15[ i ];
+            res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
+            DEBUG_STORE_DATA( NLSF_res_q10.dat, &res_Q10[ i ], sizeof( opus_int16 ) );
+            res_Q15[ i ] = pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ];
+            res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( res_Q15[ i ], W_tmp_Q9 ), 14 );
+            DEBUG_STORE_DATA( NLSF_resq_q10.dat, &res_Q10[ i ], sizeof( opus_int16 ) );
+        }
+
+        Dist_Q22_dec = 0;
+        for( i = 0; i < psNLSF_CB->order; i++ ) {
+            diff_Q15 = pNLSF_Q15_orig[ i ] - pNLSF_Q15[ i ];
+            Dist_Q22_dec += ( ( (diff_Q15 >> 5) * (diff_Q15 >> 5) ) * pW_Q5[ i ] ) >> 3;
+        }
+        iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ];
+        if( ind1 == 0 ) {
+            prob_Q8 = 256 - iCDF_ptr[ ind1 ];
+        } else {
+            prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ];
+        }
+        Rate_Q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 );
+        for( i = 0; i < psNLSF_CB->order; i++ ) {
+            Rate_Q7 += ((int)psNLSF_CB->ec_Rates_Q5[ ec_ix[ i ] + silk_LIMIT( NLSFIndices[ i + 1 ] + NLSF_QUANT_MAX_AMPLITUDE, 0, 2 * NLSF_QUANT_MAX_AMPLITUDE ) ] ) << 2;
+            if( silk_abs( NLSFIndices[ i + 1 ] ) >= NLSF_QUANT_MAX_AMPLITUDE ) {
+                Rate_Q7 += 128 << ( silk_abs( NLSFIndices[ i + 1 ] ) - NLSF_QUANT_MAX_AMPLITUDE );
+            }
+        }
+        RD_dec_Q22 = Dist_Q22_dec + Rate_Q7 * NLSF_mu_Q20 >> 5;
+        DEBUG_STORE_DATA( dec_dist_q22.dat, &Dist_Q22_dec, sizeof( opus_int32 ) );
+        DEBUG_STORE_DATA( dec_rate_q7.dat, &Rate_Q7, sizeof( opus_int32 ) );
+        DEBUG_STORE_DATA( dec_rd_q22.dat, &RD_dec_Q22, sizeof( opus_int32 ) );
+    }
+    DEBUG_STORE_DATA( NLSF_ind.dat, NLSFIndices, (psNLSF_CB->order+1) * sizeof( opus_int8 ) );
+#endif
+
+    return RD_Q25[ 0 ];
+}
--- /dev/null
+++ b/silk/NLSF_stabilize.c
@@ -1,0 +1,142 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* NLSF stabilizer:                                         */
+/*                                                          */
+/* - Moves NLSFs futher apart if they are too close         */
+/* - Moves NLSFs away from borders if they are too close    */
+/* - High effort to achieve a modification with minimum     */
+/*     Euclidean distance to input vector                   */
+/* - Output are sorted NLSF coefficients                    */
+/*                                                          */
+
+#include "SigProc_FIX.h"
+
+/* Constant Definitions */
+#define MAX_LOOPS        20
+
+/* NLSF stabilizer, for a single input data vector */
+void silk_NLSF_stabilize(
+          opus_int16  *NLSF_Q15,            /* I/O:  Unstable/stabilized normalized LSF vector in Q15 [L]                    */
+    const opus_int16  *NDeltaMin_Q15,       /* I:    Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */
+    const opus_int     L                    /* I:    Number of NLSF parameters in the input vector                           */
+)
+{
+    opus_int   i, I=0, k, loops;
+    opus_int16 center_freq_Q15;
+    opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15;
+
+    /* This is necessary to ensure an output within range of a opus_int16 */
+    silk_assert( NDeltaMin_Q15[L] >= 1 );
+
+    for( loops = 0; loops < MAX_LOOPS; loops++ ) {
+        /**************************/
+        /* Find smallest distance */
+        /**************************/
+        /* First element */
+        min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0];
+        I = 0;
+        /* Middle elements */
+        for( i = 1; i <= L-1; i++ ) {
+            diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
+            if( diff_Q15 < min_diff_Q15 ) {
+                min_diff_Q15 = diff_Q15;
+                I = i;
+            }
+        }
+        /* Last element */
+        diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] );
+        if( diff_Q15 < min_diff_Q15 ) {
+            min_diff_Q15 = diff_Q15;
+            I = L;
+        }
+
+        /***************************************************/
+        /* Now check if the smallest distance non-negative */
+        /***************************************************/
+        if (min_diff_Q15 >= 0) {
+            return;
+        }
+
+        if( I == 0 ) {
+            /* Move away from lower limit */
+            NLSF_Q15[0] = NDeltaMin_Q15[0];
+
+        } else if( I == L) {
+            /* Move away from higher limit */
+            NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L];
+
+        } else {
+            /* Find the lower extreme for the location of the current center frequency */
+            min_center_Q15 = 0;
+            for( k = 0; k < I; k++ ) {
+                min_center_Q15 += NDeltaMin_Q15[k];
+            }
+            min_center_Q15 += silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+
+            /* Find the upper extreme for the location of the current center frequency */
+            max_center_Q15 = 1 << 15;
+            for( k = L; k > I; k-- ) {
+                max_center_Q15 -= NDeltaMin_Q15[k];
+            }
+            max_center_Q15 -= silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+
+            /* Move apart, sorted by value, keeping the same center frequency */
+            center_freq_Q15 = (opus_int16)silk_LIMIT_32( silk_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ),
+                min_center_Q15, max_center_Q15 );
+            NLSF_Q15[I-1] = center_freq_Q15 - silk_RSHIFT( NDeltaMin_Q15[I], 1 );
+            NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I];
+        }
+    }
+
+    /* Safe and simple fall back method, which is less ideal than the above */
+    if( loops == MAX_LOOPS )
+    {
+        /* Insertion sort (fast for already almost sorted arrays):   */
+        /* Best case:  O(n)   for an already sorted array            */
+        /* Worst case: O(n^2) for an inversely sorted array          */
+        silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L );
+
+        /* First NLSF should be no less than NDeltaMin[0] */
+        NLSF_Q15[0] = silk_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] );
+
+        /* Keep delta_min distance between the NLSFs */
+        for( i = 1; i < L; i++ )
+            NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
+
+        /* Last NLSF should be no higher than 1 - NDeltaMin[L] */
+        NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] );
+
+        /* Keep NDeltaMin distance between the NLSFs */
+        for( i = L-2; i >= 0; i-- )
+            NLSF_Q15[i] = silk_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] );
+    }
+}
--- /dev/null
+++ b/silk/NLSF_unpack.c
@@ -1,0 +1,55 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Unpack predictor values and indices for entropy coding tables */
+void silk_NLSF_unpack(
+          opus_int16             ec_ix[],                /* O    Indices to entropy tales [ LPC_ORDER ]  */
+          opus_uint8             pred_Q8[],              /* O    LSF predictor [ LPC_ORDER ]             */
+    const silk_NLSF_CB_struct   *psNLSF_CB,             /* I    Codebook object                         */
+    const opus_int               CB1_index               /* I    Index of vector in first LSF codebook   */
+)
+{
+    opus_int   i;
+    opus_uint8 entry;
+    const opus_uint8 *ec_sel_ptr;
+
+    ec_sel_ptr = &psNLSF_CB->ec_sel[ CB1_index * psNLSF_CB->order / 2 ];
+    for( i = 0; i < psNLSF_CB->order; i += 2 ) {
+        entry = *ec_sel_ptr++;
+        ec_ix  [ i     ] = silk_SMULBB( silk_RSHIFT( entry, 1 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
+        pred_Q8[ i     ] = psNLSF_CB->pred_Q8[ i + ( entry & 1 ) * ( psNLSF_CB->order - 1 ) ];
+        ec_ix  [ i + 1 ] = silk_SMULBB( silk_RSHIFT( entry, 5 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
+        pred_Q8[ i + 1 ] = psNLSF_CB->pred_Q8[ i + ( silk_RSHIFT( entry, 4 ) & 1 ) * ( psNLSF_CB->order - 1 ) + 1 ];
+    }
+}
+
--- /dev/null
+++ b/silk/NSQ.c
@@ -1,0 +1,431 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+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                     */
+    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_int             subfr,              /* I    subframe number                 */
+    const opus_int       LTP_scale_Q14,      /* I                                    */
+    const opus_int32     Gains_Q16[ MAX_NB_SUBFR ], /* I                             */
+    const opus_int       pitchL[ MAX_NB_SUBFR ]  /* I                                */
+);
+
+static inline void silk_noise_shape_quantizer(
+    silk_nsq_state      *NSQ,               /* I/O  NSQ state                       */
+    opus_int             signalType,         /* I    Signal type                     */
+    const opus_int32     x_sc_Q10[],         /* I                                    */
+    opus_int8            pulses[],           /* O                                    */
+    opus_int16           xq[],               /* O                                    */
+    opus_int32           sLTP_Q16[],         /* 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          */
+    opus_int             lag,                /* I    Pitch lag                       */
+    opus_int32           HarmShapeFIRPacked_Q14, /* I                                */
+    opus_int             Tilt_Q14,           /* I    Spectral tilt                   */
+    opus_int32           LF_shp_Q14,         /* I                                    */
+    opus_int32           Gain_Q16,           /* I                                    */
+    opus_int             Lambda_Q10,         /* I                                    */
+    opus_int             offset_Q10,         /* I                                    */
+    opus_int             length,             /* I    Input length                    */
+    opus_int             shapingLPCOrder,    /* I    Noise shaping AR filter order   */
+    opus_int             predictLPCOrder     /* I    Prediction filter order         */
+);
+
+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            */
+    opus_int8                        pulses[],                                   /* O    quantized qulse signal              */
+    const opus_int16                 PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefficients  */
+    const opus_int16                 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefficients   */
+    const opus_int16                 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I                                     */
+    const opus_int                   HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I                                        */
+    const opus_int                   Tilt_Q14[ MAX_NB_SUBFR ],                   /* I    Spectral tilt                       */
+    const opus_int32                 LF_shp_Q14[ MAX_NB_SUBFR ],                 /* I                                        */
+    const opus_int32                 Gains_Q16[ MAX_NB_SUBFR ],                  /* I                                        */
+    const opus_int                   pitchL[ MAX_NB_SUBFR ],                     /* I                                        */
+    const opus_int                   Lambda_Q10,                                 /* I                                        */
+    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 ];
+
+    NSQ->rand_seed = psIndices->Seed;
+
+    /* Set unvoiced lag to the previous one, overwrite later for voiced */
+    lag = NSQ->lagPrev;
+
+    silk_assert( NSQ->prev_inv_gain_Q16 != 0 );
+
+    offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
+
+    if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
+        LSF_interpolation_flag = 0;
+    } else {
+        LSF_interpolation_flag = 1;
+    }
+
+    /* Setup 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 ];
+    for( k = 0; k < psEncC->nb_subfr; k++ ) {
+        A_Q12      = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
+        B_Q14      = &LTPCoef_Q14[ k * LTP_ORDER ];
+        AR_shp_Q13 = &AR2_Q13[     k * MAX_SHAPE_LPC_ORDER ];
+
+        /* 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 );
+
+        NSQ->rewhite_flag = 0;
+        if( psIndices->signalType == TYPE_VOICED ) {
+            /* Voiced */
+            lag = pitchL[ k ];
+
+            /* Re-whitening */
+            if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
+                /* Rewhiten with new A coefs */
+                start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
+                silk_assert( start_idx > 0 );
+
+                silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
+                    A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder );
+
+                NSQ->rewhite_flag = 1;
+                NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
+            }
+        }
+
+        silk_nsq_scale_states( psEncC, NSQ, x, x_sc_Q10, sLTP, sLTP_Q16, k, LTP_scale_Q14, Gains_Q16, pitchL );
+
+        silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_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, psEncC->shapingLPCOrder, psEncC->predictLPCOrder );
+
+        x      += psEncC->subfr_length;
+        pulses += psEncC->subfr_length;
+        pxq    += psEncC->subfr_length;
+    }
+
+    /* Update lagPrev for next frame */
+    NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
+
+    /* Save quantized speech and noise shaping signals */
+    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 ) );
+
+#ifdef SAVE_ALL_INTERNAL_DATA
+    DEBUG_STORE_DATA( xq.dat,       &pxq[ -psEncC->frame_length ],       psEncC->frame_length * sizeof( opus_int16 ) );
+    DEBUG_STORE_DATA( q.dat,        &pulses[ -psEncC->frame_length ],    psEncC->frame_length * sizeof( opus_int8 ) );
+    DEBUG_STORE_DATA( sLTP_Q16.dat, &sLTP_Q16[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int32 ) );
+#endif
+}
+
+/***********************************/
+/* silk_noise_shape_quantizer  */
+/***********************************/
+static inline void silk_noise_shape_quantizer(
+    silk_nsq_state  *NSQ,               /* I/O  NSQ state                       */
+    opus_int             signalType,         /* I    Signal type                     */
+    const opus_int32     x_sc_Q10[],         /* I                                    */
+    opus_int8            pulses[],           /* O                                    */
+    opus_int16           xq[],               /* O                                    */
+    opus_int32           sLTP_Q16[],         /* 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          */
+    opus_int             lag,                /* I    Pitch lag                       */
+    opus_int32           HarmShapeFIRPacked_Q14, /* I                                */
+    opus_int             Tilt_Q14,           /* I    Spectral tilt                   */
+    opus_int32           LF_shp_Q14,         /* I                                    */
+    opus_int32           Gain_Q16,           /* I                                    */
+    opus_int             Lambda_Q10,         /* I                                    */
+    opus_int             offset_Q10,         /* I                                    */
+    opus_int             length,             /* I    Input length                    */
+    opus_int             shapingLPCOrder,    /* I    Noise shaping AR filter order   */
+    opus_int             predictLPCOrder     /* I    Prediction filter order         */
+)
+{
+    opus_int     i, j;
+    opus_int32   LTP_pred_Q14, 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 ];
+
+    /* Setup short term AR state */
+    psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
+
+    for( i = 0; i < length; i++ ) {
+        /* Generate dither */
+        NSQ->rand_seed = silk_RAND( NSQ->rand_seed );
+
+        /* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */
+        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 */
+        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 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
+        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
+        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 ] );
+        }
+
+        /* 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 ] );
+            pred_lag_ptr++;
+        } else {
+            LTP_pred_Q14 = 0;
+        }
+
+        /* Noise shape feedback */
+        silk_assert( ( shapingLPCOrder & 1 ) == 0 );   /* check that order is even */
+        tmp2 = psLPC_Q14[ 0 ];
+        tmp1 = NSQ->sAR2_Q14[ 0 ];
+        NSQ->sAR2_Q14[ 0 ] = tmp2;
+        n_AR_Q10 = silk_SMULWB( tmp2, AR_shp_Q13[ 0 ] );
+        for( j = 2; j < shapingLPCOrder; j += 2 ) {
+            tmp2 = NSQ->sAR2_Q14[ j - 1 ];
+            NSQ->sAR2_Q14[ j - 1 ] = tmp1;
+            n_AR_Q10 = silk_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] );
+            tmp1 = NSQ->sAR2_Q14[ j + 0 ];
+            NSQ->sAR2_Q14[ j + 0 ] = tmp2;
+            n_AR_Q10 = silk_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] );
+        }
+        NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
+        n_AR_Q10 = silk_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
+
+        n_AR_Q10 = silk_RSHIFT( n_AR_Q10, 1 );   /* Q11 -> Q10 */
+        n_AR_Q10 = silk_SMLAWB( n_AR_Q10, NSQ->sLF_AR_shp_Q12, Tilt_Q14 );
+
+        n_LF_Q10 = silk_LSHIFT( silk_SMULWB( NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ), 2 );
+        n_LF_Q10 = silk_SMLAWT( n_LF_Q10, NSQ->sLF_AR_shp_Q12, LF_shp_Q14 );
+
+        silk_assert( lag > 0 || signalType != TYPE_VOICED );
+
+        /* 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_LSHIFT( n_LTP_Q14, 6 );
+            shp_lag_ptr++;
+
+            tmp1 = silk_SUB32( LTP_pred_Q14, 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 */
+        } else {
+            tmp1 = silk_SUB32( LPC_pred_Q10, n_AR_Q10 );                         /* subtract Q10 stuff */
+        }
+
+        /* Input minus prediction plus noise feedback  */
+        /*r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP;*/
+        tmp1  = silk_SUB32( tmp1, n_LF_Q10 );                                    /* subtract Q10 stuff */
+        r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 );
+
+        /* Flip sign depending on dither */
+        r_Q10 = r_Q10 ^ dither;
+        r_Q10 = silk_LIMIT_32( r_Q10, -31 << 10, 30 << 10 );
+
+        /* Find two quantization level candidates and measure their rate-distortion */
+        q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
+        q1_Q10 = silk_RSHIFT( q1_Q10, 10 );
+        if( q1_Q10 > 0 ) {
+            q1_Q10  = silk_SUB32( silk_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 );
+            q1_Q10  = silk_ADD32( q1_Q10, offset_Q10 );
+            q2_Q10  = silk_ADD32( q1_Q10, 1024 );
+            rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
+            rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
+        } else if( q1_Q10 == 0 ) {
+            q1_Q10  = offset_Q10;
+            q2_Q10  = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
+            rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
+            rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
+        } else if( q1_Q10 == -1 ) {
+            q2_Q10  = offset_Q10;
+            q1_Q10  = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
+            rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
+            rd2_Q10 = silk_SMULBB(  q2_Q10, Lambda_Q10 );
+        } else {            /* Q1_Q10 < -1 */
+            q1_Q10  = silk_ADD32( silk_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 );
+            q1_Q10  = silk_ADD32( q1_Q10, offset_Q10 );
+            q2_Q10  = silk_ADD32( q1_Q10, 1024 );
+            rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
+            rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
+        }
+        rr_Q10  = silk_SUB32( r_Q10, q1_Q10 );
+        rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 );
+        rr_Q10  = silk_SUB32( r_Q10, q2_Q10 );
+        rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 );
+
+        if( rd2_Q10 < rd1_Q10 ) {
+            q1_Q10 = q2_Q10;
+        }
+
+        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 ) );
+        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 ) );
+
+        /* Update states */
+        psLPC_Q14++;
+        *psLPC_Q14 = silk_LSHIFT( xq_Q10, 4 );
+        sLF_AR_shp_Q10 = silk_SUB32( xq_Q10, n_AR_Q10 );
+        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 );
+        NSQ->sLTP_shp_buf_idx++;
+        NSQ->sLTP_buf_idx++;
+
+        /* Make dither dependent on quantized signal */
+        NSQ->rand_seed = silk_ADD32_ovflw(NSQ->rand_seed, pulses[ i ]);
+    }
+
+    /* Update LPC synth buffer */
+    silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
+}
+
+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                     */
+    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_int             subfr,              /* I    subframe number                 */
+    const opus_int       LTP_scale_Q14,      /* I                                    */
+    const opus_int32     Gains_Q16[ MAX_NB_SUBFR ], /* I                             */
+    const opus_int       pitchL[ MAX_NB_SUBFR ]  /* I                                */
+)
+{
+    opus_int   i, lag;
+    opus_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32;
+
+    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 );
+        if( subfr == 0 ) {
+            /* Do LTP downscaling */
+            inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, 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 ] );
+        }
+    }
+
+    /* Adjust for changing gain */
+    if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) {
+        gain_adj_Q16 = silk_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 16 );
+
+        /* Scale long-term shaping state */
+        for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
+            NSQ->sLTP_shp_Q10[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] );
+        }
+
+        /* Scale long-term prediction state */
+        if( 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 ] );
+            }
+        }
+
+        NSQ->sLF_AR_shp_Q12 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q12 );
+
+        /* Scale short-term prediction and shaping states */
+        for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+            NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] );
+        }
+        for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
+            NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
+        }
+    }
+
+    /* 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 );
+    }
+
+    /* save inv_gain */
+    silk_assert( inv_gain_Q16 != 0 );
+    NSQ->prev_inv_gain_Q16 = inv_gain_Q16;
+}
--- /dev/null
+++ b/silk/NSQ_del_dec.c
@@ -1,0 +1,684 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+typedef struct {
+    opus_int32 sLPC_Q14[ MAX_FRAME_LENGTH / MAX_NB_SUBFR + NSQ_LPC_BUF_LENGTH ];
+    opus_int32 RandState[ DECISION_DELAY ];
+    opus_int32 Q_Q10[     DECISION_DELAY ];
+    opus_int32 Xq_Q10[    DECISION_DELAY ];
+    opus_int32 Pred_Q16[  DECISION_DELAY ];
+    opus_int32 Shape_Q10[ DECISION_DELAY ];
+    opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
+    opus_int32 LF_AR_Q12;
+    opus_int32 Seed;
+    opus_int32 SeedInit;
+    opus_int32 RD_Q10;
+} NSQ_del_dec_struct;
+
+typedef struct {
+    opus_int32 Q_Q10;
+    opus_int32 RD_Q10;
+    opus_int32 xq_Q14;
+    opus_int32 LF_AR_Q12;
+    opus_int32 sLTP_shp_Q10;
+    opus_int32 LPC_exc_Q16;
+} NSQ_sample_struct;
+
+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                         */
+    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_int             subfr,                      /* I    Subframe number                     */
+    opus_int             nStatesDelayedDecision,     /* I    Number of del dec states            */
+    opus_int             smpl_buf_idx,               /* I    Index to newest samples in buffers  */
+    const opus_int       LTP_scale_Q14,              /* I    LTP state scaling                   */
+    const opus_int32     Gains_Q16[ MAX_NB_SUBFR ],  /* I                                        */
+    const opus_int       pitchL[ MAX_NB_SUBFR ]      /* I    Pitch lag                           */
+);
+
+/******************************************/
+/* Noise shape quantizer for one subframe */
+/******************************************/
+static inline void silk_noise_shape_quantizer_del_dec(
+    silk_nsq_state      *NSQ,                   /* I/O  NSQ state                           */
+    NSQ_del_dec_struct  psDelDec[],             /* I/O  Delayed decision states             */
+    opus_int             signalType,             /* I    Signal type                         */
+    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           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          */
+    const opus_int16     AR_shp_Q13[],           /* I    Noise shaping coefs                 */
+    opus_int             lag,                    /* I    Pitch lag                           */
+    opus_int32           HarmShapeFIRPacked_Q14, /* I                                        */
+    opus_int             Tilt_Q14,               /* I    Spectral tilt                       */
+    opus_int32           LF_shp_Q14,             /* I                                        */
+    opus_int32           Gain_Q16,               /* I                                        */
+    opus_int             Lambda_Q10,             /* I                                        */
+    opus_int             offset_Q10,             /* I                                        */
+    opus_int             length,                 /* I    Input length                        */
+    opus_int             subfr,                  /* I    Subframe number                     */
+    opus_int             shapingLPCOrder,        /* I    Shaping LPC filter order            */
+    opus_int             predictLPCOrder,        /* I    Prediction filter order             */
+    opus_int             warping_Q16,            /* I                                        */
+    opus_int             nStatesDelayedDecision, /* I    Number of states in decision tree   */
+    opus_int             *smpl_buf_idx,          /* I    Index to newest samples in buffers  */
+    opus_int             decisionDelay           /* I                                        */
+);
+
+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            */
+    opus_int8                        pulses[],                                   /* O    Quantized pulse signal              */
+    const opus_int16                 PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Prediction coefs                    */
+    const opus_int16                 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    LT prediction coefs                 */
+    const opus_int16                 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I                                     */
+    const opus_int                   HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I                                        */
+    const opus_int                   Tilt_Q14[ MAX_NB_SUBFR ],                   /* I    Spectral tilt                       */
+    const opus_int32                 LF_shp_Q14[ MAX_NB_SUBFR ],                 /* I                                        */
+    const opus_int32                 Gains_Q16[ MAX_NB_SUBFR ],                  /* I                                        */
+    const opus_int                   pitchL[ MAX_NB_SUBFR ],                     /* I                                        */
+    const opus_int                   Lambda_Q10,                                 /* I                                        */
+    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;
+
+    /* Set unvoiced lag to the previous one, overwrite later for voiced */
+    lag = NSQ->lagPrev;
+
+    silk_assert( NSQ->prev_inv_gain_Q16 != 0 );
+
+    /* Initialize delayed decision states */
+    silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) );
+    for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
+        psDD                 = &psDelDec[ k ];
+        psDD->Seed           = ( k + psIndices->Seed ) & 3;
+        psDD->SeedInit       = psDD->Seed;
+        psDD->RD_Q10         = 0;
+        psDD->LF_AR_Q12      = NSQ->sLF_AR_shp_Q12;
+        psDD->Shape_Q10[ 0 ] = NSQ->sLTP_shp_Q10[ psEncC->ltp_mem_length - 1 ];
+        silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
+        silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
+    }
+
+    offset_Q10   = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
+    smpl_buf_idx = 0; /* index of oldest samples */
+
+    decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length );
+
+    /* For voiced frames limit the decision delay to lower than the pitch lag */
+    if( psIndices->signalType == TYPE_VOICED ) {
+        for( k = 0; k < psEncC->nb_subfr; k++ ) {
+            decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 );
+        }
+    } else {
+        if( lag > 0 ) {
+            decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 );
+        }
+    }
+
+    if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
+        LSF_interpolation_flag = 0;
+    } else {
+        LSF_interpolation_flag = 1;
+    }
+
+    /* Setup 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;
+    subfr = 0;
+    for( k = 0; k < psEncC->nb_subfr; k++ ) {
+        A_Q12      = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
+        B_Q14      = &LTPCoef_Q14[ k * LTP_ORDER           ];
+        AR_shp_Q13 = &AR2_Q13[     k * MAX_SHAPE_LPC_ORDER ];
+
+        /* 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 );
+
+        NSQ->rewhite_flag = 0;
+        if( psIndices->signalType == TYPE_VOICED ) {
+            /* Voiced */
+            lag = pitchL[ k ];
+
+            /* Re-whitening */
+            if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
+                if( k == 2 ) {
+                    /* RESET DELAYED DECISIONS */
+                    /* Find winner */
+                    RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
+                    Winner_ind = 0;
+                    for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) {
+                        if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) {
+                            RDmin_Q10 = psDelDec[ i ].RD_Q10;
+                            Winner_ind = i;
+                        }
+                    }
+                    for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) {
+                        if( i != Winner_ind ) {
+                            psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 );
+                            silk_assert( psDelDec[ i ].RD_Q10 >= 0 );
+                        }
+                    }
+
+                    /* Copy final part of signals from winner state to output and long-term filter states */
+                    psDD = &psDelDec[ Winner_ind ];
+                    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(
+                            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 ];
+                    }
+
+                    subfr = 0;
+                }
+
+                /* Rewhiten with new A coefs */
+                start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
+                silk_assert( start_idx > 0 );
+
+                silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
+                    A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder );
+
+                NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
+                NSQ->rewhite_flag = 1;
+            }
+        }
+
+        silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x, x_sc_Q10, sLTP, sLTP_Q16, k,
+            psEncC->nStatesDelayedDecision, smpl_buf_idx, LTP_scale_Q14, Gains_Q16, pitchL );
+
+        silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q16,
+            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;
+        pulses += psEncC->subfr_length;
+        pxq    += psEncC->subfr_length;
+    }
+
+    /* Find winner */
+    RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
+    Winner_ind = 0;
+    for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) {
+        if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) {
+            RDmin_Q10 = psDelDec[ k ].RD_Q10;
+            Winner_ind = k;
+        }
+    }
+
+    /* Copy final part of signals from winner state to output and long-term filter states */
+    psDD = &psDelDec[ Winner_ind ];
+    psIndices->Seed = psDD->SeedInit;
+    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(
+            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 ];
+        sLTP_Q16[          NSQ->sLTP_buf_idx     - decisionDelay + i ] = psDD->Pred_Q16[  last_smple_idx ];
+    }
+    silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
+    silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) );
+
+    /* Update states */
+    NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12;
+    NSQ->lagPrev        = pitchL[ psEncC->nb_subfr - 1 ];
+
+    /* Save quantized speech and noise shaping signals */
+    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 ) );
+
+#ifdef SAVE_ALL_INTERNAL_DATA
+    DEBUG_STORE_DATA( xq.dat,       &pxq[ -psEncC->frame_length ],       psEncC->frame_length * sizeof( opus_int16 ) );
+    DEBUG_STORE_DATA( q.dat,        &pulses[ -psEncC->frame_length ],    psEncC->frame_length * sizeof( opus_int8 ) );
+    DEBUG_STORE_DATA( sLTP_Q16.dat, &sLTP_Q16[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int32 ) );
+#endif
+}
+
+/******************************************/
+/* Noise shape quantizer for one subframe */
+/******************************************/
+static inline void silk_noise_shape_quantizer_del_dec(
+    silk_nsq_state  *NSQ,                   /* I/O  NSQ state                           */
+    NSQ_del_dec_struct  psDelDec[],             /* I/O  Delayed decision states             */
+    opus_int             signalType,             /* I    Signal type                         */
+    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           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          */
+    const opus_int16     AR_shp_Q13[],           /* I    Noise shaping coefs                 */
+    opus_int             lag,                    /* I    Pitch lag                           */
+    opus_int32           HarmShapeFIRPacked_Q14, /* I                                        */
+    opus_int             Tilt_Q14,               /* I    Spectral tilt                       */
+    opus_int32           LF_shp_Q14,             /* I                                        */
+    opus_int32           Gain_Q16,               /* I                                        */
+    opus_int             Lambda_Q10,             /* I                                        */
+    opus_int             offset_Q10,             /* I                                        */
+    opus_int             length,                 /* I    Input length                        */
+    opus_int             subfr,                  /* I    Subframe number                     */
+    opus_int             shapingLPCOrder,        /* I    Shaping LPC filter order            */
+    opus_int             predictLPCOrder,        /* I    Prediction filter order             */
+    opus_int             warping_Q16,            /* I                                        */
+    opus_int             nStatesDelayedDecision, /* I    Number of states in decision tree   */
+    opus_int             *smpl_buf_idx,          /* I    Index to newest samples in buffers  */
+    opus_int             decisionDelay           /* I                                        */
+)
+{
+    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   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;
+    opus_int32   *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
+    NSQ_sample_struct  psSampleState[ MAX_DEL_DEC_STATES ][ 2 ];
+    NSQ_del_dec_struct *psDD;
+    NSQ_sample_struct  *psSS;
+
+    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 ];
+
+    for( i = 0; i < length; i++ ) {
+        /* Perform common calculations used in all states */
+
+        /* 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 ] );
+            pred_lag_ptr++;
+        } else {
+            LTP_pred_Q14 = 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_LSHIFT( n_LTP_Q14, 6 );
+            shp_lag_ptr++;
+
+            LTP_Q10 = silk_RSHIFT( silk_SUB32( LTP_pred_Q14, n_LTP_Q14 ), 4 );
+        } else {
+            LTP_Q10 = 0;
+        }
+
+        for( k = 0; k < nStatesDelayedDecision; k++ ) {
+            /* Delayed decision state */
+            psDD = &psDelDec[ k ];
+
+            /* Sample state */
+            psSS = psSampleState[ k ];
+
+            /* Generate dither */
+            psDD->Seed = silk_RAND( psDD->Seed );
+
+            /* dither = rand_seed < 0 ? 0xFFFFFFFF : 0; */
+            dither = silk_RSHIFT( psDD->Seed, 31 );
+
+            /* 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 */
+            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 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
+            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 ] );
+            }
+
+            /* Noise shape feedback */
+            silk_assert( ( shapingLPCOrder & 1 ) == 0 );   /* check that order is even */
+            /* Output of lowpass section */
+            tmp2 = silk_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
+            /* Output of allpass section */
+            tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
+            psDD->sAR2_Q14[ 0 ] = tmp2;
+            n_AR_Q10 = silk_SMULWB( tmp2, AR_shp_Q13[ 0 ] );
+            /* Loop over allpass sections */
+            for( j = 2; j < shapingLPCOrder; j += 2 ) {
+                /* Output of allpass section */
+                tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 );
+                psDD->sAR2_Q14[ j - 1 ] = tmp1;
+                n_AR_Q10 = silk_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] );
+                /* Output of allpass section */
+                tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 );
+                psDD->sAR2_Q14[ j + 0 ] = tmp2;
+                n_AR_Q10 = silk_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] );
+            }
+            psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
+            n_AR_Q10 = silk_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
+
+            n_AR_Q10 = silk_RSHIFT( n_AR_Q10, 1 );           /* Q11 -> Q10 */
+            n_AR_Q10 = silk_SMLAWB( n_AR_Q10, psDD->LF_AR_Q12, Tilt_Q14 );
+
+            n_LF_Q10 = silk_LSHIFT( silk_SMULWB( psDD->Shape_Q10[ *smpl_buf_idx ], LF_shp_Q14 ), 2 );
+            n_LF_Q10 = silk_SMLAWT( n_LF_Q10, psDD->LF_AR_Q12, LF_shp_Q14 );
+
+            /* Input minus prediction plus noise feedback                       */
+            /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP  */
+            tmp1  = silk_ADD32( LTP_Q10, LPC_pred_Q10 );                         /* add Q10 stuff */
+            tmp1  = silk_SUB32( tmp1, n_AR_Q10 );                                /* subtract Q10 stuff */
+            tmp1  = silk_SUB32( tmp1, n_LF_Q10 );                                /* subtract Q10 stuff */
+            r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 );                              /* residual error Q10 */
+
+            /* Flip sign depending on dither */
+            r_Q10 = r_Q10 ^ dither;
+            r_Q10 = silk_LIMIT_32( r_Q10, -31 << 10, 30 << 10 );
+
+            /* Find two quantization level candidates and measure their rate-distortion */
+            q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
+            q1_Q10 = silk_RSHIFT( q1_Q10, 10 );
+            if( q1_Q10 > 0 ) {
+                q1_Q10  = silk_SUB32( silk_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 );
+                q1_Q10  = silk_ADD32( q1_Q10, offset_Q10 );
+                q2_Q10  = silk_ADD32( q1_Q10, 1024 );
+                rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
+                rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
+            } else if( q1_Q10 == 0 ) {
+                q1_Q10  = offset_Q10;
+                q2_Q10  = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
+                rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
+                rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
+            } else if( q1_Q10 == -1 ) {
+                q2_Q10  = offset_Q10;
+                q1_Q10  = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
+                rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
+                rd2_Q10 = silk_SMULBB(  q2_Q10, Lambda_Q10 );
+            } else {            /* Q1_Q10 < -1 */
+                q1_Q10  = silk_ADD32( silk_LSHIFT( q1_Q10, 10 ), QUANT_LEVEL_ADJUST_Q10 );
+                q1_Q10  = silk_ADD32( q1_Q10, offset_Q10 );
+                q2_Q10  = silk_ADD32( q1_Q10, 1024 );
+                rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
+                rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
+            }
+            rr_Q10  = silk_SUB32( r_Q10, q1_Q10 );
+            rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 );
+            rr_Q10  = silk_SUB32( r_Q10, q2_Q10 );
+            rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 );
+
+            if( rd1_Q10 < rd2_Q10 ) {
+                psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
+                psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
+                psSS[ 0 ].Q_Q10  = q1_Q10;
+                psSS[ 1 ].Q_Q10  = q2_Q10;
+            } else {
+                psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
+                psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
+                psSS[ 0 ].Q_Q10  = q2_Q10;
+                psSS[ 1 ].Q_Q10  = q1_Q10;
+            }
+
+            /* Update states for best quantization */
+
+            /* Quantized excitation */
+            exc_Q10 = psSS[ 0 ].Q_Q10 ^ dither;
+
+            /* Add predictions */
+            LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q14, 4 );
+            xq_Q10      = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
+
+            /* Update states */
+            sLF_AR_shp_Q10         = silk_SUB32(  xq_Q10, n_AR_Q10 );
+            psSS[ 0 ].sLTP_shp_Q10 = silk_SUB32(  sLF_AR_shp_Q10, n_LF_Q10 );
+            psSS[ 0 ].LF_AR_Q12    = silk_LSHIFT( sLF_AR_shp_Q10, 2 );
+            psSS[ 0 ].xq_Q14       = silk_LSHIFT( xq_Q10,         4 );
+            psSS[ 0 ].LPC_exc_Q16  = silk_LSHIFT( LPC_exc_Q10,    6 );
+
+            /* Update states for second best quantization */
+
+            /* Quantized excitation */
+            exc_Q10 = psSS[ 1 ].Q_Q10 ^ dither;
+
+            /* Add predictions */
+            LPC_exc_Q10 = exc_Q10 + silk_RSHIFT_ROUND( LTP_pred_Q14, 4 );
+            xq_Q10      = silk_ADD32( LPC_exc_Q10, LPC_pred_Q10 );
+
+            /* Update states */
+            sLF_AR_shp_Q10         = silk_SUB32(  xq_Q10, n_AR_Q10 );
+            psSS[ 1 ].sLTP_shp_Q10 = silk_SUB32(  sLF_AR_shp_Q10, n_LF_Q10 );
+            psSS[ 1 ].LF_AR_Q12    = silk_LSHIFT( sLF_AR_shp_Q10, 2 );
+            psSS[ 1 ].xq_Q14       = silk_LSHIFT( xq_Q10,         4 );
+            psSS[ 1 ].LPC_exc_Q16  = silk_LSHIFT( LPC_exc_Q10,    6 );
+        }
+
+        *smpl_buf_idx  = ( *smpl_buf_idx - 1 ) & DECISION_DELAY_MASK;                   /* Index to newest samples              */
+        last_smple_idx = ( *smpl_buf_idx + decisionDelay ) & DECISION_DELAY_MASK;       /* Index to decisionDelay old samples   */
+
+        /* Find winner */
+        RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
+        Winner_ind = 0;
+        for( k = 1; k < nStatesDelayedDecision; k++ ) {
+            if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) {
+                RDmin_Q10  = psSampleState[ k ][ 0 ].RD_Q10;
+                Winner_ind = k;
+            }
+        }
+
+        /* Increase RD values of expired states */
+        Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ];
+        for( k = 0; k < nStatesDelayedDecision; k++ ) {
+            if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) {
+                psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, ( silk_int32_MAX >> 4 ) );
+                psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, ( silk_int32_MAX >> 4 ) );
+                silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 );
+            }
+        }
+
+        /* Find worst in first set and best in second set */
+        RDmax_Q10  = psSampleState[ 0 ][ 0 ].RD_Q10;
+        RDmin_Q10  = psSampleState[ 0 ][ 1 ].RD_Q10;
+        RDmax_ind = 0;
+        RDmin_ind = 0;
+        for( k = 1; k < nStatesDelayedDecision; k++ ) {
+            /* find worst in first set */
+            if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) {
+                RDmax_Q10  = psSampleState[ k ][ 0 ].RD_Q10;
+                RDmax_ind = k;
+            }
+            /* find best in second set */
+            if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) {
+                RDmin_Q10  = psSampleState[ k ][ 1 ].RD_Q10;
+                RDmin_ind = k;
+            }
+        }
+
+        /* Replace a state if best from second set outperforms worst in first set */
+        if( RDmin_Q10 < RDmax_Q10 ) {
+            silk_memcpy( ((opus_int32 *)&psDelDec[ RDmax_ind ]) + i,
+                        ((opus_int32 *)&psDelDec[ RDmin_ind ]) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) );
+            silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) );
+        }
+
+        /* 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(
+                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 ];
+        }
+        NSQ->sLTP_shp_buf_idx++;
+        NSQ->sLTP_buf_idx++;
+
+        /* Update states */
+        for( k = 0; k < nStatesDelayedDecision; k++ ) {
+            psDD                                     = &psDelDec[ k ];
+            psSS                                     = &psSampleState[ k ][ 0 ];
+            psDD->LF_AR_Q12                          = psSS->LF_AR_Q12;
+            psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
+            psDD->Xq_Q10[    *smpl_buf_idx ]         = silk_RSHIFT( psSS->xq_Q14, 4 );
+            psDD->Q_Q10[     *smpl_buf_idx ]         = psSS->Q_Q10;
+            psDD->Pred_Q16[  *smpl_buf_idx ]         = psSS->LPC_exc_Q16;
+            psDD->Shape_Q10[ *smpl_buf_idx ]         = psSS->sLTP_shp_Q10;
+            psDD->Seed                               = silk_ADD32( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) );
+            psDD->RandState[ *smpl_buf_idx ]         = psDD->Seed;
+            psDD->RD_Q10                             = psSS->RD_Q10;
+        }
+        delayedGain_Q16[     *smpl_buf_idx ]         = Gain_Q16;
+    }
+    /* Update LPC states */
+    for( k = 0; k < nStatesDelayedDecision; k++ ) {
+        psDD = &psDelDec[ k ];
+        silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
+    }
+}
+
+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                         */
+    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_int             subfr,                      /* I    Subframe number                     */
+    opus_int             nStatesDelayedDecision,     /* I    Number of del dec states            */
+    opus_int             smpl_buf_idx,               /* I    Index to newest samples in buffers  */
+    const opus_int       LTP_scale_Q14,              /* I    LTP state scaling                   */
+    const opus_int32     Gains_Q16[ MAX_NB_SUBFR ],  /* I                                        */
+    const opus_int       pitchL[ MAX_NB_SUBFR ]      /* I    Pitch lag                           */
+)
+{
+    opus_int            i, k, lag;
+    opus_int32          inv_gain_Q16, gain_adj_Q16, inv_gain_Q32;
+    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 );
+        if( subfr == 0 ) {
+            /* Do LTP downscaling */
+            inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, 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 ] );
+        }
+    }
+
+    /* Adjust for changing gain */
+    if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) {
+        gain_adj_Q16 = silk_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 16 );
+
+        /* Scale long-term shaping state */
+        for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
+            NSQ->sLTP_shp_Q10[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] );
+        }
+
+        /* Scale long-term prediction state */
+        if( 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 ] );
+            }
+        }
+
+        for( k = 0; k < nStatesDelayedDecision; k++ ) {
+            psDD = &psDelDec[ k ];
+
+            /* Scale scalar states */
+            psDD->LF_AR_Q12 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q12 );
+
+            /* Scale short-term prediction and shaping states */
+            for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+                psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] );
+            }
+            for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
+                psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] );
+            }
+            for( i = 0; i < DECISION_DELAY; i++ ) {
+                psDD->Pred_Q16[  i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q16[  i ] );
+                psDD->Shape_Q10[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q10[ i ] );
+            }
+        }
+    }
+
+    /* 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 );
+    }
+
+    /* save inv_gain */
+    silk_assert( inv_gain_Q16 != 0 );
+    NSQ->prev_inv_gain_Q16 = inv_gain_Q16;
+}
--- /dev/null
+++ b/silk/PLC.c
@@ -1,0 +1,395 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "PLC.h"
+
+#define NB_ATT 2
+static const opus_int16 HARM_ATT_Q15[NB_ATT]              = { 32440, 31130 }; /* 0.99, 0.95 */
+static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT]  = { 31130, 26214 }; /* 0.95, 0.8 */
+static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */
+
+void silk_PLC_Reset(
+    silk_decoder_state      *psDec              /* I/O Decoder state        */
+)
+{
+    psDec->sPLC.pitchL_Q8 = silk_RSHIFT( psDec->frame_length, 1 );
+}
+
+void silk_PLC(
+    silk_decoder_state          *psDec,             /* I Decoder state          */
+    silk_decoder_control        *psDecCtrl,         /* I Decoder control        */
+    opus_int16                   frame[],            /* O Concealed signal       */
+    opus_int                     length,             /* I length of residual     */
+    opus_int                     lost                /* I Loss flag              */
+)
+{
+    /* PLC control function */
+    if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) {
+        silk_PLC_Reset( psDec );
+        psDec->sPLC.fs_kHz = psDec->fs_kHz;
+    }
+
+    if( lost ) {
+        /****************************/
+        /* Generate Signal          */
+        /****************************/
+        silk_PLC_conceal( psDec, psDecCtrl, frame, length );
+
+        psDec->lossCnt++;
+    } else {
+        /****************************/
+        /* Update state             */
+        /****************************/
+        silk_PLC_update( psDec, psDecCtrl, frame, length );
+    }
+}
+
+/**************************************************/
+/* Update state of PLC                            */
+/**************************************************/
+void silk_PLC_update(
+    silk_decoder_state          *psDec,             /* (I/O) Decoder state          */
+    silk_decoder_control        *psDecCtrl,         /* (I/O) Decoder control        */
+    opus_int16                   frame[],
+    opus_int                     length
+)
+{
+    opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14;
+    opus_int   i, j;
+    silk_PLC_struct *psPLC;
+
+    psPLC = &psDec->sPLC;
+
+    /* Update parameters used in case of packet loss */
+    psDec->prevSignalType = psDec->indices.signalType;
+    LTP_Gain_Q14 = 0;
+    if( psDec->indices.signalType == TYPE_VOICED ) {
+        /* Find the parameters for the last subframe which contains a pitch pulse */
+        for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) {
+            if( j == psDec->nb_subfr ){
+                break;
+            }
+            temp_LTP_Gain_Q14 = 0;
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER  + i ];
+            }
+            if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) {
+                LTP_Gain_Q14 = temp_LTP_Gain_Q14;
+                silk_memcpy( psPLC->LTPCoef_Q14,
+                    &psDecCtrl->LTPCoef_Q14[ silk_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ],
+                    LTP_ORDER * sizeof( opus_int16 ) );
+
+                psPLC->pitchL_Q8 = silk_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 );
+            }
+        }
+
+#if USE_SINGLE_TAP
+        silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
+        psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14;
+#endif
+
+        /* Limit LT coefs */
+        if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) {
+            opus_int   scale_Q10;
+            opus_int32 tmp;
+
+            tmp = silk_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 );
+            scale_Q10 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 );
+            }
+        } else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) {
+            opus_int   scale_Q14;
+            opus_int32 tmp;
+
+            tmp = silk_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 );
+            scale_Q14 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 );
+            }
+        }
+    } else {
+        psPLC->pitchL_Q8 = silk_LSHIFT( silk_SMULBB( psDec->fs_kHz, 18 ), 8 );
+        silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ));
+    }
+
+    /* Save LPC coeficients */
+    silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
+    psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
+
+    /* Save Gains */
+    silk_memcpy( psPLC->prevGain_Q16, psDecCtrl->Gains_Q16, psDec->nb_subfr * sizeof( opus_int32 ) );
+}
+
+void silk_PLC_conceal(
+    silk_decoder_state          *psDec,             /* I/O Decoder state */
+    silk_decoder_control        *psDecCtrl,         /* I/O Decoder control */
+    opus_int16                   frame[],            /* O concealed signal */
+    opus_int                     length              /* I length of residual */
+)
+{
+    opus_int   i, j, k;
+    opus_int16 *B_Q14, exc_buf[ MAX_FRAME_LENGTH ], *exc_buf_ptr;
+    opus_int16 rand_scale_Q14, A_Q12_tmp[ MAX_LPC_ORDER ];
+    opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15;
+    opus_int   lag, idx, sLTP_buf_idx, shift1, shift2;
+    opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
+    opus_int32 sig_Q10[ MAX_FRAME_LENGTH ], *sig_Q10_ptr, LPC_exc_Q10, LPC_pred_Q10,  LTP_pred_Q14;
+    silk_PLC_struct *psPLC;
+    psPLC = &psDec->sPLC;
+
+    /* Update LTP buffer */
+    silk_memmove( psDec->sLTP_Q16, &psDec->sLTP_Q16[ psDec->frame_length ], psDec->ltp_mem_length * sizeof( opus_int32 ) );
+
+    /* LPC concealment. Apply BWE to previous LPC */
+    silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );
+
+    /* Find random noise component */
+    /* Scale previous excitation signal */
+    exc_buf_ptr = exc_buf;
+    /* FIXME: JMV: Is this the right fix? */
+    for (i=0;i<MAX_FRAME_LENGTH;i++)
+        exc_buf[i] = 0;
+    for( k = ( psDec->nb_subfr >> 1 ); k < psDec->nb_subfr; k++ ) {
+        for( i = 0; i < psDec->subfr_length; i++ ) {
+            exc_buf_ptr[ i ] = ( opus_int16 )silk_RSHIFT(
+                silk_SMULWW( psDec->exc_Q10[ i + k * psDec->subfr_length ], psPLC->prevGain_Q16[ k ] ), 10 );
+        }
+        exc_buf_ptr += psDec->subfr_length;
+    }
+    /* Find the subframe with lowest energy of the last two and use that as random noise generator */
+    silk_sum_sqr_shift( &energy1, &shift1, exc_buf,                         psDec->subfr_length );
+    silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length );
+
+    if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
+        /* First sub-frame has lowest energy */
+        rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, 3 * psDec->subfr_length - RAND_BUF_SIZE ) ];
+    } else {
+        /* Second sub-frame has lowest energy */
+        rand_ptr = &psDec->exc_Q10[ silk_max_int( 0, psDec->frame_length - RAND_BUF_SIZE ) ];
+    }
+
+    /* Setup Gain to random noise component */
+    B_Q14          = psPLC->LTPCoef_Q14;
+    rand_scale_Q14 = psPLC->randScale_Q14;
+
+    /* Setup 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 ) ];
+    } else {
+        rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
+    }
+
+    /* First Lost frame */
+    if( psDec->lossCnt == 0 ) {
+        rand_scale_Q14 = 1 << 14;
+
+        /* Reduce random noise Gain for voiced frames */
+        if( psDec->prevSignalType == TYPE_VOICED ) {
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                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 );
+        } 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 );
+
+            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 );
+            down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
+
+            rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
+        }
+    }
+
+    rand_seed    = psPLC->rand_seed;
+    lag          = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
+    sLTP_buf_idx = psDec->ltp_mem_length;
+
+    /***************************/
+    /* LTP synthesis filtering */
+    /***************************/
+    sig_Q10_ptr = sig_Q10;
+    for( k = 0; k < psDec->nb_subfr; k++ ) {
+        /* Setup pointer */
+        pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+        for( i = 0; i < psDec->subfr_length; i++ ) {
+            rand_seed = silk_RAND( rand_seed );
+            idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
+
+            /* 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 ] );
+            pred_lag_ptr++;
+
+            /* Generate LPC residual */
+            LPC_exc_Q10 = silk_LSHIFT( silk_SMULWB( rand_ptr[ idx ], rand_scale_Q14 ), 2 ); /* Random noise part */
+            LPC_exc_Q10 = silk_ADD32( LPC_exc_Q10, silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ) );  /* Harmonic part */
+
+            /* Update states */
+            psDec->sLTP_Q16[ sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q10, 6 );
+            sLTP_buf_idx++;
+
+            /* Save LPC residual */
+            sig_Q10_ptr[ i ] = LPC_exc_Q10;
+        }
+        sig_Q10_ptr += psDec->subfr_length;
+        /* Gradually reduce LTP gain */
+        for( j = 0; j < LTP_ORDER; j++ ) {
+            B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
+        }
+        /* Gradually reduce excitation gain */
+        rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
+
+        /* Slowly increase pitch lag */
+        psPLC->pitchL_Q8 += silk_SMULWB( psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
+        psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
+        lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
+    }
+
+    /***************************/
+    /* LPC synthesis filtering */
+    /***************************/
+    sig_Q10_ptr = sig_Q10;
+    /* Preload LPC coeficients to array on stack. Gives small performance gain */
+    silk_memcpy( A_Q12_tmp, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
+    silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
+    for( k = 0; k < psDec->nb_subfr; k++ ) {
+        for( i = 0; i < psDec->subfr_length; i++ ){
+            /* partly unrolled */
+            LPC_pred_Q10 = silk_SMULWB(               psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12_tmp[ 0 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  2 ], A_Q12_tmp[ 1 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  3 ], A_Q12_tmp[ 2 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  4 ], A_Q12_tmp[ 3 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  5 ], A_Q12_tmp[ 4 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  6 ], A_Q12_tmp[ 5 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  7 ], A_Q12_tmp[ 6 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  8 ], A_Q12_tmp[ 7 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  9 ], A_Q12_tmp[ 8 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->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, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] );
+            }
+
+            /* Add prediction to LPC residual */
+            sig_Q10_ptr[ i ] = silk_ADD32( sig_Q10_ptr[ i ], LPC_pred_Q10 );
+
+            /* Update states */
+            psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_LSHIFT( sig_Q10_ptr[ i ], 4 );
+        }
+        sig_Q10_ptr += psDec->subfr_length;
+        /* Update LPC filter state */
+        silk_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+    }
+
+    /* Scale with Gain */
+    for( i = 0; i < psDec->frame_length; i++ ) {
+        frame[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sig_Q10[ i ], psPLC->prevGain_Q16[ psDec->nb_subfr - 1 ] ), 10 ) );
+    }
+
+    /**************************************/
+    /* Update states                      */
+    /**************************************/
+    psPLC->rand_seed     = rand_seed;
+    psPLC->randScale_Q14 = rand_scale_Q14;
+    for( i = 0; i < MAX_NB_SUBFR; i++ ) {
+        psDecCtrl->pitchL[ i ] = lag;
+    }
+}
+
+/* Glues concealed frames with new good recieved frames             */
+void silk_PLC_glue_frames(
+    silk_decoder_state          *psDec,             /* I/O decoder state    */
+    silk_decoder_control        *psDecCtrl,         /* I/O Decoder control  */
+    opus_int16                   frame[],            /* I/O signal           */
+    opus_int                     length              /* I length of residual */
+)
+{
+    opus_int   i, energy_shift;
+    opus_int32 energy;
+    silk_PLC_struct *psPLC;
+    psPLC = &psDec->sPLC;
+
+    if( psDec->lossCnt ) {
+        /* Calculate energy in concealed residual */
+        silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length );
+
+        psPLC->last_frame_lost = 1;
+    } else {
+        if( psDec->sPLC.last_frame_lost ) {
+            /* Calculate residual in decoded signal if last frame was lost */
+            silk_sum_sqr_shift( &energy, &energy_shift, frame, length );
+
+            /* Normalize energies */
+            if( energy_shift > psPLC->conc_energy_shift ) {
+                psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
+            } else if( energy_shift < psPLC->conc_energy_shift ) {
+                energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
+            }
+
+            /* Fade in the energy difference */
+            if( energy > psPLC->conc_energy ) {
+                opus_int32 frac_Q24, LZ;
+                opus_int32 gain_Q16, slope_Q16;
+
+                LZ = silk_CLZ32( psPLC->conc_energy );
+                LZ = LZ - 1;
+                psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ );
+                energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) );
+
+                frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) );
+
+                gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 );
+                slope_Q16 = silk_DIV32_16( ( 1 << 16 ) - gain_Q16, length );
+                /* Make slope 4x steeper to avoid missing onsets after DTX */
+                slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
+
+                for( i = 0; i < length; i++ ) {
+                    frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
+                    gain_Q16 += slope_Q16;
+                    if( gain_Q16 > 1 << 16 ) {
+                        break;
+                    }
+                }
+            }
+        }
+        psPLC->last_frame_lost = 0;
+    }
+}
--- /dev/null
+++ b/silk/PLC.h
@@ -1,0 +1,79 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_PLC_FIX_H
+#define SILK_PLC_FIX_H
+
+#include "main.h"
+
+#define BWE_COEF                        0.99
+#define V_PITCH_GAIN_START_MIN_Q14      11469           /* 0.7 in Q14                       */
+#define V_PITCH_GAIN_START_MAX_Q14      15565           /* 0.95 in Q14                      */
+#define MAX_PITCH_LAG_MS                18
+#define SA_THRES_Q8                     50
+#define USE_SINGLE_TAP                  1
+#define RAND_BUF_SIZE                   128
+#define RAND_BUF_MASK                   (RAND_BUF_SIZE - 1)
+#define LOG2_INV_LPC_GAIN_HIGH_THRES    3               /* 2^3 = 8 dB LPC gain              */
+#define LOG2_INV_LPC_GAIN_LOW_THRES     8               /* 2^8 = 24 dB LPC gain             */
+#define PITCH_DRIFT_FAC_Q16             655             /* 0.01 in Q16                      */
+
+void silk_PLC_Reset(
+    silk_decoder_state      *psDec              /* I/O Decoder state        */
+);
+
+void silk_PLC(
+    silk_decoder_state      *psDec,             /* I/O Decoder state        */
+    silk_decoder_control    *psDecCtrl,         /* I/O Decoder control      */
+    opus_int16                   signal[],           /* I/O  signal              */
+    opus_int                     length,             /* I length of residual     */
+    opus_int                     lost                /* I Loss flag              */
+);
+
+void silk_PLC_update(
+    silk_decoder_state      *psDec,             /* I/O Decoder state        */
+    silk_decoder_control    *psDecCtrl,         /* I/O Decoder control      */
+    opus_int16                   signal[],
+    opus_int                     length
+);
+
+void silk_PLC_conceal(
+    silk_decoder_state      *psDec,             /* I/O Decoder state        */
+    silk_decoder_control    *psDecCtrl,         /* I/O Decoder control      */
+    opus_int16                   signal[],           /* O LPC residual signal    */
+    opus_int                     length              /* I length of signal       */
+);
+
+void silk_PLC_glue_frames(
+    silk_decoder_state      *psDec,             /* I/O decoder state        */
+    silk_decoder_control    *psDecCtrl,         /* I/O Decoder control      */
+    opus_int16                   signal[],           /* I/O signal               */
+    opus_int                     length              /* I length of signal       */
+);
+
+#endif
+
--- /dev/null
+++ b/silk/SigProc_FIX.h
@@ -1,0 +1,620 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef _SILK_SIGPROC_FIX_H_
+#define _SILK_SIGPROC_FIX_H_
+
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+
+/*#define silk_MACRO_COUNT */          /* Used to enable WMOPS counting */
+
+#define SILK_MAX_ORDER_LPC            16                        /* max order of the LPC analysis in schur() and k2a()    */
+
+#include <stdlib.h>                                             /* for abs() */
+#include <string.h>                                             /* for memset(), memcpy(), memmove() */
+#include "typedef.h"
+#include "resampler_structs.h"
+#include "macros.h"
+
+
+/********************************************************************/
+/*                    SIGNAL PROCESSING FUNCTIONS                   */
+/********************************************************************/
+
+/*!
+ * 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)    */
+);
+
+/*!
+ * Clear the states of all resampling filters, without resetting sampling rate ratio
+ */
+opus_int silk_resampler_clear(
+    silk_resampler_state_struct            *S          /* I/O: Resampler state             */
+);
+
+/*!
+ * 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        */
+);
+
+/*!
+ Upsample 2x, low quality
+ */
+void silk_resampler_up2(
+    opus_int32                           *S,         /* I/O: State vector [ 2 ]                  */
+    opus_int16                           *out,       /* O:   Output signal [ 2 * len ]           */
+    const opus_int16                     *in,        /* I:   Input signal [ len ]                */
+    opus_int32                           len         /* I:   Number of input samples             */
+);
+
+/*!
+* Downsample 2x, mediocre quality
+*/
+void silk_resampler_down2(
+    opus_int32                           *S,         /* I/O: State vector [ 2 ]                  */
+    opus_int16                           *out,       /* O:   Output signal [ len ]               */
+    const opus_int16                     *in,        /* I:   Input signal [ floor(len/2) ]       */
+    opus_int32                           inLen       /* I:   Number of input samples             */
+);
+
+
+/*!
+ * Downsample by a factor 2/3, low quality
+*/
+void silk_resampler_down2_3(
+    opus_int32                           *S,         /* I/O: State vector [ 6 ]                  */
+    opus_int16                           *out,       /* O:   Output signal [ floor(2*inLen/3) ]  */
+    const opus_int16                     *in,        /* I:   Input signal [ inLen ]              */
+    opus_int32                           inLen       /* I:   Number of input samples             */
+);
+
+/*!
+ * Downsample by a factor 3, low quality
+*/
+void silk_resampler_down3(
+    opus_int32                           *S,         /* I/O: State vector [ 8 ]                  */
+    opus_int16                           *out,       /* O:   Output signal [ floor(inLen/3) ]    */
+    const opus_int16                     *in,        /* I:   Input signal [ inLen ]              */
+    opus_int32                           inLen       /* I:   Number of input samples             */
+);
+
+/*!
+ * second order ARMA filter;
+ * slower than biquad() but uses more precise coefficients
+ * can handle (slowly) varying coefficients
+ */
+void silk_biquad_alt(
+    const opus_int16     *in,           /* I:    input signal                 */
+    const opus_int32     *B_Q28,        /* I:    MA coefficients [3]          */
+    const opus_int32     *A_Q28,        /* I:    AR coefficients [2]          */
+    opus_int32           *S,            /* I/O:  State vector [2]             */
+    opus_int16           *out,          /* O:    output signal                */
+    const opus_int32     len,           /* I:    signal length (must be even) */
+    int stride
+);
+
+/* Variable order MA prediction error filter. */
+void silk_LPC_analysis_filter(
+    opus_int16            *out,         /* O:   Output signal                               */
+    const opus_int16      *in,          /* I:   Input signal                                */
+    const opus_int16      *B,           /* I:   MA prediction coefficients, Q12 [order]     */
+    const opus_int32      len,          /* I:   Signal length                               */
+    const opus_int32      Order         /* I:   Filter order                                */
+);
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander(
+    opus_int16            *ar,          /* I/O  AR filter to be expanded (without leading 1)    */
+    const opus_int        d,            /* I    Length of ar                                    */
+    opus_int32            chirp_Q16     /* I    Chirp factor (typically in the range 0 to 1)    */
+);
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander_32(
+    opus_int32            *ar,          /* I/O  AR filter to be expanded (without leading 1)    */
+    const opus_int        d,            /* I    Length of ar                                    */
+    opus_int32            chirp_Q16     /* I    Chirp factor in Q16                             */
+);
+
+/* 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  */
+    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]        */
+    const opus_int       order           /* I:   Prediction order                            */
+);
+
+/* split signal in two decimated bands using first-order allpass filters */
+void silk_ana_filt_bank_1(
+    const opus_int16      *in,           /* I:   Input signal [N]        */
+    opus_int32            *S,            /* I/O: State vector [2]        */
+    opus_int16            *outL,         /* O:   Low band [N/2]          */
+    opus_int16            *outH,         /* O:   High band [N/2]         */
+    const opus_int32      N              /* I:   Number of input samples */
+);
+
+/********************************************************************/
+/*                        SCALAR FUNCTIONS                          */
+/********************************************************************/
+
+/* approximation of 128 * log2() (exact inverse of approx 2^() below) */
+/* convert input to a log scale    */
+opus_int32 silk_lin2log(const opus_int32 inLin);        /* I: input in linear scale        */
+
+/* Approximation of a sigmoid function */
+opus_int silk_sigm_Q15(opus_int in_Q5);
+
+/* approximation of 2^() (exact inverse of approx log2() above) */
+/* convert input to a linear scale    */
+opus_int32 silk_log2lin(const opus_int32 inLog_Q7);    /* I: input on log scale */
+
+/* Function that returns the maximum absolut value of the input vector */
+opus_int16 silk_int16_array_maxabs(      /* O   Maximum absolute value, max: 2^15-1   */
+    const opus_int16     *vec,           /* I   Input vector  [len]                   */
+    const opus_int32     len             /* I   Length of input vector                */
+);
+
+/* Compute number of bits to right shift the sum of squares of a vector    */
+/* of int16s to make it fit in an int32                                    */
+void silk_sum_sqr_shift(
+    opus_int32           *energy,        /* O   Energy of x, after shifting to the right            */
+    opus_int             *shift,         /* O   Number of bits right shift applied to energy        */
+    const opus_int16     *x,             /* I   Input vector                                        */
+    opus_int             len             /* I   Length of input vector                              */
+);
+
+/* Calculates the reflection coefficients from the correlation sequence    */
+/* Faster than schur64(), but much less accurate.                          */
+/* uses SMLAWB(), requiring armv5E and higher.                             */
+opus_int32 silk_schur(                   /* O:    Returns residual energy                   */
+    opus_int16           *rc_Q15,        /* O:    reflection coefficients [order] Q15       */
+    const opus_int32     *c,             /* I:    correlations [order+1]                    */
+    const opus_int32     order           /* I:    prediction order                          */
+);
+
+/* Calculates the reflection coefficients from the correlation sequence    */
+/* Slower than schur(), but more accurate.                                 */
+/* Uses SMULL(), available on armv4                                        */
+opus_int32 silk_schur64(                 /* O:  returns residual energy                     */
+    opus_int32           rc_Q16[],       /* O:  Reflection coefficients [order] Q16         */
+    const opus_int32     c[],            /* I:  Correlations [order+1]                      */
+    opus_int32           order           /* I:  Prediction order                            */
+);
+
+/* Step up function, converts reflection coefficients to prediction coefficients */
+void silk_k2a(
+    opus_int32           *A_Q24,         /* O:  Prediction coefficients [order] Q24         */
+    const opus_int16     *rc_Q15,        /* I:  Reflection coefficients [order] Q15         */
+    const opus_int32     order           /* I:  Prediction order                            */
+);
+
+/* Step up function, converts reflection coefficients to prediction coefficients */
+void silk_k2a_Q16(
+    opus_int32           *A_Q24,         /* O:  Prediction coefficients [order] Q24         */
+    const opus_int32     *rc_Q16,        /* I:  Reflection coefficients [order] Q16         */
+    const opus_int32     order           /* I:  Prediction order                            */
+);
+
+/* Apply sine window to signal vector.                                      */
+/* Window types:                                                            */
+/*    1 -> sine window from 0 to pi/2                                       */
+/*    2 -> sine window from pi/2 to pi                                      */
+/* every other sample of window is linearly interpolated, for speed         */
+void silk_apply_sine_window(
+    opus_int16           px_win[],       /* O  Pointer to windowed signal                  */
+    const opus_int16     px[],           /* I  Pointer to input signal                     */
+    const opus_int       win_type,       /* I  Selects a window type                       */
+    const opus_int       length          /* I  Window length, multiple of 4                */
+);
+
+/* Compute autocorrelation */
+void silk_autocorr(
+    opus_int32           *results,       /* O  Result (length correlationCount)            */
+    opus_int             *scale,         /* O  Scaling of the correlation vector           */
+    const opus_int16     *inputData,     /* I  Input data to correlate                     */
+    const opus_int       inputDataSize,  /* I  Length of input                             */
+    const opus_int       correlationCount /* I  Number of correlation taps to compute      */
+);
+
+/* Pitch estimator */
+#define SILK_PE_MIN_COMPLEX        0
+#define SILK_PE_MID_COMPLEX        1
+#define SILK_PE_MAX_COMPLEX        2
+
+void silk_decode_pitch(
+    opus_int16       lagIndex,                        /* I                             */
+    opus_int8        contourIndex,                    /* O                             */
+    opus_int         pitch_lags[],                    /* O 4 pitch values              */
+    const opus_int   Fs_kHz,                          /* I sampling frequency (kHz)    */
+    const opus_int   nb_subfr                         /* I number of sub frames        */
+);
+
+opus_int silk_pitch_analysis_core(        /* O    Voicing estimate: 0 voiced, 1 unvoiced                     */
+    const opus_int16  *signal,            /* I    Signal of length PE_FRAME_LENGTH_MS*Fs_kHz                 */
+    opus_int          *pitch_out,         /* O    4 pitch lag values                                         */
+    opus_int16        *lagIndex,          /* O    Lag Index                                                  */
+    opus_int8         *contourIndex,      /* O    Pitch contour Index                                        */
+    opus_int          *LTPCorr_Q15,       /* I/O  Normalized correlation; input: value from previous frame   */
+    opus_int          prevLag,            /* I    Last lag of previous frame; set to zero is unvoiced        */
+    const opus_int32  search_thres1_Q16,  /* I    First stage threshold for lag candidates 0 - 1             */
+    const opus_int    search_thres2_Q15,  /* I    Final threshold for lag candidates 0 - 1                   */
+    const opus_int    Fs_kHz,             /* I    Sample frequency (kHz)                                     */
+    const opus_int    complexity,         /* I    Complexity setting, 0-2, where 2 is highest                */
+    const opus_int    nb_subfr            /* I    number of 5 ms subframes                                   */
+);
+
+/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients      */
+/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
+void silk_A2NLSF(
+    opus_int16          *NLSF,            /* O    Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d] */
+    opus_int32          *a_Q16,           /* I/O  Monic whitening filter coefficients in Q16 [d]                */
+    const opus_int      d                 /* I    Filter order (must be even)                                   */
+);
+
+/* compute whitening filter coefficients from normalized line spectral frequencies */
+void silk_NLSF2A(
+    opus_int16        *a_Q12,            /* O    monic whitening filter coefficients in Q12,  [ d ]  */
+    const opus_int16  *NLSF,             /* I    normalized line spectral frequencies in Q15, [ d ]  */
+    const opus_int    d                  /* I    filter order (should be even)                       */
+);
+
+void silk_insertion_sort_increasing(
+    opus_int32            *a,            /* I/O   Unsorted / Sorted vector                */
+    opus_int              *idx,          /* O:    Index vector for the sorted elements    */
+    const opus_int        L,             /* I:    Vector length                           */
+    const opus_int        K              /* I:    Number of correctly sorted positions    */
+);
+
+void silk_insertion_sort_decreasing_int16(
+    opus_int16            *a,            /* I/O:  Unsorted / Sorted vector                */
+    opus_int              *idx,          /* O:    Index vector for the sorted elements    */
+    const opus_int        L,             /* I:    Vector length                           */
+    const opus_int        K              /* I:    Number of correctly sorted positions    */
+);
+
+void silk_insertion_sort_increasing_all_values_int16(
+     opus_int16           *a,            /* I/O:  Unsorted / Sorted vector                */
+     const opus_int       L              /* I:    Vector length                           */
+);
+
+/* NLSF stabilizer, for a single input data vector */
+void silk_NLSF_stabilize(
+          opus_int16      *NLSF_Q15,      /* I/O:  Unstable/stabilized normalized LSF vector in Q15 [L]                    */
+    const opus_int16      *NDeltaMin_Q15, /* I:    Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */
+    const opus_int        L               /* I:    Number of NLSF parameters in the input vector                           */
+);
+
+/* Laroia low complexity NLSF weights */
+void silk_NLSF_VQ_weights_laroia(
+    opus_int16            *pNLSFW_Q_OUT,  /* O:    Pointer to input vector weights            [D x 1]       */
+    const opus_int16      *pNLSF_Q15,     /* I:    Pointer to input vector                    [D x 1]       */
+    const opus_int        D               /* I:    Input vector dimension (even)                            */
+);
+
+/* Compute reflection coefficients from input signal */
+void silk_burg_modified(
+    opus_int32            *res_nrg,           /* O   residual energy                                                 */
+    opus_int              *res_nrgQ,          /* 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_int        subfr_length,       /* I   input signal subframe length (including 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                                                           */
+);
+
+/* Copy and multiply a vector by a constant */
+void silk_scale_copy_vector16(
+    opus_int16            *data_out,
+    const opus_int16      *data_in,
+    opus_int32            gain_Q16,           /* I:   gain in Q16   */
+    const opus_int        dataSize            /* I:   length        */
+);
+
+/* Some for the LTP related function requires Q26 to work.*/
+void silk_scale_vector32_Q26_lshift_18(
+    opus_int32            *data1,             /* I/O: Q0/Q18        */
+    opus_int32            gain_Q26,           /* I:   Q26           */
+    opus_int              dataSize            /* I:   length        */
+);
+
+/********************************************************************/
+/*                        INLINE ARM MATH                             */
+/********************************************************************/
+
+/*    return sum(inVec1[i]*inVec2[i])    */
+opus_int32 silk_inner_prod_aligned(
+    const opus_int16 *const  inVec1,     /*    I input vector 1    */
+    const opus_int16 *const  inVec2,     /*    I input vector 2    */
+    const opus_int           len         /*    I vector lengths    */
+);
+
+opus_int32 silk_inner_prod_aligned_scale(
+    const opus_int16 *const  inVec1,     /*    I input vector 1          */
+    const opus_int16 *const  inVec2,     /*    I input vector 2          */
+    const opus_int           scale,      /*    I number of bits to shift */
+    const opus_int           len         /*    I vector lengths          */
+);
+
+opus_int64 silk_inner_prod16_aligned_64(
+    const opus_int16         *inVec1,    /*    I input vector 1    */
+    const opus_int16         *inVec2,    /*    I input vector 2    */
+    const opus_int           len         /*    I vector lengths    */
+);
+
+/********************************************************************/
+/*                                MACROS                            */
+/********************************************************************/
+
+/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating
+   left. Output is 32bit int.
+   Note: contemporary compilers recognize the C expression below and
+   compile it into a 'ror' instruction if available. No need for inline ASM! */
+static inline opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
+{
+    opus_uint32 x = (opus_uint32) a32;
+    opus_uint32 r = (opus_uint32) rot;
+    opus_uint32 m = (opus_uint32) -rot;
+    if (rot==0)
+       return a32;
+    else if(rot < 0)
+        return (opus_int32) ((x << m) | (x >> (32 - m)));
+    else
+        return (opus_int32) ((x << (32 - r)) | (x >> r));
+}
+
+/* Allocate opus_int16 alligned to 4-byte memory address */
+#if EMBEDDED_ARM
+#define silk_DWORD_ALIGN __attribute__((aligned(4)))
+#else
+#define silk_DWORD_ALIGN
+#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 */
+/* fixed point macros */
+
+/* (a32 * b32) output have to be 32bit int */
+#define silk_MUL(a32, b32)                  ((a32) * (b32))
+
+/* (a32 * b32) output have to be 32bit uint */
+#define silk_MUL_uint(a32, b32)             silk_MUL(a32, b32)
+
+/* a32 + (b32 * c32) output have to be 32bit int */
+#define silk_MLA(a32, b32, c32)             silk_ADD32((a32),((b32) * (c32)))
+
+/* a32 + (b32 * c32) output have to be 32bit uint */
+#define silk_MLA_uint(a32, b32, c32)        silk_MLA(a32, b32, c32)
+
+/* ((a32 >> 16)  * (b32 >> 16)) output have to be 32bit int */
+#define silk_SMULTT(a32, b32)               (((a32) >> 16) * ((b32) >> 16))
+
+/* a32 + ((a32 >> 16)  * (b32 >> 16)) output have to be 32bit int */
+#define silk_SMLATT(a32, b32, c32)          silk_ADD32((a32),((b32) >> 16) * ((c32) >> 16))
+
+#define silk_SMLALBB(a64, b16, c16)         silk_ADD64((a64),(opus_int64)((opus_int32)(b16) * (opus_int32)(c16)))
+
+/* (a32 * b32) */
+#define silk_SMULL(a32, b32)                ((opus_int64)(a32) * /*(opus_int64)*/(b32))
+
+/* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
+   (just standard two's complement implementation-specific behaviour) */
+#define silk_ADD32_ovflw(a, b)              ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b)))
+
+/* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
+#define silk_MLA_ovflw(a32, b32, c32)       silk_ADD32_ovflw((a32),(opus_uint32)(b32) * (opus_uint32)(c32))
+#ifndef silk_SMLABB_ovflw
+#    define silk_SMLABB_ovflw(a32, b32, c32)    silk_ADD32_ovflw((a32), (opus_int32)((opus_int16)(b32)) * (opus_int32)((opus_int16)(c32)))
+#endif
+
+#define silk_DIV32_16(a32, b16)             ((opus_int32)((a32) / (b16)))
+#define silk_DIV32(a32, b32)                ((opus_int32)((a32) / (b32)))
+
+/* These macros enables checking for overflow in silk_API_Debug.h*/
+#define silk_ADD16(a, b)                    ((a) + (b))
+#define silk_ADD32(a, b)                    ((a) + (b))
+#define silk_ADD64(a, b)                    ((a) + (b))
+
+#define silk_SUB16(a, b)                    ((a) - (b))
+#define silk_SUB32(a, b)                    ((a) - (b))
+#define silk_SUB64(a, b)                    ((a) - (b))
+
+#define silk_SAT8(a)                        ((a) > silk_int8_MAX ? silk_int8_MAX  : \
+                                           ((a) < silk_int8_MIN ? silk_int8_MIN  : (a)))
+#define silk_SAT16(a)                       ((a) > silk_int16_MAX ? silk_int16_MAX : \
+                                           ((a) < silk_int16_MIN ? silk_int16_MIN : (a)))
+#define silk_SAT32(a)                       ((a) > silk_int32_MAX ? silk_int32_MAX : \
+                                           ((a) < silk_int32_MIN ? silk_int32_MIN : (a)))
+
+#define silk_CHECK_FIT8(a)                  (a)
+#define silk_CHECK_FIT16(a)                 (a)
+#define silk_CHECK_FIT32(a)                 (a)
+
+#define silk_ADD_SAT16(a, b)                (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a), (b) ) )
+#define silk_ADD_SAT64(a, b)                ((((a) + (b)) & 0x8000000000000000LL) == 0 ?                            \
+                                           ((((a) & (b)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a)+(b)) :    \
+                                           ((((a) | (b)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a)+(b)) )
+
+#define silk_SUB_SAT16(a, b)                (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a), (b) ) )
+#define silk_SUB_SAT64(a, b)                ((((a)-(b)) & 0x8000000000000000LL) == 0 ?                                                    \
+                                           (( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a)-(b)) :    \
+                                           ((((a)^0x8000000000000000LL) & (b)  & 0x8000000000000000LL) ? silk_int64_MAX : (a)-(b)) )
+
+/* Saturation for positive input values */
+#define silk_POS_SAT32(a)                   ((a) > silk_int32_MAX ? silk_int32_MAX : (a))
+
+/* Add with saturation for positive input values */
+#define silk_ADD_POS_SAT8(a, b)             ((((a)+(b)) & 0x80)                 ? silk_int8_MAX  : ((a)+(b)))
+#define silk_ADD_POS_SAT16(a, b)            ((((a)+(b)) & 0x8000)               ? silk_int16_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT32(a, b)            ((((a)+(b)) & 0x80000000)           ? silk_int32_MAX : ((a)+(b)))
+#define silk_ADD_POS_SAT64(a, b)            ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)))
+
+#define silk_LSHIFT8(a, shift)              ((a)<<(shift))                /* shift >= 0, shift < 8  */
+#define silk_LSHIFT16(a, shift)             ((a)<<(shift))                /* shift >= 0, shift < 16 */
+#define silk_LSHIFT32(a, shift)             ((a)<<(shift))                /* shift >= 0, shift < 32 */
+#define silk_LSHIFT64(a, shift)             ((a)<<(shift))                /* shift >= 0, shift < 64 */
+#define silk_LSHIFT(a, shift)               silk_LSHIFT32(a, shift)        /* shift >= 0, shift < 32 */
+
+#define silk_RSHIFT8(a, shift)              ((a)>>(shift))                /* shift >= 0, shift < 8  */
+#define silk_RSHIFT16(a, shift)             ((a)>>(shift))                /* shift >= 0, shift < 16 */
+#define silk_RSHIFT32(a, shift)             ((a)>>(shift))                /* shift >= 0, shift < 32 */
+#define silk_RSHIFT64(a, shift)             ((a)>>(shift))                /* shift >= 0, shift < 64 */
+#define silk_RSHIFT(a, shift)               silk_RSHIFT32(a, shift)        /* shift >= 0, shift < 32 */
+
+/* saturates before shifting */
+#define silk_LSHIFT_SAT16(a, shift)         (silk_LSHIFT16( silk_LIMIT( (a), silk_RSHIFT16( silk_int16_MIN, (shift) ),    \
+                                                                          silk_RSHIFT16( silk_int16_MAX, (shift) ) ), (shift) ))
+#define silk_LSHIFT_SAT32(a, shift)         (silk_LSHIFT32( silk_LIMIT( (a), silk_RSHIFT32( silk_int32_MIN, (shift) ),    \
+                                                                          silk_RSHIFT32( silk_int32_MAX, (shift) ) ), (shift) ))
+
+#define silk_LSHIFT_ovflw(a, shift)        ((a)<<(shift))        /* shift >= 0, allowed to overflow */
+#define silk_LSHIFT_uint(a, shift)         ((a)<<(shift))        /* shift >= 0 */
+#define silk_RSHIFT_uint(a, shift)         ((a)>>(shift))        /* shift >= 0 */
+
+#define silk_ADD_LSHIFT(a, b, shift)       ((a) + silk_LSHIFT((b), (shift)))             /* shift >= 0 */
+#define silk_ADD_LSHIFT32(a, b, shift)     silk_ADD32((a), silk_LSHIFT32((b), (shift)))   /* shift >= 0 */
+#define silk_ADD_LSHIFT_uint(a, b, shift)  ((a) + silk_LSHIFT_uint((b), (shift)))        /* shift >= 0 */
+#define silk_ADD_RSHIFT(a, b, shift)       ((a) + silk_RSHIFT((b), (shift)))             /* shift >= 0 */
+#define silk_ADD_RSHIFT32(a, b, shift)     silk_ADD32((a), silk_RSHIFT32((b), (shift)))   /* shift >= 0 */
+#define silk_ADD_RSHIFT_uint(a, b, shift)  ((a) + silk_RSHIFT_uint((b), (shift)))        /* shift >= 0 */
+#define silk_SUB_LSHIFT32(a, b, shift)     silk_SUB32((a), silk_LSHIFT32((b), (shift)))   /* shift >= 0 */
+#define silk_SUB_RSHIFT32(a, b, shift)     silk_SUB32((a), silk_RSHIFT32((b), (shift)))   /* shift >= 0 */
+
+/* Requires that shift > 0 */
+#define silk_RSHIFT_ROUND(a, shift)        ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
+#define silk_RSHIFT_ROUND64(a, shift)      ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
+
+/* Number of rightshift required to fit the multiplication */
+#define silk_NSHIFT_MUL_32_32(a, b)        ( -(31- (32-silk_CLZ32(silk_abs(a)) + (32-silk_CLZ32(silk_abs(b))))) )
+#define silk_NSHIFT_MUL_16_16(a, b)        ( -(15- (16-silk_CLZ16(silk_abs(a)) + (16-silk_CLZ16(silk_abs(b))))) )
+
+
+#define silk_min(a, b)                     (((a) < (b)) ? (a) : (b))
+#define silk_max(a, b)                     (((a) > (b)) ? (a) : (b))
+
+/* Macro to convert floating-point constants to fixed-point */
+#define SILK_FIX_CONST( C, Q )           ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5))
+
+/* silk_min() versions with typecast in the function call */
+static inline opus_int silk_min_int(opus_int a, opus_int b)
+{
+    return (((a) < (b)) ? (a) : (b));
+}
+static inline opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
+{
+    return (((a) < (b)) ? (a) : (b));
+}
+static inline opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
+{
+    return (((a) < (b)) ? (a) : (b));
+}
+static inline opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
+{
+    return (((a) < (b)) ? (a) : (b));
+}
+
+/* silk_min() versions with typecast in the function call */
+static inline opus_int silk_max_int(opus_int a, opus_int b)
+{
+    return (((a) > (b)) ? (a) : (b));
+}
+static inline opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
+{
+    return (((a) > (b)) ? (a) : (b));
+}
+static inline opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
+{
+    return (((a) > (b)) ? (a) : (b));
+}
+static inline opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
+{
+    return (((a) > (b)) ? (a) : (b));
+}
+
+#define silk_LIMIT( a, limit1, limit2)    ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
+                                                             : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))))
+
+#define silk_LIMIT_int silk_LIMIT
+#define silk_LIMIT_16 silk_LIMIT
+#define silk_LIMIT_32 silk_LIMIT
+
+/*#define silk_non_neg(a)                 ((a) & ((-(a)) >> (8 * sizeof(a) - 1)))*/   /* doesn't seem faster than silk_max(0, a);*/
+
+#define silk_abs(a)                       (((a) >  0)  ? (a) : -(a))            /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
+#define silk_abs_int(a)                   (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1)))
+#define silk_abs_int32(a)                 (((a) ^ ((a) >> 31)) - ((a) >> 31))
+#define silk_abs_int64(a)                 (((a) >  0)  ? (a) : -(a))
+
+#define silk_sign(a)                      ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ))
+
+#define silk_sqrt(a)                      (sqrt(a))
+
+/* PSEUDO-RANDOM GENERATOR                                                          */
+/* Make sure to store the result as the seed for the next call (also in between     */
+/* frames), otherwise result won't be random at all. When only using some of the    */
+/* bits, take the most significant bits by right-shifting.                          */
+#define silk_RAND(seed)                   (silk_MLA_ovflw(907633515, (seed), 196314165))
+
+/*  Add some multiplication functions that can be easily mapped to ARM. */
+
+/*    silk_SMMUL: Signed top word multiply.
+          ARMv6        2 instruction cycles.
+          ARMv3M+        3 instruction cycles. use SMULL and ignore LSB registers.(except xM)*/
+/*#define silk_SMMUL(a32, b32)            (opus_int32)silk_RSHIFT(silk_SMLAL(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16)), 16)*/
+/* the following seems faster on x86 */
+#define silk_SMMUL(a32, b32)              (opus_int32)silk_RSHIFT64(silk_SMULL((a32), (b32)), 32)
+
+#include "Inlines.h"
+#include "MacroCount.h"
+#include "MacroDebug.h"
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+++ b/silk/VAD.c
@@ -1,0 +1,325 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include "main.h"
+
+/**********************************/
+/* Initialization of the Silk VAD */
+/**********************************/
+opus_int silk_VAD_Init(                              /* O    Return value, 0 if success                  */
+    silk_VAD_state              *psSilk_VAD         /* I/O  Pointer to Silk VAD state                   */
+)
+{
+    opus_int b, ret = 0;
+
+    /* reset state memory */
+    silk_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) );
+
+    /* init noise levels */
+    /* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */
+    for( b = 0; b < VAD_N_BANDS; b++ ) {
+        psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 );
+    }
+
+    /* Initialize state */
+    for( b = 0; b < VAD_N_BANDS; b++ ) {
+        psSilk_VAD->NL[ b ]     = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] );
+        psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] );
+    }
+    psSilk_VAD->counter = 15;
+
+    /* init smoothed energy-to-noise ratio*/
+    for( b = 0; b < VAD_N_BANDS; b++ ) {
+        psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256;       /* 100 * 256 --> 20 dB SNR */
+    }
+
+    return( ret );
+}
+
+/* Weighting factors for tilt measure */
+static const opus_int32 tiltWeights[ VAD_N_BANDS ] = { 30000, 6000, -12000, -12000 };
+
+/***************************************/
+/* Get the speech activity level in Q8 */
+/***************************************/
+opus_int silk_VAD_GetSA_Q8(                          /* O    Return value, 0 if success                  */
+    silk_encoder_state          *psEncC,            /* I/O  Encoder state                               */
+    const opus_int16             pIn[]               /* I    PCM input                                   */
+)
+{
+    opus_int   SA_Q15, pSNR_dB_Q7, input_tilt;
+    opus_int   decimated_framelength, dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
+    opus_int32 sumSquared, smooth_coef_Q16;
+    opus_int16 HPstateTmp;
+    opus_int16 X[ VAD_N_BANDS ][ MAX_FRAME_LENGTH / 2 ];
+    opus_int32 Xnrg[ VAD_N_BANDS ];
+    opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
+    opus_int32 speech_nrg, x_tmp;
+    opus_int   ret = 0;
+    silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
+
+    /* Safety checks */
+    silk_assert( VAD_N_BANDS == 4 );
+    silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
+    silk_assert( psEncC->frame_length <= 512 );
+    silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
+
+    /***********************/
+    /* Filter and Decimate */
+    /***********************/
+    /* 0-8 kHz to 0-4 kHz and 4-8 kHz */
+    silk_ana_filt_bank_1( pIn,          &psSilk_VAD->AnaState[  0 ], &X[ 0 ][ 0 ], &X[ 3 ][ 0 ], psEncC->frame_length );
+
+    /* 0-4 kHz to 0-2 kHz and 2-4 kHz */
+    silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState1[ 0 ], &X[ 0 ][ 0 ], &X[ 2 ][ 0 ], silk_RSHIFT( psEncC->frame_length, 1 ) );
+
+    /* 0-2 kHz to 0-1 kHz and 1-2 kHz */
+    silk_ana_filt_bank_1( &X[ 0 ][ 0 ], &psSilk_VAD->AnaState2[ 0 ], &X[ 0 ][ 0 ], &X[ 1 ][ 0 ], silk_RSHIFT( psEncC->frame_length, 2 ) );
+
+    /*********************************************/
+    /* HP filter on lowest band (differentiator) */
+    /*********************************************/
+    decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
+    X[ 0 ][ decimated_framelength - 1 ] = silk_RSHIFT( X[ 0 ][ decimated_framelength - 1 ], 1 );
+    HPstateTmp = X[ 0 ][ decimated_framelength - 1 ];
+    for( i = decimated_framelength - 1; i > 0; i-- ) {
+        X[ 0 ][ i - 1 ]  = silk_RSHIFT( X[ 0 ][ i - 1 ], 1 );
+        X[ 0 ][ i ]     -= X[ 0 ][ i - 1 ];
+    }
+    X[ 0 ][ 0 ] -= psSilk_VAD->HPstate;
+    psSilk_VAD->HPstate = HPstateTmp;
+
+    /*************************************/
+    /* Calculate the energy in each band */
+    /*************************************/
+    for( b = 0; b < VAD_N_BANDS; b++ ) {
+        /* Find the decimated framelength in the non-uniformly divided bands */
+        decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) );
+
+        /* Split length into subframe lengths */
+        dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
+        dec_subframe_offset = 0;
+
+        /* Compute energy per sub-frame */
+        /* initialize with summed energy of last subframe */
+        Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
+        for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
+            sumSquared = 0;
+            for( i = 0; i < dec_subframe_length; i++ ) {
+                /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2.            */
+                /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128)  */
+                x_tmp = silk_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 );
+                sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp );
+
+                /* Safety check */
+                silk_assert( sumSquared >= 0 );
+            }
+
+            /* Add/saturate summed energy of current subframe */
+            if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
+                Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
+            } else {
+                /* Look-ahead subframe */
+                Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) );
+            }
+
+            dec_subframe_offset += dec_subframe_length;
+        }
+        psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
+    }
+
+    /********************/
+    /* Noise estimation */
+    /********************/
+    silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );
+
+    /***********************************************/
+    /* Signal-plus-noise to noise ratio estimation */
+    /***********************************************/
+    sumSquared = 0;
+    input_tilt = 0;
+    for( b = 0; b < VAD_N_BANDS; b++ ) {
+        speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
+        if( speech_nrg > 0 ) {
+            /* Divide, with sufficient resolution */
+            if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
+                NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
+            } else {
+                NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
+            }
+
+            /* Convert to log domain */
+            SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;
+
+            /* Sum-of-squares */
+            sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 );          /* Q14 */
+
+            /* Tilt measure */
+            if( speech_nrg < ( 1 << 20 ) ) {
+                /* Scale down SNR value for small subband speech energies */
+                SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
+            }
+            input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
+        } else {
+            NrgToNoiseRatio_Q8[ b ] = 256;
+        }
+    }
+
+    /* Mean-of-squares */
+    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 */
+
+    /*********************************/
+    /* Speech Probability Estimation */
+    /*********************************/
+    SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 );
+
+    /**************************/
+    /* Frequency Tilt Measure */
+    /**************************/
+    psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 );
+
+    /**************************************************/
+    /* Scale the sigmoid output based on power levels */
+    /**************************************************/
+    speech_nrg = 0;
+    for( b = 0; b < VAD_N_BANDS; b++ ) {
+        /* Accumulate signal-without-noise energies, higher frequency bands have more weight */
+        speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
+    }
+
+    /* Power scaling */
+    if( speech_nrg <= 0 ) {
+        SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
+    } else if( speech_nrg < 32768 ) {
+        if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
+            speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
+        } else {
+            speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
+        }
+
+        /* square-root */
+        speech_nrg = silk_SQRT_APPROX( speech_nrg );
+        SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 );
+    }
+
+    /* Copy the resulting speech activity in Q8 */
+    psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX );
+
+    /***********************************/
+    /* Energy Level and SNR estimation */
+    /***********************************/
+    /* Smoothing coefficient */
+    smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( SA_Q15, SA_Q15 ) );
+
+    if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
+        smooth_coef_Q16 >>= 1;
+    }
+
+    for( b = 0; b < VAD_N_BANDS; b++ ) {
+        /* compute smoothed energy-to-noise ratio per band */
+        psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ],
+            NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 );
+
+        /* signal to noise ratio in dB per band */
+        SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 );
+        /* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */
+        psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
+    }
+
+    return( ret );
+}
+
+/**************************/
+/* Noise level estimation */
+/**************************/
+void silk_VAD_GetNoiseLevels(
+    const opus_int32                 pX[ VAD_N_BANDS ],  /* I    subband energies                            */
+    silk_VAD_state              *psSilk_VAD         /* I/O  Pointer to Silk VAD state                   */
+)
+{
+    opus_int   k;
+    opus_int32 nl, nrg, inv_nrg;
+    opus_int   coef, min_coef;
+
+    /* Initially faster smoothing */
+    if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
+        min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
+    } else {
+        min_coef = 0;
+    }
+
+    for( k = 0; k < VAD_N_BANDS; k++ ) {
+        /* Get old noise level estimate for current band */
+        nl = psSilk_VAD->NL[ k ];
+        silk_assert( nl >= 0 );
+
+        /* Add bias */
+        nrg = silk_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] );
+        silk_assert( nrg > 0 );
+
+        /* Invert energies */
+        inv_nrg = silk_DIV32( silk_int32_MAX, nrg );
+        silk_assert( inv_nrg >= 0 );
+
+        /* Less update when subband energy is high */
+        if( nrg > silk_LSHIFT( nl, 3 ) ) {
+            coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3;
+        } else if( nrg < nl ) {
+            coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16;
+        } else {
+            coef = silk_SMULWB( silk_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 );
+        }
+
+        /* Initially faster smoothing */
+        coef = silk_max_int( coef, min_coef );
+
+        /* Smooth inverse energies */
+        psSilk_VAD->inv_NL[ k ] = silk_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef );
+        silk_assert( psSilk_VAD->inv_NL[ k ] >= 0 );
+
+        /* Compute noise level by inverting again */
+        nl = silk_DIV32( silk_int32_MAX, psSilk_VAD->inv_NL[ k ] );
+        silk_assert( nl >= 0 );
+
+        /* Limit noise levels (guarantee 7 bits of head room) */
+        nl = silk_min( nl, 0x00FFFFFF );
+
+        /* Store as part of state */
+        psSilk_VAD->NL[ k ] = nl;
+    }
+
+    /* Increment frame counter */
+    psSilk_VAD->counter++;
+}
--- /dev/null
+++ b/silk/VQ_WMat_EC.c
@@ -1,0 +1,111 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Entropy constrained matrix-weighted VQ, hard-coded to 5-element vectors, for a single input data vector */
+void silk_VQ_WMat_EC(
+    opus_int8                        *ind,               /* O    index of best codebook vector               */
+    opus_int32                       *rate_dist_Q14,     /* O    best weighted quantization error + mu * rate*/
+    const opus_int16                 *in_Q14,            /* I    input vector to be quantized                */
+    const opus_int32                 *W_Q18,             /* I    weighting matrix                            */
+    const opus_int8                  *cb_Q7,             /* I    codebook                                    */
+    const opus_uint8                 *cl_Q5,             /* I    code length for each codebook vector        */
+    const opus_int                   mu_Q9,              /* I    tradeoff between weighted error and rate    */
+    opus_int                         L                   /* I    number of vectors in codebook               */
+)
+{
+    opus_int   k;
+    const opus_int8 *cb_row_Q7;
+    opus_int16 diff_Q14[ 5 ];
+    opus_int32 sum1_Q14, sum2_Q16;
+
+    /* Loop over codebook */
+    *rate_dist_Q14 = silk_int32_MAX;
+    cb_row_Q7 = cb_Q7;
+    for( k = 0; k < L; k++ ) {
+        diff_Q14[ 0 ] = in_Q14[ 0 ] - silk_LSHIFT( cb_row_Q7[ 0 ], 7 );
+        diff_Q14[ 1 ] = in_Q14[ 1 ] - silk_LSHIFT( cb_row_Q7[ 1 ], 7 );
+        diff_Q14[ 2 ] = in_Q14[ 2 ] - silk_LSHIFT( cb_row_Q7[ 2 ], 7 );
+        diff_Q14[ 3 ] = in_Q14[ 3 ] - silk_LSHIFT( cb_row_Q7[ 3 ], 7 );
+        diff_Q14[ 4 ] = in_Q14[ 4 ] - silk_LSHIFT( cb_row_Q7[ 4 ], 7 );
+
+        /* Weighted rate */
+        sum1_Q14 = silk_SMULBB( mu_Q9, cl_Q5[ k ] );
+
+        silk_assert( sum1_Q14 >= 0 );
+
+        /* first row of W_Q18 */
+        sum2_Q16 = silk_SMULWB(           W_Q18[  1 ], diff_Q14[ 1 ] );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[  2 ], diff_Q14[ 2 ] );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[  3 ], diff_Q14[ 3 ] );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[  4 ], diff_Q14[ 4 ] );
+        sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[  0 ], diff_Q14[ 0 ] );
+        sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16,    diff_Q14[ 0 ] );
+
+        /* second row of W_Q18 */
+        sum2_Q16 = silk_SMULWB(           W_Q18[  7 ], diff_Q14[ 2 ] );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[  8 ], diff_Q14[ 3 ] );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[  9 ], diff_Q14[ 4 ] );
+        sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[  6 ], diff_Q14[ 1 ] );
+        sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16,    diff_Q14[ 1 ] );
+
+        /* third row of W_Q18 */
+        sum2_Q16 = silk_SMULWB(           W_Q18[ 13 ], diff_Q14[ 3 ] );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
+        sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
+        sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16,    diff_Q14[ 2 ] );
+
+        /* fourth row of W_Q18 */
+        sum2_Q16 = silk_SMULWB(           W_Q18[ 19 ], diff_Q14[ 4 ] );
+        sum2_Q16 = silk_LSHIFT( sum2_Q16, 1 );
+        sum2_Q16 = silk_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
+        sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16,    diff_Q14[ 3 ] );
+
+        /* last row of W_Q18 */
+        sum2_Q16 = silk_SMULWB(           W_Q18[ 24 ], diff_Q14[ 4 ] );
+        sum1_Q14 = silk_SMLAWB( sum1_Q14, sum2_Q16,    diff_Q14[ 4 ] );
+
+        silk_assert( sum1_Q14 >= 0 );
+
+        /* find best */
+        if( sum1_Q14 < *rate_dist_Q14 ) {
+            *rate_dist_Q14 = sum1_Q14;
+            *ind = (opus_int8)k;
+        }
+
+        /* Go to next cbk vector */
+        cb_row_Q7 += LTP_ORDER;
+    }
+}
--- /dev/null
+++ b/silk/ana_filt_bank_1.c
@@ -1,0 +1,75 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Coefficients for 2-band filter bank based on first-order allpass filters */
+/* old*/
+static opus_int16 A_fb1_20[ 1 ] = {  5394 << 1 };
+static opus_int16 A_fb1_21[ 1 ] = { 20623 << 1 };        /* wrap-around to negative number is intentional */
+
+/* Split signal into two decimated bands using first-order allpass filters */
+void silk_ana_filt_bank_1(
+    const opus_int16      *in,        /* I:   Input signal [N]        */
+    opus_int32            *S,         /* I/O: State vector [2]        */
+    opus_int16            *outL,      /* O:   Low band [N/2]          */
+    opus_int16            *outH,      /* O:   High band [N/2]         */
+    const opus_int32      N           /* I:   Number of input samples */
+)
+{
+    opus_int      k, N2 = silk_RSHIFT( N, 1 );
+    opus_int32    in32, X, Y, out_1, out_2;
+
+    /* Internal variables and state are in Q10 format */
+    for( k = 0; k < N2; k++ ) {
+        /* Convert to Q10 */
+        in32 = silk_LSHIFT( (opus_int32)in[ 2 * k ], 10 );
+
+        /* All-pass section for even input sample */
+        Y      = silk_SUB32( in32, S[ 0 ] );
+        X      = silk_SMLAWB( Y, Y, A_fb1_21[ 0 ] );
+        out_1  = silk_ADD32( S[ 0 ], X );
+        S[ 0 ] = silk_ADD32( in32, X );
+
+        /* Convert to Q10 */
+        in32 = silk_LSHIFT( (opus_int32)in[ 2 * k + 1 ], 10 );
+
+        /* All-pass section for odd input sample, and add to output of previous section */
+        Y      = silk_SUB32( in32, S[ 1 ] );
+        X      = silk_SMULWB( Y, A_fb1_20[ 0 ] );
+        out_2  = silk_ADD32( S[ 1 ], X );
+        S[ 1 ] = silk_ADD32( in32, X );
+
+        /* Add/subtract, convert back to int16 and store to output */
+        outL[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_ADD32( out_2, out_1 ), 11 ) );
+        outH[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SUB32( out_2, out_1 ), 11 ) );
+    }
+}
--- /dev/null
+++ b/silk/apply_sine_window.c
@@ -1,0 +1,101 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Apply sine window to signal vector.                                      */
+/* Window types:                                                            */
+/*    1 -> sine window from 0 to pi/2                                       */
+/*    2 -> sine window from pi/2 to pi                                      */
+/* Every other sample is linearly interpolated, for speed.                  */
+/* Window length must be between 16 and 120 (incl) and a multiple of 4.     */
+
+/* Matlab code for table:
+   for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end
+*/
+static opus_int16 freq_table_Q16[ 27 ] = {
+   12111,    9804,    8235,    7100,    6239,    5565,    5022,    4575,    4202,
+    3885,    3612,    3375,    3167,    2984,    2820,    2674,    2542,    2422,
+    2313,    2214,    2123,    2038,    1961,    1889,    1822,    1760,    1702,
+};
+
+void silk_apply_sine_window(
+    opus_int16                        px_win[],            /* O    Pointer to windowed signal                  */
+    const opus_int16                  px[],                /* I    Pointer to input signal                     */
+    const opus_int                    win_type,            /* I    Selects a window type                       */
+    const opus_int                    length               /* I    Window length, multiple of 4                */
+)
+{
+    opus_int   k, f_Q16, c_Q16;
+    opus_int32 S0_Q16, S1_Q16;
+
+    silk_assert( win_type == 1 || win_type == 2 );
+
+    /* Length must be in a range from 16 to 120 and a multiple of 4 */
+    silk_assert( length >= 16 && length <= 120 );
+    silk_assert( ( length & 3 ) == 0 );
+
+    /* Frequency */
+    k = ( length >> 2 ) - 4;
+    silk_assert( k >= 0 && k <= 26 );
+    f_Q16 = (opus_int)freq_table_Q16[ k ];
+
+    /* Factor used for cosine approximation */
+    c_Q16 = silk_SMULWB( f_Q16, -f_Q16 );
+    silk_assert( c_Q16 >= -32768 );
+
+    /* initialize state */
+    if( win_type == 1 ) {
+        /* start from 0 */
+        S0_Q16 = 0;
+        /* approximation of sin(f) */
+        S1_Q16 = f_Q16 + silk_RSHIFT( length, 3 );
+    } else {
+        /* start from 1 */
+        S0_Q16 = ( 1 << 16 );
+        /* approximation of cos(f) */
+        S1_Q16 = ( 1 << 16 ) + silk_RSHIFT( c_Q16, 1 ) + silk_RSHIFT( length, 4 );
+    }
+
+    /* Uses the recursive equation:   sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f)    */
+    /* 4 samples at a time */
+    for( k = 0; k < length; k += 4 ) {
+        px_win[ k ]     = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] );
+        px_win[ k + 1 ] = (opus_int16)silk_SMULWB( S1_Q16, px[ k + 1] );
+        S0_Q16 = silk_SMULWB( S1_Q16, c_Q16 ) + silk_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1;
+        S0_Q16 = silk_min( S0_Q16, ( 1 << 16 ) );
+
+        px_win[ k + 2 ] = (opus_int16)silk_SMULWB( silk_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] );
+        px_win[ k + 3 ] = (opus_int16)silk_SMULWB( S0_Q16, px[ k + 3 ] );
+        S1_Q16 = silk_SMULWB( S0_Q16, c_Q16 ) + silk_LSHIFT( S0_Q16, 1 ) - S1_Q16;
+        S1_Q16 = silk_min( S1_Q16, ( 1 << 16 ) );
+    }
+}
--- /dev/null
+++ b/silk/array_maxabs.c
@@ -1,0 +1,64 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Function that returns the maximum absolut value of the input vector */
+opus_int16 silk_int16_array_maxabs(          /* O    Maximum absolute value, max: 2^15-1   */
+    const opus_int16        *vec,            /* I    Input vector  [len]                   */
+    const opus_int32        len              /* I    Length of input vector                */
+)
+{
+    opus_int32 max = 0, i, lvl = 0, ind;
+    if( len == 0 ) return 0;
+
+    ind = len - 1;
+    max = silk_SMULBB( vec[ ind ], vec[ ind ] );
+    for( i = len - 2; i >= 0; i-- ) {
+        lvl = silk_SMULBB( vec[ i ], vec[ i ] );
+        if( lvl > max ) {
+            max = lvl;
+            ind = i;
+        }
+    }
+
+    /* Do not return 32768, as it will not fit in an int16 so may lead to problems later on */
+    if( max >= 1073676289 ) { /* (2^15-1)^2 = 1073676289*/
+        return( silk_int16_MAX );
+    } else {
+        if( vec[ ind ] < 0 ) {
+            return( -vec[ ind ] );
+        } else {
+            return(  vec[ ind ] );
+        }
+    }
+}
+
--- /dev/null
+++ b/silk/autocorr.c
@@ -1,0 +1,76 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Compute autocorrelation */
+void silk_autocorr(
+    opus_int32        *results,                   /* O    Result (length correlationCount)            */
+    opus_int          *scale,                     /* O    Scaling of the correlation vector           */
+    const opus_int16  *inputData,                 /* I    Input data to correlate                     */
+    const opus_int    inputDataSize,              /* I    Length of input                             */
+    const opus_int    correlationCount            /* I    Number of correlation taps to compute       */
+)
+{
+    opus_int   i, lz, nRightShifts, corrCount;
+    opus_int64 corr64;
+
+    corrCount = silk_min_int( inputDataSize, correlationCount );
+
+    /* compute energy (zero-lag correlation) */
+    corr64 = silk_inner_prod16_aligned_64( inputData, inputData, inputDataSize );
+
+    /* deal with all-zero input data */
+    corr64 += 1;
+
+    /* number of leading zeros */
+    lz = silk_CLZ64( corr64 );
+
+    /* scaling: number of right shifts applied to correlations */
+    nRightShifts = 35 - lz;
+    *scale = nRightShifts;
+
+    if( nRightShifts <= 0 ) {
+        results[ 0 ] = silk_LSHIFT( (opus_int32)silk_CHECK_FIT32( corr64 ), -nRightShifts );
+
+        /* compute remaining correlations based on int32 inner product */
+          for( i = 1; i < corrCount; i++ ) {
+            results[ i ] = silk_LSHIFT( silk_inner_prod_aligned( inputData, inputData + i, inputDataSize - i ), -nRightShifts );
+        }
+    } else {
+        results[ 0 ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr64, nRightShifts ) );
+
+        /* compute remaining correlations based on int64 inner product */
+          for( i = 1; i < corrCount; i++ ) {
+            results[ i ] =  (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( silk_inner_prod16_aligned_64( inputData, inputData + i, inputDataSize - i ), nRightShifts ) );
+        }
+    }
+}
--- /dev/null
+++ b/silk/biquad_alt.c
@@ -1,0 +1,79 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+/*                                                                      *
+ * silk_biquad_alt.c                                              *
+ *                                                                      *
+ * Second order ARMA filter                                             *
+ * Can handle slowly varying filter coefficients                        *
+ *                                                                      */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+
+/* Second order ARMA filter, alternative implementation */
+void silk_biquad_alt(
+    const opus_int16      *in,            /* I:    Input signal                   */
+    const opus_int32      *B_Q28,         /* I:    MA coefficients [3]            */
+    const opus_int32      *A_Q28,         /* I:    AR coefficients [2]            */
+    opus_int32            *S,             /* I/O:  State vector [2]               */
+    opus_int16            *out,           /* O:    Output signal                  */
+    const opus_int32      len,            /* I:    Signal length (must be even)   */
+    int stride
+)
+{
+    /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+    opus_int   k;
+    opus_int32 inval, A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14;
+
+    /* Negate A_Q28 values and split in two parts */
+    A0_L_Q28 = ( -A_Q28[ 0 ] ) & 0x00003FFF;        /* lower part */
+    A0_U_Q28 = silk_RSHIFT( -A_Q28[ 0 ], 14 );       /* upper part */
+    A1_L_Q28 = ( -A_Q28[ 1 ] ) & 0x00003FFF;        /* lower part */
+    A1_U_Q28 = silk_RSHIFT( -A_Q28[ 1 ], 14 );       /* upper part */
+
+    for( k = 0; k < len; k++ ) {
+        /* S[ 0 ], S[ 1 ]: Q12 */
+        inval = in[ k*stride ];
+        out32_Q14 = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], inval ), 2 );
+
+        S[ 0 ] = S[1] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A0_L_Q28 ), 14 );
+        S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14, A0_U_Q28 );
+        S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], inval);
+
+        S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14, A1_L_Q28 ), 14 );
+        S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14, A1_U_Q28 );
+        S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], inval );
+
+        /* Scale back to Q0 and saturate */
+        out[ k*stride ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
+    }
+}
--- /dev/null
+++ b/silk/burg_modified.c
@@ -1,0 +1,222 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.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
+#define MIN_RSHIFTS                 -16
+#define MAX_RSHIFTS                 (32 - QA)
+
+/* Compute reflection coefficients from input signal */
+void silk_burg_modified(
+    opus_int32       *res_nrg,           /* O    residual energy                                                 */
+    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_int   subfr_length,       /* I    input signal subframe length (including 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;
+    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 );
+    if( rshifts > MAX_RSHIFTS ) {
+        C0 = silk_LSHIFT32( C0, rshifts - MAX_RSHIFTS );
+        silk_assert( C0 > 0 );
+        rshifts = MAX_RSHIFTS;
+    } else {
+        lz = silk_CLZ32( C0 ) - 1;
+        rshifts_extra = N_BITS_HEAD_ROOM - lz;
+        if( rshifts_extra > 0 ) {
+            rshifts_extra = silk_min( rshifts_extra, MAX_RSHIFTS - rshifts );
+            C0 = silk_RSHIFT32( C0, rshifts_extra );
+        } else {
+            rshifts_extra = silk_max( rshifts_extra, MIN_RSHIFTS - rshifts );
+            C0 = silk_LSHIFT32( C0, -rshifts_extra );
+        }
+        rshifts += rshifts_extra;
+    }
+    silk_memset( C_first_row, 0, SILK_MAX_ORDER_LPC * sizeof( opus_int32 ) );
+    if( rshifts > 0 ) {
+        for( s = 0; s < nb_subfr; s++ ) {
+            x_ptr = x + s * subfr_length;
+            for( n = 1; n < D + 1; n++ ) {
+                C_first_row[ n - 1 ] += (opus_int32)silk_RSHIFT64(
+                    silk_inner_prod16_aligned_64( x_ptr, x_ptr + n, subfr_length - n ), rshifts );
+            }
+        }
+    } else {
+        for( s = 0; s < nb_subfr; s++ ) {
+            x_ptr = x + s * subfr_length;
+            for( n = 1; n < D + 1; n++ ) {
+                C_first_row[ n - 1 ] += silk_LSHIFT32(
+                    silk_inner_prod_aligned( x_ptr, x_ptr + n, subfr_length - n ), -rshifts );
+            }
+        }
+    }
+    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)*/
+
+    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) */
+        /* Update C * Af */
+        /* Update C * flipud(Af) (stored in reversed order) */
+        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)*/
+                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 )*/
+                    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_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 )*/
+                }
+            }
+        } 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*/
+                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*/
+                }
+                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 )*/
+                    CAb[ k ] = silk_SMLAWW( CAb[ k ], tmp2,
+                        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 )*/
+        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 )*/
+
+            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 )*/
+        }
+        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;
+        }
+
+        /* 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*/
+        }
+        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 )*/
+        }
+    }
+
+    /* 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;
+}
--- /dev/null
+++ b/silk/bwexpander.c
@@ -1,0 +1,51 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander(
+    opus_int16            *ar,        /* I/O  AR filter to be expanded (without leading 1)    */
+    const opus_int        d,          /* I    Length of ar                                    */
+    opus_int32            chirp_Q16   /* I    Chirp factor (typically in the range 0 to 1)    */
+)
+{
+    opus_int   i;
+    opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536;
+
+    /* NB: Dont use silk_SMULWB, instead of silk_RSHIFT_ROUND( silk_MUL(), 16 ), below.  */
+    /* Bias in silk_SMULWB can lead to unstable filters                                */
+    for( i = 0; i < d - 1; i++ ) {
+        ar[ i ]    = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ i ]             ), 16 );
+        chirp_Q16 +=            silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
+    }
+    ar[ d - 1 ] = (opus_int16)silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, ar[ d - 1 ] ), 16 );
+}
--- /dev/null
+++ b/silk/bwexpander_32.c
@@ -1,0 +1,50 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Chirp (bandwidth expand) LP AR filter */
+void silk_bwexpander_32(
+    opus_int32        *ar,       /* I/O  AR filter to be expanded (without leading 1)    */
+    const opus_int    d,         /* I    Length of ar                                    */
+    opus_int32        chirp_Q16  /* I    Chirp factor in Q16                             */
+)
+{
+    opus_int   i;
+    opus_int32 chirp_minus_one_Q16 = chirp_Q16 - 65536;
+
+    for( i = 0; i < d - 1; i++ ) {
+        ar[ i ]    = silk_SMULWW( chirp_Q16, ar[ i ] );
+        chirp_Q16 += silk_RSHIFT_ROUND( silk_MUL( chirp_Q16, chirp_minus_one_Q16 ), 16 );
+    }
+    ar[ d - 1 ] = silk_SMULWW( chirp_Q16, ar[ d - 1 ] );
+}
+
--- /dev/null
+++ b/silk/check_control_input.c
@@ -1,0 +1,106 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "control.h"
+#include "errors.h"
+
+/* Check encoder control struct */
+opus_int check_control_input(
+    silk_EncControlStruct        *encControl     /* I:   Control structure                               */
+)
+{
+    silk_assert( encControl != NULL );
+
+    if( ( ( encControl->API_sampleRate            !=  8000 ) &&
+          ( encControl->API_sampleRate            != 12000 ) &&
+          ( encControl->API_sampleRate            != 16000 ) &&
+          ( encControl->API_sampleRate            != 24000 ) &&
+          ( encControl->API_sampleRate            != 32000 ) &&
+          ( encControl->API_sampleRate            != 44100 ) &&
+          ( encControl->API_sampleRate            != 48000 ) ) ||
+        ( ( encControl->desiredInternalSampleRate !=  8000 ) &&
+          ( encControl->desiredInternalSampleRate != 12000 ) &&
+          ( encControl->desiredInternalSampleRate != 16000 ) ) ||
+        ( ( encControl->maxInternalSampleRate     !=  8000 ) &&
+          ( encControl->maxInternalSampleRate     != 12000 ) &&
+          ( encControl->maxInternalSampleRate     != 16000 ) ) ||
+        ( ( encControl->minInternalSampleRate     !=  8000 ) &&
+          ( encControl->minInternalSampleRate     != 12000 ) &&
+          ( encControl->minInternalSampleRate     != 16000 ) ) ||
+          ( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) ||
+          ( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) ||
+          ( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) {
+        silk_assert( 0 );
+        return SILK_ENC_FS_NOT_SUPPORTED;
+    }
+    if( encControl->payloadSize_ms != 10 &&
+        encControl->payloadSize_ms != 20 &&
+        encControl->payloadSize_ms != 40 &&
+        encControl->payloadSize_ms != 60 ) {
+        silk_assert( 0 );
+        return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
+    }
+    if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) {
+        silk_assert( 0 );
+        return SILK_ENC_INVALID_LOSS_RATE;
+    }
+    if( encControl->useDTX < 0 || encControl->useDTX > 1 ) {
+        silk_assert( 0 );
+        return SILK_ENC_INVALID_DTX_SETTING;
+    }
+    if( encControl->useCBR < 0 || encControl->useCBR > 1 ) {
+        silk_assert( 0 );
+        return SILK_ENC_INVALID_CBR_SETTING;
+    }
+    if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) {
+        silk_assert( 0 );
+        return SILK_ENC_INVALID_INBAND_FEC_SETTING;
+    }
+    if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) {
+        silk_assert( 0 );
+        return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
+    }
+    if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) {
+        silk_assert( 0 );
+        return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
+    }
+    if( encControl->nChannelsInternal > encControl->nChannelsAPI ) {
+        silk_assert( 0 );
+        return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
+    }
+    if( encControl->complexity < 0 || encControl->complexity > 10 ) {
+        silk_assert( 0 );
+        return SILK_ENC_INVALID_COMPLEXITY_SETTING;
+    }
+
+    return SILK_NO_ERROR;
+}
--- /dev/null
+++ b/silk/code_signs.c
@@ -1,0 +1,115 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/*#define silk_enc_map(a)                ((a) > 0 ? 1 : 0)*/
+/*#define silk_dec_map(a)                ((a) > 0 ? 1 : -1)*/
+/* shifting avoids if-statement */
+#define silk_enc_map(a)                  ( silk_RSHIFT( (a), 15 ) + 1 )
+#define silk_dec_map(a)                  ( silk_LSHIFT( (a),  1 ) - 1 )
+
+/* Encodes signs of excitation */
+void silk_encode_signs(
+    ec_enc                      *psRangeEnc,                        /* I/O  Compressor data structure                   */
+    const opus_int8              pulses[],                           /* I    pulse signal                                */
+    opus_int                     length,                             /* I    length of input                             */
+    const opus_int               signalType,                         /* I    Signal type                                 */
+    const opus_int               quantOffsetType,                    /* I    Quantization offset type                    */
+    const opus_int               sum_pulses[ MAX_NB_SHELL_BLOCKS ]   /* I    Sum of absolute pulses per block            */
+)
+{
+    opus_int         i, j, p;
+    opus_uint8       icdf[ 2 ];
+    const opus_int8  *q_ptr;
+    const opus_uint8 *icdf_ptr;
+
+    icdf[ 1 ] = 0;
+    q_ptr = pulses;
+    i = silk_SMULBB( 6, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
+    icdf_ptr = &silk_sign_iCDF[ i ];
+    length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
+    for( i = 0; i < length; i++ ) {
+        p = sum_pulses[ i ];
+        if( p > 0 ) {
+            icdf[ 0 ] = icdf_ptr[ silk_min( p - 1, 5 ) ];
+            for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
+                if( q_ptr[ j ] != 0 ) {
+                    ec_enc_icdf( psRangeEnc, silk_enc_map( q_ptr[ j ]), icdf, 8 );
+                }
+            }
+        }
+        q_ptr += SHELL_CODEC_FRAME_LENGTH;
+    }
+}
+
+/* Decodes signs of excitation */
+void silk_decode_signs(
+    ec_dec                      *psRangeDec,                        /* I/O  Compressor data structure                   */
+    opus_int                     pulses[],                           /* I/O  pulse signal                                */
+    opus_int                     length,                             /* I    length of input                             */
+    const opus_int               signalType,                         /* I    Signal type                                 */
+    const opus_int               quantOffsetType,                    /* I    Quantization offset type                    */
+    const opus_int               sum_pulses[ MAX_NB_SHELL_BLOCKS ]   /* I    Sum of absolute pulses per block            */
+)
+{
+    opus_int         i, j, p;
+    opus_uint8       icdf[ 2 ];
+    opus_int         *q_ptr;
+    const opus_uint8 *icdf_ptr;
+
+    icdf[ 1 ] = 0;
+    q_ptr = pulses;
+    i = silk_SMULBB( 6, silk_ADD_LSHIFT( quantOffsetType, signalType, 1 ) );
+    icdf_ptr = &silk_sign_iCDF[ i ];
+    length = silk_RSHIFT( length + SHELL_CODEC_FRAME_LENGTH/2, LOG2_SHELL_CODEC_FRAME_LENGTH );
+    for( i = 0; i < length; i++ ) {
+        p = sum_pulses[ i ];
+        if( p > 0 ) {
+            icdf[ 0 ] = icdf_ptr[ silk_min( p - 1, 5 ) ];
+            for( j = 0; j < SHELL_CODEC_FRAME_LENGTH; j++ ) {
+                if( q_ptr[ j ] > 0 ) {
+                    /* attach sign */
+#if 0
+                    /* conditional implementation */
+                    if( ec_dec_icdf( psRangeDec, icdf, 8 ) == 0 ) {
+                        q_ptr[ j ] = -q_ptr[ j ];
+                    }
+#else
+                    /* implementation with shift, subtraction, multiplication */
+                    q_ptr[ j ] *= silk_dec_map( ec_dec_icdf( psRangeDec, icdf, 8 ) );
+#endif
+                }
+            }
+        }
+        q_ptr += SHELL_CODEC_FRAME_LENGTH;
+    }
+}
--- /dev/null
+++ b/silk/control.h
@@ -1,0 +1,123 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_CONTROL_H
+#define SILK_CONTROL_H
+
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Decoder API flags */
+#define FLAG_DECODE_NORMAL                      0
+#define FLAG_PACKET_LOST                        1
+#define FLAG_DECODE_LBRR                        2
+
+/***********************************************/
+/* Structure for controlling encoder operation */
+/***********************************************/
+typedef struct {
+    /* I:   Number of channels; 1/2                                                         */
+    opus_int32 nChannelsAPI;
+
+    /* I:   Number of channels; 1/2                                                         */
+    opus_int32 nChannelsInternal;
+
+    /* I:   Input signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000   */
+    opus_int32 API_sampleRate;
+
+    /* I:   Maximum internal sampling rate in Hertz; 8000/12000/16000                       */
+    opus_int32 maxInternalSampleRate;
+
+    /* I:   Minimum internal sampling rate in Hertz; 8000/12000/16000                       */
+    opus_int32 minInternalSampleRate;
+
+    /* I:   Soft request for internal sampling rate in Hertz; 8000/12000/16000              */
+    opus_int32 desiredInternalSampleRate;
+
+    /* I:   Number of samples per packet in milliseconds; 10/20/40/60                       */
+    opus_int payloadSize_ms;
+
+    /* I:   Bitrate during active speech in bits/second; internally limited                 */
+    opus_int32 bitRate;
+
+    /* I:   Uplink packet loss in percent (0-100)                                           */
+    opus_int packetLossPercentage;
+
+    /* I:   Complexity mode; 0 is lowest, 10 is highest complexity                          */
+    opus_int complexity;
+
+    /* I:   Flag to enable in-band Forward Error Correction (FEC); 0/1                      */
+    opus_int useInBandFEC;
+
+    /* I:   Flag to enable discontinuous transmission (DTX); 0/1                            */
+    opus_int useDTX;
+
+    /* I:   Flag to use constant bitrate                                                    */
+    opus_int useCBR;
+
+    /* O:   Internal sampling rate used, in Hertz; 8000/12000/16000                         */
+    opus_int32 internalSampleRate;
+
+    /* O: Flag that bandwidth switching is allowed (because low voice activity)             */
+    opus_int allowBandwidthSwitch;
+
+    /* O:   Flag that SILK runs in WB mode without variable LP filter (use for switching between WB/SWB/FB) */
+    opus_int inWBmodeWithoutVariableLP;
+
+    /* O:   Stereo width */
+    opus_int stereoWidth_Q14;
+} silk_EncControlStruct;
+
+/**************************************************************************/
+/* Structure for controlling decoder operation and reading decoder status */
+/**************************************************************************/
+typedef struct {
+    /* I:   Number of channels; 1/2                                                         */
+    opus_int32 nChannelsAPI;
+
+    /* I:   Number of channels; 1/2                                                         */
+    opus_int32 nChannelsInternal;
+
+    /* I:   Output signal sampling rate in Hertz; 8000/12000/16000/24000/32000/44100/48000  */
+    opus_int32 API_sampleRate;
+
+    /* I:   Internal sampling rate used, in Hertz; 8000/12000/16000                         */
+    opus_int32 internalSampleRate;
+
+    /* I:   Number of samples per packet in milliseconds; 10/20/40/60                       */
+    opus_int payloadSize_ms;
+} silk_DecControlStruct;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+++ b/silk/control_SNR.c
@@ -1,0 +1,81 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "tuning_parameters.h"
+
+/* Control SNR of redidual quantizer */
+opus_int silk_control_SNR(
+    silk_encoder_state          *psEncC,            /* I/O  Pointer to Silk encoder state               */
+    opus_int32                   TargetRate_bps      /* I    Target max bitrate (bps)                    */
+)
+{
+    opus_int k, ret = SILK_NO_ERROR;
+    opus_int32 frac_Q6;
+    const opus_int32 *rateTable;
+
+    /* Set bitrate/coding quality */
+    TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
+    if( TargetRate_bps != psEncC->TargetRate_bps ) {
+        psEncC->TargetRate_bps = TargetRate_bps;
+
+        /* If new TargetRate_bps, translate to SNR_dB value */
+        if( psEncC->fs_kHz == 8 ) {
+            rateTable = silk_TargetRate_table_NB;
+        } else if( psEncC->fs_kHz == 12 ) {
+            rateTable = silk_TargetRate_table_MB;
+        } else {
+            rateTable = silk_TargetRate_table_WB;
+        }
+
+        /* Reduce bitrate for 10 ms modes in these calculations */
+        if( psEncC->nb_subfr == 2 ) {
+            TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;
+        }
+
+        /* Find bitrate interval in table and interpolate */
+        for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {
+            if( TargetRate_bps <= rateTable[ k ] ) {
+                frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ),
+                                                 rateTable[ k ] - rateTable[ k - 1 ] );
+                psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] );
+                break;
+            }
+        }
+
+        /* Reduce coding quality whenever LBRR is enabled, to free up some bits */
+        if( psEncC->LBRR_enabled ) {
+            psEncC->SNR_dB_Q7 = silk_SMLABB( psEncC->SNR_dB_Q7, 12 - psEncC->LBRR_GainIncreases, SILK_FIX_CONST( -0.25, 7 ) );
+        }
+    }
+
+    return ret;
+}
--- /dev/null
+++ b/silk/control_audio_bandwidth.c
@@ -1,0 +1,110 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "tuning_parameters.h"
+
+/* Control internal sampling rate */
+opus_int silk_control_audio_bandwidth(
+    silk_encoder_state      *psEncC             /* I/O  Pointer to Silk encoder state               */
+)
+{
+    opus_int   fs_kHz;
+    opus_int32 fs_Hz;
+
+    fs_kHz = psEncC->fs_kHz;
+    fs_Hz = silk_SMULBB( fs_kHz, 1000 );
+    if( fs_Hz == 0 ) {
+        /* Encoder has just been initialized */
+        fs_Hz  = silk_min( psEncC->desiredInternal_fs_Hz, psEncC->API_fs_Hz );
+        fs_kHz = silk_DIV32_16( fs_Hz, 1000 );
+    } else if( fs_Hz > psEncC->API_fs_Hz || fs_Hz > psEncC->maxInternal_fs_Hz || fs_Hz < psEncC->minInternal_fs_Hz ) {
+        /* Make sure internal rate is not higher than external rate or maximum allowed, or lower than minimum allowed */
+        fs_Hz  = psEncC->API_fs_Hz;
+        fs_Hz  = silk_min( fs_Hz, psEncC->maxInternal_fs_Hz );
+        fs_Hz  = silk_max( fs_Hz, psEncC->minInternal_fs_Hz );
+        fs_kHz = silk_DIV32_16( fs_Hz, 1000 );
+    } else {
+        /* State machine for the internal sampling rate switching */
+        if( psEncC->sLP.transition_frame_no >= TRANSITION_FRAMES ) {
+            /* Stop transition phase */
+            psEncC->sLP.mode = 0;
+        }
+        if( psEncC->allow_bandwidth_switch ) {
+            /* Check if we should switch down */
+            if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
+            {
+                /* Switch down */
+                if( psEncC->sLP.mode == 0 ) {
+                    /* New transition */
+                    psEncC->sLP.transition_frame_no = TRANSITION_FRAMES;
+
+                    /* Reset transition filter state */
+                    silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) );
+                }
+                if( psEncC->sLP.transition_frame_no <= 0 ) {
+                    /* Stop transition phase */
+                    psEncC->sLP.mode = 0;
+
+                    /* Switch to a lower sample frequency */
+                    fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8;
+                } else {
+                    /* Direction: down (at double speed) */
+                    psEncC->sLP.mode = -2;
+                }
+            }
+            else
+            /* Check if we should switch up */
+            if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
+            {
+                /* Switch up */
+                if( psEncC->sLP.mode == 0 ) {
+                    /* Switch to a higher sample frequency */
+                    fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16;
+
+                    /* New transition */
+                    psEncC->sLP.transition_frame_no = 0;
+
+                    /* Reset transition filter state */
+                    silk_memset( psEncC->sLP.In_LP_State, 0, sizeof( psEncC->sLP.In_LP_State ) );
+                }
+                /* Direction: up */
+                psEncC->sLP.mode = 1;
+            }
+        }
+    }
+
+#ifdef FORCE_INTERNAL_FS_KHZ
+    fs_kHz = FORCE_INTERNAL_FS_KHZ;
+#endif
+
+    return fs_kHz;
+}
--- /dev/null
+++ b/silk/control_codec.c
@@ -1,0 +1,423 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#ifdef FIXED_POINT
+#include "main_FIX.h"
+#define silk_encoder_state_Fxx      silk_encoder_state_FIX
+#else
+#include "main_FLP.h"
+#define silk_encoder_state_Fxx      silk_encoder_state_FLP
+#endif
+#include "tuning_parameters.h"
+
+opus_int silk_setup_resamplers(
+    silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
+    opus_int                         fs_kHz              /* I                        */
+);
+
+opus_int silk_setup_fs(
+    silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
+    opus_int                         fs_kHz,             /* I                        */
+    opus_int                         PacketSize_ms       /* I                        */
+);
+
+opus_int silk_setup_complexity(
+    silk_encoder_state              *psEncC,            /* I/O                      */
+    opus_int                         Complexity          /* I                        */
+);
+
+static inline opus_int silk_setup_LBRR(
+    silk_encoder_state              *psEncC,            /* I/O                      */
+    const opus_int32                 TargetRate_bps      /* I                        */
+);
+
+
+/* Control encoder */
+opus_int silk_control_encoder(
+    silk_encoder_state_Fxx          *psEnc,             /* I/O  Pointer to Silk encoder state           */
+    silk_EncControlStruct           *encControl,        /* I:   Control structure                       */
+    const opus_int32                 TargetRate_bps,     /* I    Target max bitrate (bps)                */
+    const opus_int                   allow_bw_switch,    /* I    Flag to allow switching audio bandwidth */
+    const opus_int                   channelNb,           /* I    Channel number                          */
+    const opus_int                   force_fs_kHz
+)
+{
+    opus_int   fs_kHz, ret = 0;
+
+    psEnc->sCmn.useDTX                 = encControl->useDTX;
+    psEnc->sCmn.useCBR                 = encControl->useCBR;
+    psEnc->sCmn.API_fs_Hz              = encControl->API_sampleRate;
+    psEnc->sCmn.maxInternal_fs_Hz      = encControl->maxInternalSampleRate;
+    psEnc->sCmn.minInternal_fs_Hz      = encControl->minInternalSampleRate;
+    psEnc->sCmn.desiredInternal_fs_Hz  = encControl->desiredInternalSampleRate;
+    psEnc->sCmn.useInBandFEC           = encControl->useInBandFEC;
+    psEnc->sCmn.nChannelsAPI           = encControl->nChannelsAPI;
+    psEnc->sCmn.nChannelsInternal      = encControl->nChannelsInternal;
+    psEnc->sCmn.allow_bandwidth_switch = allow_bw_switch;
+    psEnc->sCmn.channelNb              = channelNb;
+
+    if( psEnc->sCmn.controlled_since_last_payload != 0 && psEnc->sCmn.prefillFlag == 0 ) {
+        if( psEnc->sCmn.API_fs_Hz != psEnc->sCmn.prev_API_fs_Hz && psEnc->sCmn.fs_kHz > 0 ) {
+            /* Change in API sampling rate in the middle of encoding a packet */
+            ret += silk_setup_resamplers( psEnc, psEnc->sCmn.fs_kHz );
+        }
+        return ret;
+    }
+
+    /* Beyond this point we know that there are no previously coded frames in the payload buffer */
+
+    /********************************************/
+    /* Determine internal sampling rate         */
+    /********************************************/
+    fs_kHz = silk_control_audio_bandwidth( &psEnc->sCmn );
+    if (force_fs_kHz)
+       fs_kHz = force_fs_kHz;
+    /********************************************/
+    /* Prepare resampler and buffered data      */
+    /********************************************/
+    ret += silk_setup_resamplers( psEnc, fs_kHz );
+
+    /********************************************/
+    /* Set internal sampling frequency          */
+    /********************************************/
+    ret += silk_setup_fs( psEnc, fs_kHz, encControl->payloadSize_ms );
+
+    /********************************************/
+    /* Set encoding complexity                  */
+    /********************************************/
+    ret += silk_setup_complexity( &psEnc->sCmn, encControl->complexity  );
+
+    /********************************************/
+    /* Set packet loss rate measured by farend  */
+    /********************************************/
+    psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage;
+
+    /********************************************/
+    /* Set LBRR usage                           */
+    /********************************************/
+    ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps );
+
+    psEnc->sCmn.controlled_since_last_payload = 1;
+
+    return ret;
+}
+
+opus_int silk_setup_resamplers(
+    silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
+    opus_int                         fs_kHz              /* I                        */
+)
+{
+    opus_int   ret = SILK_NO_ERROR;
+    opus_int32 nSamples_temp;
+
+    if( psEnc->sCmn.fs_kHz != fs_kHz || psEnc->sCmn.prev_API_fs_Hz != psEnc->sCmn.API_fs_Hz )
+    {
+        if( psEnc->sCmn.fs_kHz == 0 ) {
+            /* Initialize the resampler for enc_API.c preparing resampling from API_fs_Hz to fs_kHz */
+            ret += silk_resampler_init( &psEnc->sCmn.resampler_state, psEnc->sCmn.API_fs_Hz, fs_kHz * 1000 );
+        } 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 ];
+#ifdef FIXED_POINT
+            opus_int16 *x_bufFIX = psEnc->x_buf;
+#else
+            opus_int16 x_bufFIX[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];
+#endif
+
+            nSamples_temp = silk_LSHIFT( psEnc->sCmn.frame_length, 1 ) + LA_SHAPE_MS * psEnc->sCmn.fs_kHz;
+
+#ifndef FIXED_POINT
+            silk_float2short_array( x_bufFIX, psEnc->x_buf, nSamples_temp );
+#endif
+
+            if( silk_SMULBB( fs_kHz, 1000 ) < psEnc->sCmn.API_fs_Hz && psEnc->sCmn.fs_kHz != 0 ) {
+                /* Resample buffered data in x_buf to API_fs_Hz */
+
+                silk_resampler_state_struct  temp_resampler_state;
+
+                /* 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 );
+
+                /* Temporary resampling of x_buf data to API_fs_Hz */
+                ret += silk_resampler( &temp_resampler_state, x_buf_API_fs_Hz, x_bufFIX, nSamples_temp );
+
+                /* Calculate number of samples that has been temporarily upsampled */
+                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 ) );
+
+            } else {
+                /* Copy data */
+                silk_memcpy( x_buf_API_fs_Hz, x_bufFIX, nSamples_temp * sizeof( opus_int16 ) );
+            }
+
+            if( 1000 * fs_kHz != psEnc->sCmn.API_fs_Hz ) {
+                /* Correct resampler state (unless resampling by a factor 1) 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 );
+            }
+#ifndef FIXED_POINT
+            silk_short2float_array( psEnc->x_buf, x_bufFIX, ( 2 * MAX_FRAME_LENGTH_MS + LA_SHAPE_MS ) * fs_kHz );
+#endif
+        }
+    }
+
+    psEnc->sCmn.prev_API_fs_Hz = psEnc->sCmn.API_fs_Hz;
+
+    return ret;
+}
+
+opus_int silk_setup_fs(
+    silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
+    opus_int                         fs_kHz,             /* I                        */
+    opus_int                         PacketSize_ms       /* I                        */
+)
+{
+    opus_int ret = SILK_NO_ERROR;
+
+    /* Set packet size */
+    if( PacketSize_ms != psEnc->sCmn.PacketSize_ms ) {
+        if( ( PacketSize_ms !=  10 ) &&
+            ( PacketSize_ms !=  20 ) &&
+            ( PacketSize_ms !=  40 ) &&
+            ( PacketSize_ms !=  60 ) ) {
+            ret = SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
+        }
+        if( PacketSize_ms <= 10 ) {
+            psEnc->sCmn.nFramesPerPacket = 1;
+            psEnc->sCmn.nb_subfr = PacketSize_ms == 10 ? 2 : 1;
+            psEnc->sCmn.frame_length = silk_SMULBB( PacketSize_ms, fs_kHz );
+            psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
+            if( psEnc->sCmn.fs_kHz == 8 ) {
+                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
+            } else {
+                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
+            }
+        } else {
+            psEnc->sCmn.nFramesPerPacket = silk_DIV32_16( PacketSize_ms, MAX_FRAME_LENGTH_MS );
+            psEnc->sCmn.nb_subfr = MAX_NB_SUBFR;
+            psEnc->sCmn.frame_length = silk_SMULBB( 20, fs_kHz );
+            psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );
+            if( psEnc->sCmn.fs_kHz == 8 ) {
+                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
+            } else {
+                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF;
+            }
+        }
+        psEnc->sCmn.PacketSize_ms  = PacketSize_ms;
+        psEnc->sCmn.TargetRate_bps = 0;         /* trigger new SNR computation */
+    }
+
+    /* 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 );
+    if( psEnc->sCmn.fs_kHz != fs_kHz ) {
+        /* reset part of the state */
+#ifdef FIXED_POINT
+        silk_memset( &psEnc->sShape,               0, sizeof( silk_shape_state_FIX ) );
+        silk_memset( &psEnc->sPrefilt,             0, sizeof( silk_prefilter_state_FIX ) );
+#else
+        silk_memset( &psEnc->sShape,               0, sizeof( silk_shape_state_FLP ) );
+        silk_memset( &psEnc->sPrefilt,             0, sizeof( silk_prefilter_state_FLP ) );
+#endif
+        silk_memset( &psEnc->sCmn.sNSQ,            0, sizeof( silk_nsq_state ) );
+        silk_memset( psEnc->sCmn.prev_NLSFq_Q15,   0, sizeof( psEnc->sCmn.prev_NLSFq_Q15 ) );
+        silk_memset( &psEnc->sCmn.sLP.In_LP_State, 0, sizeof( psEnc->sCmn.sLP.In_LP_State ) );
+        psEnc->sCmn.inputBufIx                  = 0;
+        psEnc->sCmn.nFramesEncoded              = 0;
+        psEnc->sCmn.TargetRate_bps              = 0;     /* trigger new SNR computation */
+
+        /* Initialize non-zero parameters */
+        psEnc->sCmn.prevLag                     = 100;
+        psEnc->sCmn.first_frame_after_reset     = 1;
+        psEnc->sPrefilt.lagPrev                 = 100;
+        psEnc->sShape.LastGainIndex             = 10;
+        psEnc->sCmn.sNSQ.lagPrev                = 100;
+        psEnc->sCmn.sNSQ.prev_inv_gain_Q16      = 65536;
+
+        psEnc->sCmn.fs_kHz = fs_kHz;
+        if( psEnc->sCmn.fs_kHz == 8 ) {
+            if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
+                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
+            } else {
+                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
+            }
+        } else {
+            if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
+                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_iCDF;
+            } else {
+                psEnc->sCmn.pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
+            }
+        }
+        if( psEnc->sCmn.fs_kHz == 8 || psEnc->sCmn.fs_kHz == 12 ) {
+            psEnc->sCmn.predictLPCOrder = MIN_LPC_ORDER;
+            psEnc->sCmn.psNLSF_CB  = &silk_NLSF_CB_NB_MB;
+        } else {
+            psEnc->sCmn.predictLPCOrder = MAX_LPC_ORDER;
+            psEnc->sCmn.psNLSF_CB  = &silk_NLSF_CB_WB;
+        }
+        psEnc->sCmn.subfr_length   = SUB_FRAME_LENGTH_MS * fs_kHz;
+        psEnc->sCmn.frame_length   = silk_SMULBB( psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );
+        psEnc->sCmn.ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz );
+        psEnc->sCmn.la_pitch       = silk_SMULBB( LA_PITCH_MS, fs_kHz );
+        psEnc->sCmn.max_pitch_lag  = silk_SMULBB( 18, fs_kHz );
+        if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
+            psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS, fs_kHz );
+        } else {
+            psEnc->sCmn.pitch_LPC_win_length = silk_SMULBB( FIND_PITCH_LPC_WIN_MS_2_SF, fs_kHz );
+        }
+        if( psEnc->sCmn.fs_kHz == 16 ) {
+            psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_WB, 9 );
+            psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
+        } else if( psEnc->sCmn.fs_kHz == 12 ) {
+            psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_MB, 9 );
+            psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
+        } else {
+            psEnc->sCmn.mu_LTP_Q9 = SILK_FIX_CONST( MU_LTP_QUANT_NB, 9 );
+            psEnc->sCmn.pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
+        }
+    }
+
+    /* Check that settings are valid */
+    silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
+
+    return ret;
+}
+
+opus_int silk_setup_complexity(
+    silk_encoder_state              *psEncC,            /* I/O                      */
+    opus_int                         Complexity          /* I                        */
+)
+{
+    opus_int ret = 0;
+
+    /* Set encoding complexity */
+    silk_assert( Complexity >= 0 && Complexity <= 10 );
+    if( Complexity < 2 ) {
+        psEncC->pitchEstimationComplexity       = SILK_PE_MIN_COMPLEX;
+        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.8, 16 );
+        psEncC->pitchEstimationLPCOrder         = 6;
+        psEncC->shapingLPCOrder                 = 8;
+        psEncC->la_shape                        = 3 * psEncC->fs_kHz;
+        psEncC->nStatesDelayedDecision          = 1;
+        psEncC->useInterpolatedNLSFs            = 0;
+        psEncC->LTPQuantLowComplexity           = 1;
+        psEncC->NLSF_MSVQ_Survivors             = 2;
+        psEncC->warping_Q16                     = 0;
+    } else if( Complexity < 4 ) {
+        psEncC->pitchEstimationComplexity       = SILK_PE_MID_COMPLEX;
+        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.76, 16 );
+        psEncC->pitchEstimationLPCOrder         = 8;
+        psEncC->shapingLPCOrder                 = 10;
+        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
+        psEncC->nStatesDelayedDecision          = 1;
+        psEncC->useInterpolatedNLSFs            = 1;
+        psEncC->LTPQuantLowComplexity           = 0;
+        psEncC->NLSF_MSVQ_Survivors             = 4;
+        psEncC->warping_Q16                     = 0;
+    } else if( Complexity < 6 ) {
+        psEncC->pitchEstimationComplexity       = SILK_PE_MID_COMPLEX;
+        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.74, 16 );
+        psEncC->pitchEstimationLPCOrder         = 10;
+        psEncC->shapingLPCOrder                 = 12;
+        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
+        psEncC->nStatesDelayedDecision          = 2;
+        psEncC->useInterpolatedNLSFs            = 0;
+        psEncC->LTPQuantLowComplexity           = 0;
+        psEncC->NLSF_MSVQ_Survivors             = 8;
+        psEncC->warping_Q16                     = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
+    } else if( Complexity < 8 ) {
+        psEncC->pitchEstimationComplexity       = SILK_PE_MID_COMPLEX;
+        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.72, 16 );
+        psEncC->pitchEstimationLPCOrder         = 12;
+        psEncC->shapingLPCOrder                 = 14;
+        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
+        psEncC->nStatesDelayedDecision          = 3;
+        psEncC->useInterpolatedNLSFs            = 0;
+        psEncC->LTPQuantLowComplexity           = 0;
+        psEncC->NLSF_MSVQ_Survivors             = 16;
+        psEncC->warping_Q16                     = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
+    } else {
+        psEncC->pitchEstimationComplexity       = SILK_PE_MAX_COMPLEX;
+        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.7, 16 );
+        psEncC->pitchEstimationLPCOrder         = 16;
+        psEncC->shapingLPCOrder                 = 16;
+        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
+        psEncC->nStatesDelayedDecision          = MAX_DEL_DEC_STATES;
+        psEncC->useInterpolatedNLSFs            = 1;
+        psEncC->LTPQuantLowComplexity           = 0;
+        psEncC->NLSF_MSVQ_Survivors             = 32;
+        psEncC->warping_Q16                     = psEncC->fs_kHz * SILK_FIX_CONST( WARPING_MULTIPLIER, 16 );
+    }
+
+    /* Do not allow higher pitch estimation LPC order than predict LPC order */
+    psEncC->pitchEstimationLPCOrder = silk_min_int( psEncC->pitchEstimationLPCOrder, psEncC->predictLPCOrder );
+    psEncC->shapeWinLength          = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape;
+    psEncC->Complexity              = Complexity;
+
+    silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
+    silk_assert( psEncC->shapingLPCOrder         <= MAX_SHAPE_LPC_ORDER      );
+    silk_assert( psEncC->nStatesDelayedDecision  <= MAX_DEL_DEC_STATES       );
+    silk_assert( psEncC->warping_Q16             <= 32767                    );
+    silk_assert( psEncC->la_shape                <= LA_SHAPE_MAX             );
+    silk_assert( psEncC->shapeWinLength          <= SHAPE_LPC_WIN_MAX        );
+    silk_assert( psEncC->NLSF_MSVQ_Survivors     <= NLSF_VQ_MAX_SURVIVORS    );
+
+    return ret;
+}
+
+static inline opus_int silk_setup_LBRR(
+    silk_encoder_state          *psEncC,            /* I/O                      */
+    const opus_int32                 TargetRate_bps      /* I                        */
+)
+{
+    opus_int   ret = SILK_NO_ERROR;
+    opus_int32 LBRR_rate_thres_bps;
+
+    psEncC->LBRR_enabled = 0;
+    if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
+        if( psEncC->fs_kHz == 8 ) {
+            LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
+        } else if( psEncC->fs_kHz == 12 ) {
+            LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
+        } else {
+            LBRR_rate_thres_bps = LBRR_WB_MIN_RATE_BPS;
+        }
+        LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps, 125 - silk_min( psEncC->PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
+
+        if( TargetRate_bps > LBRR_rate_thres_bps ) {
+            /* Set gain increase for coding LBRR excitation */
+            psEncC->LBRR_enabled = 1;
+            psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
+        }
+    }
+
+    return ret;
+}
--- /dev/null
+++ b/silk/create_init_destroy.c
@@ -1,0 +1,57 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+
+/************************/
+/* Init Decoder State   */
+/************************/
+opus_int silk_init_decoder(
+    silk_decoder_state      *psDec              /* I/O  Decoder state pointer                       */
+)
+{
+    /* Clear the entire encoder state, except anything copied */
+    silk_memset( psDec, 0, sizeof( silk_decoder_state ) );
+
+    /* Used to deactivate e.g. LSF interpolation and fluctuation reduction */
+    psDec->first_frame_after_reset = 1;
+    psDec->prev_inv_gain_Q16 = 65536;
+
+    /* Reset CNG state */
+    silk_CNG_Reset( psDec );
+
+    /* Reset PLC state */
+    silk_PLC_Reset( psDec );
+
+    return(0);
+}
+
--- /dev/null
+++ b/silk/debug.c
@@ -1,0 +1,170 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "debug.h"
+#include "SigProc_FIX.h"
+
+#if SILK_TIC_TOC
+
+#ifdef _WIN32
+
+#if (defined(_WIN32) || defined(_WINCE))
+#include <windows.h>    /* timer */
+#else   /* Linux or Mac*/
+#include <sys/time.h>
+#endif
+
+unsigned long silk_GetHighResolutionTime(void) /* O: time in usec*/
+{
+    /* Returns a time counter in microsec   */
+    /* the resolution is platform dependent */
+    /* but is typically 1.62 us resolution  */
+    LARGE_INTEGER lpPerformanceCount;
+    LARGE_INTEGER lpFrequency;
+    QueryPerformanceCounter(&lpPerformanceCount);
+    QueryPerformanceFrequency(&lpFrequency);
+    return (unsigned long)((1000000*(lpPerformanceCount.QuadPart)) / lpFrequency.QuadPart);
+}
+#else   /* Linux or Mac*/
+unsigned long GetHighResolutionTime(void) /* O: time in usec*/
+{
+    struct timeval tv;
+    gettimeofday(&tv, 0);
+    return((tv.tv_sec*1000000)+(tv.tv_usec));
+}
+#endif
+
+int           silk_Timer_nTimers = 0;
+int           silk_Timer_depth_ctr = 0;
+char          silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
+#ifdef WIN32
+LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
+#else
+unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
+#endif
+unsigned int  silk_Timer_cnt[silk_NUM_TIMERS_MAX];
+opus_int64     silk_Timer_min[silk_NUM_TIMERS_MAX];
+opus_int64     silk_Timer_sum[silk_NUM_TIMERS_MAX];
+opus_int64     silk_Timer_max[silk_NUM_TIMERS_MAX];
+opus_int64     silk_Timer_depth[silk_NUM_TIMERS_MAX];
+
+#ifdef WIN32
+void silk_TimerSave(char *file_name)
+{
+    if( silk_Timer_nTimers > 0 )
+    {
+        int k;
+        FILE *fp;
+        LARGE_INTEGER lpFrequency;
+        LARGE_INTEGER lpPerformanceCount1, lpPerformanceCount2;
+        int del = 0x7FFFFFFF;
+        double avg, sum_avg;
+        /* estimate overhead of calling performance counters */
+        for( k = 0; k < 1000; k++ ) {
+            QueryPerformanceCounter(&lpPerformanceCount1);
+            QueryPerformanceCounter(&lpPerformanceCount2);
+            lpPerformanceCount2.QuadPart -= lpPerformanceCount1.QuadPart;
+            if( (int)lpPerformanceCount2.LowPart < del )
+                del = lpPerformanceCount2.LowPart;
+        }
+        QueryPerformanceFrequency(&lpFrequency);
+        /* print results to file */
+        sum_avg = 0.0f;
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {
+            if (silk_Timer_depth[k] == 0) {
+                sum_avg += (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart * silk_Timer_cnt[k];
+            }
+        }
+        fp = fopen(file_name, "w");
+        fprintf(fp, "                                min         avg     %%         max      count\n");
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {
+            if (silk_Timer_depth[k] == 0) {
+                fprintf(fp, "%-28s", silk_Timer_tags[k]);
+            } else if (silk_Timer_depth[k] == 1) {
+                fprintf(fp, " %-27s", silk_Timer_tags[k]);
+            } else if (silk_Timer_depth[k] == 2) {
+                fprintf(fp, "  %-26s", silk_Timer_tags[k]);
+            } else if (silk_Timer_depth[k] == 3) {
+                fprintf(fp, "   %-25s", silk_Timer_tags[k]);
+            } else {
+                fprintf(fp, "    %-24s", silk_Timer_tags[k]);
+            }
+            avg = (1e6 * silk_Timer_sum[k] / silk_Timer_cnt[k] - del) / lpFrequency.QuadPart;
+            fprintf(fp, "%8.2f", (1e6 * (silk_max_64(silk_Timer_min[k] - del, 0))) / lpFrequency.QuadPart);
+            fprintf(fp, "%12.2f %6.2f", avg, 100.0 * avg / sum_avg * silk_Timer_cnt[k]);
+            fprintf(fp, "%12.2f", (1e6 * (silk_max_64(silk_Timer_max[k] - del, 0))) / lpFrequency.QuadPart);
+            fprintf(fp, "%10d\n", silk_Timer_cnt[k]);
+        }
+        fprintf(fp, "                                microseconds\n");
+        fclose(fp);
+    }
+}
+#else
+void silk_TimerSave(char *file_name)
+{
+    if( silk_Timer_nTimers > 0 )
+    {
+        int k;
+        FILE *fp;
+        /* print results to file */
+        fp = fopen(file_name, "w");
+        fprintf(fp, "                                min         avg         max      count\n");
+        for( k = 0; k < silk_Timer_nTimers; k++ )
+        {
+            if (silk_Timer_depth[k] == 0) {
+                fprintf(fp, "%-28s", silk_Timer_tags[k]);
+            } else if (silk_Timer_depth[k] == 1) {
+                fprintf(fp, " %-27s", silk_Timer_tags[k]);
+            } else if (silk_Timer_depth[k] == 2) {
+                fprintf(fp, "  %-26s", silk_Timer_tags[k]);
+            } else if (silk_Timer_depth[k] == 3) {
+                fprintf(fp, "   %-25s", silk_Timer_tags[k]);
+            } else {
+                fprintf(fp, "    %-24s", silk_Timer_tags[k]);
+            }
+            fprintf(fp, "%d ", silk_Timer_min[k]);
+            fprintf(fp, "%f ", (double)silk_Timer_sum[k] / (double)silk_Timer_cnt[k]);
+            fprintf(fp, "%d ", silk_Timer_max[k]);
+            fprintf(fp, "%10d\n", silk_Timer_cnt[k]);
+        }
+        fprintf(fp, "                                microseconds\n");
+        fclose(fp);
+    }
+}
+#endif
+
+#endif /* SILK_TIC_TOC */
+
+#if SILK_DEBUG
+FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ];
+int silk_debug_store_count = 0;
+#endif /* SILK_DEBUG */
+
--- /dev/null
+++ b/silk/debug.h
@@ -1,0 +1,311 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef _SILK_DEBUG_H_
+#define _SILK_DEBUG_H_
+
+#ifdef _WIN32
+#define _CRT_SECURE_NO_DEPRECATE    1
+#endif
+
+#include "typedef.h"
+#include <stdio.h>      /* file writing */
+#include <string.h>     /* strcpy, strcmp */
+
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+
+unsigned long GetHighResolutionTime(void); /* O: time in usec*/
+
+/* make SILK_DEBUG dependent on compiler's _DEBUG */
+#if defined _WIN32
+    #ifdef _DEBUG
+        #define SILK_DEBUG  1
+    #else
+        #define SILK_DEBUG  0
+    #endif
+
+    /* overrule the above */
+    #if 0
+    /*  #define NO_ASSERTS*/
+    #undef  SILK_DEBUG
+    #define SILK_DEBUG  1
+    #endif
+#else
+    #define SILK_DEBUG  0
+#endif
+
+/* Flag for using timers */
+#define SILK_TIC_TOC 0
+
+#if SILK_TIC_TOC
+
+#if (defined(_WIN32) || defined(_WINCE))
+#include <windows.h>    /* timer */
+#pragma warning( disable : 4996 )       /* stop bitching about strcpy in TIC()*/
+#else   /* Linux or Mac*/
+#include <sys/time.h>
+#endif
+
+/*********************************/
+/* timer functions for profiling */
+/*********************************/
+/* example:                                                         */
+/*                                                                  */
+/* TIC(LPC)                                                         */
+/* do_LPC(in_vec, order, acoef);    // do LPC analysis              */
+/* TOC(LPC)                                                         */
+/*                                                                  */
+/* and call the following just before exiting (from main)           */
+/*                                                                  */
+/* silk_TimerSave("silk_TimingData.txt");                             */
+/*                                                                  */
+/* results are now in silk_TimingData.txt                            */
+
+void silk_TimerSave(char *file_name);
+
+/* max number of timers (in different locations) */
+#define silk_NUM_TIMERS_MAX                  50
+/* max length of name tags in TIC(..), TOC(..) */
+#define silk_NUM_TIMERS_MAX_TAG_LEN          30
+
+extern int           silk_Timer_nTimers;
+extern int           silk_Timer_depth_ctr;
+extern char          silk_Timer_tags[silk_NUM_TIMERS_MAX][silk_NUM_TIMERS_MAX_TAG_LEN];
+#ifdef _WIN32
+extern LARGE_INTEGER silk_Timer_start[silk_NUM_TIMERS_MAX];
+#else
+extern unsigned long silk_Timer_start[silk_NUM_TIMERS_MAX];
+#endif
+extern unsigned int  silk_Timer_cnt[silk_NUM_TIMERS_MAX];
+extern opus_int64     silk_Timer_sum[silk_NUM_TIMERS_MAX];
+extern opus_int64     silk_Timer_max[silk_NUM_TIMERS_MAX];
+extern opus_int64     silk_Timer_min[silk_NUM_TIMERS_MAX];
+extern opus_int64     silk_Timer_depth[silk_NUM_TIMERS_MAX];
+
+/* WARNING: TIC()/TOC can measure only up to 0.1 seconds at a time */
+#ifdef _WIN32
+#define TIC(TAG_NAME) {                                     \
+    static int init = 0;                                    \
+    static int ID = -1;                                     \
+    if( init == 0 )                                         \
+    {                                                       \
+        int k;                                              \
+        init = 1;                                           \
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {          \
+            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {   \
+                ID = k;                                     \
+                break;                                      \
+            }                                               \
+        }                                                   \
+        if (ID == -1) {                                     \
+            ID = silk_Timer_nTimers;                         \
+            silk_Timer_nTimers++;                            \
+            silk_Timer_depth[ID] = silk_Timer_depth_ctr;      \
+            strcpy(silk_Timer_tags[ID], #TAG_NAME);          \
+            silk_Timer_cnt[ID] = 0;                          \
+            silk_Timer_sum[ID] = 0;                          \
+            silk_Timer_min[ID] = 0xFFFFFFFF;                 \
+            silk_Timer_max[ID] = 0;                          \
+        }                                                   \
+    }                                                       \
+    silk_Timer_depth_ctr++;                                  \
+    QueryPerformanceCounter(&silk_Timer_start[ID]);          \
+}
+#else
+#define TIC(TAG_NAME) {                                     \
+    static int init = 0;                                    \
+    static int ID = -1;                                     \
+    if( init == 0 )                                         \
+    {                                                       \
+        int k;                                              \
+        init = 1;                                           \
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {          \
+        if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {   \
+                ID = k;                                     \
+                break;                                      \
+            }                                               \
+        }                                                   \
+        if (ID == -1) {                                     \
+            ID = silk_Timer_nTimers;                         \
+            silk_Timer_nTimers++;                            \
+            silk_Timer_depth[ID] = silk_Timer_depth_ctr;      \
+            strcpy(silk_Timer_tags[ID], #TAG_NAME);          \
+            silk_Timer_cnt[ID] = 0;                          \
+            silk_Timer_sum[ID] = 0;                          \
+            silk_Timer_min[ID] = 0xFFFFFFFF;                 \
+            silk_Timer_max[ID] = 0;                          \
+        }                                                   \
+    }                                                       \
+    silk_Timer_depth_ctr++;                                  \
+    silk_Timer_start[ID] = GetHighResolutionTime();          \
+}
+#endif
+
+#ifdef _WIN32
+#define TOC(TAG_NAME) {                                             \
+    LARGE_INTEGER lpPerformanceCount;                               \
+    static int init = 0;                                            \
+    static int ID = 0;                                              \
+    if( init == 0 )                                                 \
+    {                                                               \
+        int k;                                                      \
+        init = 1;                                                   \
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {                  \
+            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {       \
+                ID = k;                                             \
+                break;                                              \
+            }                                                       \
+        }                                                           \
+    }                                                               \
+    QueryPerformanceCounter(&lpPerformanceCount);                   \
+    lpPerformanceCount.QuadPart -= silk_Timer_start[ID].QuadPart;    \
+    if((lpPerformanceCount.QuadPart < 100000000) &&                 \
+        (lpPerformanceCount.QuadPart >= 0)) {                       \
+        silk_Timer_cnt[ID]++;                                        \
+        silk_Timer_sum[ID] += lpPerformanceCount.QuadPart;           \
+        if( lpPerformanceCount.QuadPart > silk_Timer_max[ID] )       \
+            silk_Timer_max[ID] = lpPerformanceCount.QuadPart;        \
+        if( lpPerformanceCount.QuadPart < silk_Timer_min[ID] )       \
+            silk_Timer_min[ID] = lpPerformanceCount.QuadPart;        \
+    }                                                               \
+    silk_Timer_depth_ctr--;                                          \
+}
+#else
+#define TOC(TAG_NAME) {                                             \
+    unsigned long endTime;                                          \
+    static int init = 0;                                            \
+    static int ID = 0;                                              \
+    if( init == 0 )                                                 \
+    {                                                               \
+        int k;                                                      \
+        init = 1;                                                   \
+        for( k = 0; k < silk_Timer_nTimers; k++ ) {                  \
+            if( strcmp(silk_Timer_tags[k], #TAG_NAME) == 0 ) {       \
+                ID = k;                                             \
+                break;                                              \
+            }                                                       \
+        }                                                           \
+    }                                                               \
+    endTime = GetHighResolutionTime();                              \
+    endTime -= silk_Timer_start[ID];                                 \
+    if((endTime < 100000000) &&                                     \
+        (endTime >= 0)) {                                           \
+        silk_Timer_cnt[ID]++;                                        \
+        silk_Timer_sum[ID] += endTime;                               \
+        if( endTime > silk_Timer_max[ID] )                           \
+            silk_Timer_max[ID] = endTime;                            \
+        if( endTime < silk_Timer_min[ID] )                           \
+            silk_Timer_min[ID] = endTime;                            \
+    }                                                               \
+        silk_Timer_depth_ctr--;                                      \
+}
+#endif
+
+#else /* SILK_TIC_TOC */
+
+/* define macros as empty strings */
+#define TIC(TAG_NAME)
+#define TOC(TAG_NAME)
+#define silk_TimerSave(FILE_NAME)
+
+#endif /* SILK_TIC_TOC */
+
+
+
+#if SILK_DEBUG
+/************************************/
+/* write data to file for debugging */
+/************************************/
+/* opens an empty file if this file has not yet been open, then writes to the file and closes it            */
+/* if file has been open previously it is opened again and the fwrite is appending, finally it is closed    */
+#define SAVE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) {                 \
+    static opus_int32 init = 0;                                      \
+    FILE *fp;                                                       \
+    if (init == 0)    {                                               \
+        init = 1;                                                   \
+        fp = fopen(#FILE_NAME, "wb");                               \
+    } else {                                                        \
+        fp = fopen(#FILE_NAME, "ab+");                              \
+    }                                                                \
+    fwrite((DATA_PTR), (N_BYTES), 1, fp);                           \
+    fclose(fp);                                                     \
+}
+
+/* Example: DEBUG_STORE_DATA(testfile.pcm, &RIN[0], 160*sizeof(opus_int16)); */
+
+#if 0
+/* Ensure that everything is written to files when an assert breaks */
+#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES) SAVE_DATA(FILE_NAME, DATA_PTR, N_BYTES)
+#define SILK_DEBUG_STORE_CLOSE_FILES
+
+#else
+
+#define silk_NUM_STORES_MAX                                  100
+extern FILE *silk_debug_store_fp[ silk_NUM_STORES_MAX ];
+extern int silk_debug_store_count;
+
+/* Faster way of storing the data */
+#define DEBUG_STORE_DATA( FILE_NAME, DATA_PTR, N_BYTES ) {          \
+    static opus_int init = 0, cnt = 0;                               \
+    static FILE **fp;                                               \
+    if (init == 0) {                                                \
+        init = 1;                                                    \
+        cnt = silk_debug_store_count++;                             \
+        silk_debug_store_fp[ cnt ] = fopen(#FILE_NAME, "wb");       \
+    }                                                               \
+    fwrite((DATA_PTR), (N_BYTES), 1, silk_debug_store_fp[ cnt ]);   \
+}
+
+/* Call this at the end of main() */
+#define SILK_DEBUG_STORE_CLOSE_FILES {                              \
+    opus_int i;                                                      \
+    for( i = 0; i < silk_debug_store_count; i++ ) {                 \
+        fclose( silk_debug_store_fp[ i ] );                         \
+    }                                                               \
+}
+#endif
+
+/* micro sec */
+#define silk_GETTIME(void)       time = (opus_int64) silk_GetHighResolutionTime();
+
+#else /* SILK_DEBUG */
+
+/* define macros as empty strings */
+#define DEBUG_STORE_DATA(FILE_NAME, DATA_PTR, N_BYTES)
+#define SAVE_DATA(FILE_NAME, DATA_PTR, N_BYTES)
+#define SILK_DEBUG_STORE_CLOSE_FILES
+
+#endif /* SILK_DEBUG */
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif /* _SILK_DEBUG_H_ */
--- /dev/null
+++ b/silk/dec_API.c
@@ -1,0 +1,310 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "API.h"
+#include "main.h"
+
+/************************/
+/* Decoder Super Struct */
+/************************/
+typedef struct {
+    silk_decoder_state          channel_state[ DECODER_NUM_CHANNELS ];
+    stereo_dec_state                sStereo;
+    opus_int                         nChannelsAPI;
+    opus_int                         nChannelsInternal;
+} silk_decoder;
+
+/*********************/
+/* Decoder functions */
+/*********************/
+
+opus_int silk_Get_Decoder_Size( int *decSizeBytes )
+{
+    opus_int ret = SILK_NO_ERROR;
+
+    *decSizeBytes = sizeof( silk_decoder );
+
+    return ret;
+}
+
+/* Reset decoder state */
+opus_int silk_InitDecoder(
+    void* decState                                      /* I/O: State                                          */
+)
+{
+    opus_int n, ret = SILK_NO_ERROR;
+    silk_decoder_state *channel_state = ((silk_decoder *)decState)->channel_state;
+
+    for( n = 0; n < DECODER_NUM_CHANNELS; n++ ) {
+        ret  = silk_init_decoder( &channel_state[ n ] );
+    }
+
+    return ret;
+}
+
+/* Decode a frame */
+opus_int silk_Decode(
+    void*                               decState,       /* I/O: State                                           */
+    silk_DecControlStruct*      decControl,     /* I/O: Control Structure                               */
+    opus_int                             lostFlag,       /* I:   0: no loss, 1 loss, 2 decode FEC                */
+    opus_int                             newPacketFlag,  /* I:   Indicates first decoder call for this packet    */
+    ec_dec                              *psRangeDec,    /* I/O  Compressor data structure                       */
+    opus_int16                           *samplesOut,    /* O:   Decoded output speech vector                    */
+    opus_int32                           *nSamplesOut    /* O:   Number of samples decoded                       */
+)
+{
+    opus_int   i, n, prev_fs_kHz, 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 ];
+    opus_int16 samplesOut2_tmp[ MAX_API_FS_KHZ * MAX_FRAME_LENGTH_MS ];
+    opus_int32 MS_pred_Q13[ 2 ] = { 0 };
+    opus_int16 *resample_out_ptr;
+    silk_decoder *psDec = ( silk_decoder * )decState;
+    silk_decoder_state *channel_state = psDec->channel_state;
+
+    /**********************************/
+    /* Test if first frame in payload */
+    /**********************************/
+    if( newPacketFlag ) {
+        for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+            channel_state[ n ].nFramesDecoded = 0;  /* Used to count frames in packet */
+        }
+    }
+
+    /* Save previous sample frequency */
+    prev_fs_kHz = channel_state[ 0 ].fs_kHz;
+
+    /* If Mono -> Stereo transition in bitstream: init state of second channel */
+    if( decControl->nChannelsInternal > psDec->nChannelsInternal ) {
+        ret += silk_init_decoder( &channel_state[ 1 ] );
+        if( psDec->nChannelsAPI == 2 ) {
+            silk_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) );
+        }
+    }
+
+    for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+        if( channel_state[ n ].nFramesDecoded == 0 ) {
+            opus_int fs_kHz_dec;
+            if( decControl->payloadSize_ms == 0 ) {
+                /* Assuming packet loss, use 10 ms */
+                channel_state[ n ].nFramesPerPacket = 1;
+                channel_state[ n ].nb_subfr = 2;
+            } else if( decControl->payloadSize_ms == 10 ) {
+                channel_state[ n ].nFramesPerPacket = 1;
+                channel_state[ n ].nb_subfr = 2;
+            } else if( decControl->payloadSize_ms == 20 ) {
+                channel_state[ n ].nFramesPerPacket = 1;
+                channel_state[ n ].nb_subfr = 4;
+            } else if( decControl->payloadSize_ms == 40 ) {
+                channel_state[ n ].nFramesPerPacket = 2;
+                channel_state[ n ].nb_subfr = 4;
+            } else if( decControl->payloadSize_ms == 60 ) {
+                channel_state[ n ].nFramesPerPacket = 3;
+                channel_state[ n ].nb_subfr = 4;
+            } else {
+                silk_assert( 0 );
+                return SILK_DEC_INVALID_FRAME_SIZE;
+            }
+            fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
+            if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
+                silk_assert( 0 );
+                return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
+            }
+            silk_decoder_set_fs( &channel_state[ n ], fs_kHz_dec );
+        }
+    }
+
+    /* Initialize resampler when switching internal or external sampling frequency */
+    if( prev_fs_kHz != channel_state[ 0 ].fs_kHz || channel_state[ 0 ].prev_API_sampleRate != decControl->API_sampleRate ) {
+        ret = silk_resampler_init( &channel_state[ 0 ].resampler_state, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ), decControl->API_sampleRate );
+        if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
+            silk_memcpy( &channel_state[ 1 ].resampler_state, &channel_state[ 0 ].resampler_state, sizeof( silk_resampler_state_struct ) );
+        }
+    }
+    channel_state[ 0 ].prev_API_sampleRate = decControl->API_sampleRate;
+    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 ) );
+    }
+    psDec->nChannelsAPI      = decControl->nChannelsAPI;
+    psDec->nChannelsInternal = decControl->nChannelsInternal;
+
+    if( decControl->API_sampleRate > MAX_API_FS_KHZ * 1000 || decControl->API_sampleRate < 8000 ) {
+        ret = SILK_DEC_INVALID_SAMPLING_FREQUENCY;
+        return( ret );
+    }
+
+    if( lostFlag != FLAG_PACKET_LOST && channel_state[ 0 ].nFramesDecoded == 0 ) {
+        /* First decoder call for this payload */
+        /* Decode VAD flags and LBRR flag */
+        for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+            for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) {
+                channel_state[ n ].VAD_flags[ i ] = ec_dec_bit_logp(psRangeDec, 1);
+            }
+            channel_state[ n ].LBRR_flag = ec_dec_bit_logp(psRangeDec, 1);
+        }
+        /* Decode LBRR flags */
+        for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+            silk_memset( channel_state[ n ].LBRR_flags, 0, sizeof( channel_state[ n ].LBRR_flags ) );
+            if( channel_state[ n ].LBRR_flag ) {
+                if( channel_state[ n ].nFramesPerPacket == 1 ) {
+                    channel_state[ n ].LBRR_flags[ 0 ] = 1;
+                } else {
+                    LBRR_symbol = ec_dec_icdf( psRangeDec, silk_LBRR_flags_iCDF_ptr[ channel_state[ n ].nFramesPerPacket - 2 ], 8 ) + 1;
+                    for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ ) {
+                        channel_state[ n ].LBRR_flags[ i ] = silk_RSHIFT( LBRR_symbol, i ) & 1;
+                    }
+                }
+            }
+        }
+
+        if( lostFlag == FLAG_DECODE_NORMAL ) {
+            /* Regular decoding: skip all LBRR data */
+            for( i = 0; i < channel_state[ 0 ].nFramesPerPacket; i++ ) {
+                for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+                    if( channel_state[ n ].LBRR_flags[ i ] ) {
+                        opus_int pulses[ MAX_FRAME_LENGTH ];
+                        if( decControl->nChannelsInternal == 2 && n == 0 ) {
+                            silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 );
+                            if( channel_state[ 1 ].LBRR_flags[ i ] == 0 ) {
+                                silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle );
+                            }
+                        }
+                        silk_decode_indices( &channel_state[ n ], psRangeDec, i, 1 );
+                        silk_decode_pulses( psRangeDec, pulses, channel_state[ n ].indices.signalType,
+                            channel_state[ n ].indices.quantOffsetType, channel_state[ n ].frame_length );
+                    }
+                }
+            }
+        }
+    }
+
+    /* Get MS predictor index */
+    if( decControl->nChannelsInternal == 2 ) {
+        if(   lostFlag == FLAG_DECODE_NORMAL ||
+            ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 0 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 1 ) )
+        {
+            silk_stereo_decode_pred( psRangeDec, MS_pred_Q13 );
+            /* For LBRR data, only decode mid-only flag if side-channel's LBRR flag is false */
+            if(   lostFlag == FLAG_DECODE_NORMAL ||
+                ( lostFlag == FLAG_DECODE_LBRR && channel_state[ 1 ].LBRR_flags[ channel_state[ 0 ].nFramesDecoded ] == 0 ) )
+            {
+                silk_stereo_decode_mid_only( psRangeDec, &decode_only_middle );
+            } else {
+                decode_only_middle = 0;
+            }
+        } else {
+            for( n = 0; n < 2; n++ ) {
+                MS_pred_Q13[n] = psDec->sStereo.pred_prev_Q13[n];
+            }
+        }
+    }
+
+    /* Call decoder for one frame */
+    for( n = 0; n < decControl->nChannelsInternal; n++ ) {
+        if( n == 0 || decode_only_middle == 0 ) {
+            ret += silk_decode_frame( &channel_state[ n ], psRangeDec, &samplesOut1_tmp[ n ][ 2 ], &nSamplesOutDec, lostFlag );
+        } else {
+            silk_memset( &samplesOut1_tmp[ n ][ 2 ], 0, nSamplesOutDec * sizeof( opus_int16 ) );
+        }
+    }
+
+    if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
+        /* Convert Mid/Side to Left/Right */
+        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 ], psDec->sStereo.sMid, 2 * sizeof( opus_int16 ) );
+        silk_memcpy( psDec->sStereo.sMid, &samplesOut1_tmp[ 0 ][ nSamplesOutDec ], 2 * sizeof( opus_int16 ) );
+    }
+
+    /* Number of output samples */
+    *nSamplesOut = silk_DIV32( nSamplesOutDec * decControl->API_sampleRate, silk_SMULBB( channel_state[ 0 ].fs_kHz, 1000 ) );
+
+    /* Set up pointers to temp buffers */
+    if( decControl->nChannelsAPI == 2 ) {
+        resample_out_ptr = samplesOut2_tmp;
+    } else {
+        resample_out_ptr = samplesOut;
+    }
+
+    for( n = 0; n < silk_min( decControl->nChannelsAPI, decControl->nChannelsInternal ); n++ ) {
+        /* Resample decoded signal to API_sampleRate */
+        ret += silk_resampler( &channel_state[ n ].resampler_state, resample_out_ptr, &samplesOut1_tmp[ n ][ 1 ], nSamplesOutDec );
+
+        /* Interleave if stereo output and stereo stream */
+        if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 2 ) {
+            for( i = 0; i < *nSamplesOut; i++ ) {
+                samplesOut[ n + 2 * i ] = resample_out_ptr[ i ];
+            }
+        }
+    }
+
+    /* Create two channel output from mono stream */
+    if( decControl->nChannelsAPI == 2 && decControl->nChannelsInternal == 1 ) {
+        for( i = 0; i < *nSamplesOut; i++ ) {
+            samplesOut[ 0 + 2 * i ] = samplesOut[ 1 + 2 * i ] = resample_out_ptr[ i ];
+        }
+    }
+
+    return ret;
+}
+
+/* Getting table of contents for a packet */
+opus_int silk_get_TOC(
+    const opus_uint8                     *payload,           /* I    Payload data                                */
+    const opus_int                       nBytesIn,           /* I:   Number of input bytes                       */
+    const opus_int                       nFramesPerPayload,  /* I:   Number of SILK frames per payload           */
+    silk_TOC_struct                 *Silk_TOC           /* O:   Type of content                             */
+)
+{
+    opus_int i, flags, ret = SILK_NO_ERROR;
+
+    if( nBytesIn < 1 ) {
+        return -1;
+    }
+    if( nFramesPerPayload < 0 || nFramesPerPayload > 3 ) {
+        return -1;
+    }
+
+    silk_memset( Silk_TOC, 0, sizeof( Silk_TOC ) );
+
+    /* For stereo, extract the flags for the mid channel */
+    flags = silk_RSHIFT( payload[ 0 ], 7 - nFramesPerPayload ) & ( silk_LSHIFT( 1, nFramesPerPayload + 1 ) - 1 );
+
+    Silk_TOC->inbandFECFlag = flags & 1;
+    for( i = nFramesPerPayload - 1; i >= 0 ; i-- ) {
+        flags = silk_RSHIFT( flags, 1 );
+        Silk_TOC->VADFlags[ i ] = flags & 1;
+        Silk_TOC->VADFlag |= flags & 1;
+    }
+
+    return ret;
+}
--- /dev/null
+++ b/silk/decode_core.c
@@ -1,0 +1,228 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/**********************************************************/
+/* Core decoder. Performs inverse NSQ operation LTP + LPC */
+/**********************************************************/
+void silk_decode_core(
+    silk_decoder_state      *psDec,                             /* I/O  Decoder state               */
+    silk_decoder_control    *psDecCtrl,                         /* I    Decoder control             */
+    opus_int16                   xq[],                               /* O    Decoded speech              */
+    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_int16 *A_Q12, *B_Q14, *pxq, A_Q12_tmp[ MAX_LPC_ORDER ];
+    opus_int16 sLTP[ MAX_FRAME_LENGTH ];
+    opus_int32 LTP_pred_Q14, LPC_pred_Q10, Gain_Q16, inv_gain_Q16, inv_gain_Q32, 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 vec_Q10[ MAX_SUB_FRAME_LENGTH ];
+
+    silk_assert( psDec->prev_inv_gain_Q16 != 0 );
+
+    offset_Q10 = silk_Quantization_Offsets_Q10[ psDec->indices.signalType >> 1 ][ psDec->indices.quantOffsetType ];
+
+    if( psDec->indices.NLSFInterpCoef_Q2 < 1 << 2 ) {
+        NLSF_interpolation_flag = 1;
+    } else {
+        NLSF_interpolation_flag = 0;
+    }
+
+    /* Decode excitation */
+    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 );
+        if( psDec->exc_Q10[ i ] > 0 ) {
+            psDec->exc_Q10[ i ] -= QUANT_LEVEL_ADJUST_Q10;
+        } else
+        if( psDec->exc_Q10[ i ] < 0 ) {
+            psDec->exc_Q10[ i ] += QUANT_LEVEL_ADJUST_Q10;
+        }
+        psDec->exc_Q10[ i ] += offset_Q10;
+        psDec->exc_Q10[ i ] ^= silk_RSHIFT( rand_seed, 31 );
+
+        rand_seed = silk_ADD32_ovflw(rand_seed, pulses[ i ]);
+    }
+
+#ifdef SAVE_ALL_INTERNAL_DATA
+    DEBUG_STORE_DATA( dec_q.dat, pulses, psDec->frame_length * sizeof( opus_int ) );
+#endif
+
+    pexc_Q10 = psDec->exc_Q10;
+    pxq      = &psDec->outBuf[ psDec->ltp_mem_length ];
+    sLTP_buf_idx = psDec->ltp_mem_length;
+    /* Loop over subframes */
+    for( k = 0; k < psDec->nb_subfr; k++ ) {
+        pres_Q10 = res_Q10;
+        A_Q12 = psDecCtrl->PredCoef_Q12[ k >> 1 ];
+
+        /* Preload LPC coeficients to array on stack. Gives small performance gain */
+        silk_memcpy( A_Q12_tmp, A_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
+        B_Q14        = &psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER ];
+        Gain_Q16     = psDecCtrl->Gains_Q16[ k ];
+        signalType   = psDec->indices.signalType;
+
+        inv_gain_Q16 = silk_INVERSE32_varQ( silk_max( Gain_Q16, 1 ), 32 );
+        inv_gain_Q16 = silk_min( inv_gain_Q16, silk_int16_MAX );
+
+        /* Calculate Gain adjustment factor */
+        gain_adj_Q16 = 1 << 16;
+        if( inv_gain_Q16 != psDec->prev_inv_gain_Q16 ) {
+            gain_adj_Q16 =  silk_DIV32_varQ( inv_gain_Q16, psDec->prev_inv_gain_Q16, 16 );
+
+            /* Scale short term state */
+            for( i = 0; i < MAX_LPC_ORDER; i++ ) {
+                psDec->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDec->sLPC_Q14[ i ] );
+            }
+        }
+
+        /* Save inv_gain */
+        silk_assert( inv_gain_Q16 != 0 );
+        psDec->prev_inv_gain_Q16 = inv_gain_Q16;
+
+        /* Avoid abrupt transition from voiced PLC to unvoiced normal decoding */
+        if( psDec->lossCnt && psDec->prevSignalType == TYPE_VOICED &&
+            psDec->indices.signalType != TYPE_VOICED && k < MAX_NB_SUBFR/2 ) {
+
+            silk_memset( B_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
+            B_Q14[ LTP_ORDER/2 ] = SILK_FIX_CONST( 0.25, 14 );
+
+            signalType = TYPE_VOICED;
+            psDecCtrl->pitchL[ k ] = psDec->lagPrev;
+        }
+
+        if( signalType == TYPE_VOICED ) {
+            /* Voiced */
+            lag = psDecCtrl->pitchL[ k ];
+
+            /* Re-whitening */
+            if( ( k & ( 3 - silk_LSHIFT( NLSF_interpolation_flag, 1 ) ) ) == 0 ) {
+                /* Rewhiten with new A coefs */
+                start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
+                silk_assert( start_idx > 0 );
+
+                silk_LPC_analysis_filter( &sLTP[ start_idx ], &psDec->outBuf[ start_idx + k * psDec->subfr_length ],
+                    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 );
+                if( k == 0 ) {
+                    /* Do LTP downscaling */
+                    inv_gain_Q32 = silk_LSHIFT( silk_SMULWB( inv_gain_Q32, psDecCtrl->LTP_scale_Q14 ), 2 );
+                }
+                for( i = 0; i < lag + LTP_ORDER/2; i++ ) {
+                    psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] = silk_SMULWB( inv_gain_Q32, 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++ ) {
+                        psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] = silk_SMULWW( gain_adj_Q16, psDec->sLTP_Q16[ sLTP_buf_idx - i - 1 ] );
+                    }
+                }
+            }
+        }
+
+        /* Long-term prediction */
+        if( signalType == TYPE_VOICED ) {
+            /* Setup pointer */
+            pred_lag_ptr = &psDec->sLTP_Q16[ 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 ] );
+                pred_lag_ptr++;
+
+                /* Generate LPC excitation */
+                pres_Q10[ i ] = silk_ADD32( pexc_Q10[ i ], silk_RSHIFT_ROUND( LTP_pred_Q14, 4 ) );
+
+                /* Update states */
+                psDec->sLTP_Q16[ sLTP_buf_idx ] = silk_LSHIFT( pres_Q10[ i ], 6 );
+                sLTP_buf_idx++;
+            }
+        } else {
+            pres_Q10 = pexc_Q10;
+        }
+
+#ifdef SAVE_ALL_INTERNAL_DATA
+        DEBUG_STORE_DATA( dec_exc_Q10.dat, pexc_Q10, psDec->subfr_length * sizeof( opus_int32 ) );
+        DEBUG_STORE_DATA( dec_res_Q10.dat, pres_Q10, psDec->subfr_length * sizeof( opus_int32 ) );
+#endif
+
+        for( i = 0; i < psDec->subfr_length; i++ ) {
+            /* Partially unrolled */
+            LPC_pred_Q10 = silk_SMULWB(               psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12_tmp[ 0 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  2 ], A_Q12_tmp[ 1 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  3 ], A_Q12_tmp[ 2 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  4 ], A_Q12_tmp[ 3 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  5 ], A_Q12_tmp[ 4 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  6 ], A_Q12_tmp[ 5 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  7 ], A_Q12_tmp[ 6 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  8 ], A_Q12_tmp[ 7 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i -  9 ], A_Q12_tmp[ 8 ] );
+            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, psDec->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, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp[ j ] );
+            }
+
+            /* Add prediction to LPC excitation */
+            vec_Q10[ i ] = silk_ADD32( pres_Q10[ i ], LPC_pred_Q10 );
+
+            /* Update states */
+            psDec->sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_LSHIFT( vec_Q10[ i ], 4 );
+        }
+
+        /* Scale with Gain */
+        for( i = 0; i < psDec->subfr_length; i++ ) {
+            pxq[ i ] = ( opus_int16 )silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( vec_Q10[ i ], Gain_Q16 ), 10 ) );
+        }
+
+        /* Update LPC filter state */
+        silk_memcpy( psDec->sLPC_Q14, &psDec->sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
+        pexc_Q10 += psDec->subfr_length;
+        pxq      += psDec->subfr_length;
+    }
+
+    /* Copy to output */
+    silk_memcpy( xq, &psDec->outBuf[ psDec->ltp_mem_length ], psDec->frame_length * sizeof( opus_int16 ) );
+
+#ifdef SAVE_ALL_INTERNAL_DATA
+    DEBUG_STORE_DATA( dec_sLTP_Q16.dat, &psDec->sLTP_Q16[ psDec->ltp_mem_length ], psDec->frame_length * sizeof( opus_int32 ));
+    DEBUG_STORE_DATA( dec_xq.dat, xq, psDec->frame_length * sizeof( opus_int16 ) );
+#endif
+}
--- /dev/null
+++ b/silk/decode_frame.c
@@ -1,0 +1,137 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+#include "PLC.h"
+
+/****************/
+/* Decode frame */
+/****************/
+opus_int silk_decode_frame(
+    silk_decoder_state      *psDec,             /* I/O  Pointer to Silk decoder state               */
+    ec_dec                      *psRangeDec,        /* I/O  Compressor data structure                   */
+    opus_int16                   pOut[],             /* O    Pointer to output speech frame              */
+    opus_int32                   *pN,                /* O    Pointer to size of output frame             */
+    opus_int                     lostFlag            /* I    0: no loss, 1 loss, 2 decode fec            */
+)
+{
+    silk_decoder_control sDecCtrl;
+    opus_int         L, mv_len, ret = 0;
+    opus_int         pulses[ MAX_FRAME_LENGTH ];
+
+TIC(DECODE_FRAME)
+
+    L = psDec->frame_length;
+    sDecCtrl.LTP_scale_Q14 = 0;
+
+    /* Safety checks */
+    silk_assert( L > 0 && L <= MAX_FRAME_LENGTH );
+
+    if(   lostFlag == FLAG_DECODE_NORMAL ||
+        ( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
+    {
+        /*********************************************/
+        /* Decode quantization indices of side info  */
+        /*********************************************/
+TIC(decode_indices)
+        silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag );
+TOC(decode_indices)
+
+        /*********************************************/
+        /* Decode quantization indices of excitation */
+        /*********************************************/
+TIC(decode_pulses)
+        silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType,
+                psDec->indices.quantOffsetType, psDec->frame_length );
+TOC(decode_pulses)
+
+        /********************************************/
+        /* Decode parameters and pulse signal       */
+        /********************************************/
+TIC(decode_params)
+        silk_decode_parameters( psDec, &sDecCtrl );
+TOC(decode_params)
+
+        /* Update length. Sampling frequency may have changed */
+        L = psDec->frame_length;
+
+        /********************************************************/
+        /* Run inverse NSQ                                      */
+        /********************************************************/
+TIC(decode_core)
+        silk_decode_core( psDec, &sDecCtrl, pOut, pulses );
+TOC(decode_core)
+
+        /********************************************************/
+        /* Update PLC state                                     */
+        /********************************************************/
+        silk_PLC( psDec, &sDecCtrl, pOut, L, 0 );
+
+        psDec->lossCnt = 0;
+        psDec->prevSignalType = psDec->indices.signalType;
+        silk_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
+
+        /* A frame has been decoded without errors */
+        psDec->first_frame_after_reset = 0;
+    } else {
+        /* Handle packet loss by extrapolation */
+        silk_PLC( psDec, &sDecCtrl, pOut, L, 1 );
+    }
+
+    /*************************/
+    /* Update output buffer. */
+    /*************************/
+    silk_assert( psDec->ltp_mem_length >= psDec->frame_length );
+    mv_len = psDec->ltp_mem_length - psDec->frame_length;
+    silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
+    silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
+
+    /****************************************************************/
+    /* Ensure smooth connection of extrapolated and good frames     */
+    /****************************************************************/
+    silk_PLC_glue_frames( psDec, &sDecCtrl, pOut, L );
+
+    /************************************************/
+    /* Comfort noise generation / estimation        */
+    /************************************************/
+    silk_CNG( psDec, &sDecCtrl, pOut, L );
+
+    /* Update some decoder state variables */
+    psDec->lagPrev = sDecCtrl.pitchL[ psDec->nb_subfr - 1 ];
+    psDec->nFramesDecoded++;
+
+    /* Set output frame length */
+    *pN = L;
+
+TOC(DECODE_FRAME)
+
+    return ret;
+}
--- /dev/null
+++ b/silk/decode_indices.c
@@ -1,0 +1,157 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Decode side-information parameters from payload */
+void silk_decode_indices(
+    silk_decoder_state      *psDec,             /* I/O  State                                       */
+    ec_dec                      *psRangeDec,        /* I/O  Compressor data structure                   */
+    opus_int                     FrameIndex,         /* I    Frame number                                */
+    opus_int                     decode_LBRR         /* I    Flag indicating LBRR data is being decoded  */
+)
+{
+    opus_int   i, k, Ix, condCoding;
+    opus_int   decode_absolute_lagIndex, delta_lagIndex;
+    opus_int16 ec_ix[ MAX_LPC_ORDER ];
+    opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
+
+    /* Use conditional coding if previous frame available */
+    if( FrameIndex > 0 && ( decode_LBRR == 0 || psDec->LBRR_flags[ FrameIndex - 1 ] == 1 ) ) {
+        condCoding = 1;
+    } else {
+        condCoding = 0;
+    }
+
+    /*******************************************/
+    /* Decode signal type and quantizer offset */
+    /*******************************************/
+    if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] ) {
+        Ix = ec_dec_icdf( psRangeDec, silk_type_offset_VAD_iCDF, 8 ) + 2;
+    } else {
+        Ix = ec_dec_icdf( psRangeDec, silk_type_offset_no_VAD_iCDF, 8 );
+    }
+    psDec->indices.signalType      = (opus_int8)silk_RSHIFT( Ix, 1 );
+    psDec->indices.quantOffsetType = (opus_int8)( Ix & 1 );
+
+    /****************/
+    /* Decode gains */
+    /****************/
+    /* First subframe */
+    if( condCoding ) {
+        /* Conditional coding */
+        psDec->indices.GainsIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
+    } else {
+        /* Independent coding, in two stages: MSB bits followed by 3 LSBs */
+        psDec->indices.GainsIndices[ 0 ]  = (opus_int8)silk_LSHIFT( ec_dec_icdf( psRangeDec, silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 );
+        psDec->indices.GainsIndices[ 0 ] += (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform8_iCDF, 8 );
+    }
+
+    /* Remaining subframes */
+    for( i = 1; i < psDec->nb_subfr; i++ ) {
+        psDec->indices.GainsIndices[ i ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
+    }
+
+    /**********************/
+    /* Decode LSF Indices */
+    /**********************/
+    psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
+    silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
+    silk_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
+    for( i = 0; i < psDec->psNLSF_CB->order; i++ ) {
+        Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
+        if( Ix == 0 ) {
+            Ix -= ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
+        } else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE ) {
+            Ix += ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
+        }
+        psDec->indices.NLSFIndices[ i+1 ] = (opus_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE );
+    }
+
+    /* Decode LSF interpolation factor */
+    if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+        psDec->indices.NLSFInterpCoef_Q2 = (opus_int8)ec_dec_icdf( psRangeDec, silk_NLSF_interpolation_factor_iCDF, 8 );
+    } else {
+        psDec->indices.NLSFInterpCoef_Q2 = 4;
+    }
+
+    if( psDec->indices.signalType == TYPE_VOICED )
+    {
+        /*********************/
+        /* Decode pitch lags */
+        /*********************/
+        /* Get lag index */
+        decode_absolute_lagIndex = 1;
+        if( condCoding && psDec->ec_prevSignalType == TYPE_VOICED ) {
+            /* Decode Delta index */
+            delta_lagIndex = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_delta_iCDF, 8 );
+            if( delta_lagIndex > 0 ) {
+                delta_lagIndex = delta_lagIndex - 9;
+                psDec->indices.lagIndex = (opus_int16)( psDec->ec_prevLagIndex + delta_lagIndex );
+                decode_absolute_lagIndex = 0;
+            }
+        }
+        if( decode_absolute_lagIndex ) {
+            /* Absolute decoding */
+            psDec->indices.lagIndex  = (opus_int16)ec_dec_icdf( psRangeDec, silk_pitch_lag_iCDF, 8 ) * silk_RSHIFT( psDec->fs_kHz, 1 );
+            psDec->indices.lagIndex += (opus_int16)ec_dec_icdf( psRangeDec, psDec->pitch_lag_low_bits_iCDF, 8 );
+        }
+        psDec->ec_prevLagIndex = psDec->indices.lagIndex;
+
+        /* Get countour index */
+        psDec->indices.contourIndex = (opus_int8)ec_dec_icdf( psRangeDec, psDec->pitch_contour_iCDF, 8 );
+
+        /********************/
+        /* Decode LTP gains */
+        /********************/
+        /* Decode PERIndex value */
+        psDec->indices.PERIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_per_index_iCDF, 8 );
+
+        for( k = 0; k < psDec->nb_subfr; k++ ) {
+            psDec->indices.LTPIndex[ k ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTP_gain_iCDF_ptrs[ psDec->indices.PERIndex ], 8 );
+        }
+
+        /**********************/
+        /* Decode LTP scaling */
+        /**********************/
+        if( !condCoding ) {
+            psDec->indices.LTP_scaleIndex = (opus_int8)ec_dec_icdf( psRangeDec, silk_LTPscale_iCDF, 8 );
+        } else {
+            psDec->indices.LTP_scaleIndex = 0;
+        }
+    }
+    psDec->ec_prevSignalType = psDec->indices.signalType;
+
+    /***************/
+    /* Decode seed */
+    /***************/
+    psDec->indices.Seed = (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform4_iCDF, 8 );
+}
--- /dev/null
+++ b/silk/decode_parameters.c
@@ -1,0 +1,115 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Decode parameters from payload */
+void silk_decode_parameters(
+    silk_decoder_state      *psDec,                             /* I/O  State                                    */
+    silk_decoder_control    *psDecCtrl                          /* I/O  Decoder control                          */
+)
+{
+    opus_int   i, k, Ix;
+    opus_int16 pNLSF_Q15[ MAX_LPC_ORDER ], pNLSF0_Q15[ MAX_LPC_ORDER ];
+    const opus_int8 *cbk_ptr_Q7;
+
+    /* Dequant Gains */
+    silk_gains_dequant( psDecCtrl->Gains_Q16, psDec->indices.GainsIndices,
+        &psDec->LastGainIndex, psDec->nFramesDecoded, psDec->nb_subfr );
+
+    /****************/
+    /* Decode NLSFs */
+    /****************/
+    silk_NLSF_decode( pNLSF_Q15, psDec->indices.NLSFIndices, psDec->psNLSF_CB );
+
+    /* Convert NLSF parameters to AR prediction filter coefficients */
+    silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order );
+
+    /* If just reset, e.g., because internal Fs changed, do not allow interpolation */
+    /* improves the case of packet loss in the first frame after a switch           */
+    if( psDec->first_frame_after_reset == 1 ) {
+        psDec->indices.NLSFInterpCoef_Q2 = 4;
+    }
+
+    if( psDec->indices.NLSFInterpCoef_Q2 < 4 ) {
+        /* Calculation of the interpolated NLSF0 vector from the interpolation factor, */
+        /* the previous NLSF1, and the current NLSF1                                   */
+        for( i = 0; i < psDec->LPC_order; i++ ) {
+            pNLSF0_Q15[ i ] = psDec->prevNLSF_Q15[ i ] + silk_RSHIFT( silk_MUL( psDec->indices.NLSFInterpCoef_Q2,
+                pNLSF_Q15[ i ] - psDec->prevNLSF_Q15[ i ] ), 2 );
+        }
+
+        /* Convert NLSF parameters to AR prediction filter coefficients */
+        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( psDec->prevNLSF_Q15, pNLSF_Q15, psDec->LPC_order * sizeof( opus_int16 ) );
+
+    /* After a packet loss do BWE of LPC coefs */
+    if( psDec->lossCnt ) {
+        silk_bwexpander( psDecCtrl->PredCoef_Q12[ 0 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
+        silk_bwexpander( psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order, BWE_AFTER_LOSS_Q16 );
+    }
+
+    if( psDec->indices.signalType == TYPE_VOICED ) {
+        /*********************/
+        /* Decode pitch lags */
+        /*********************/
+
+        /* Decode pitch values */
+        silk_decode_pitch( psDec->indices.lagIndex, psDec->indices.contourIndex, psDecCtrl->pitchL, psDec->fs_kHz, psDec->nb_subfr );
+
+        /* Decode Codebook Index */
+        cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ psDec->indices.PERIndex ]; /* set pointer to start of codebook */
+
+        for( k = 0; k < psDec->nb_subfr; k++ ) {
+            Ix = psDec->indices.LTPIndex[ k ];
+            for( i = 0; i < LTP_ORDER; i++ ) {
+                psDecCtrl->LTPCoef_Q14[ k * LTP_ORDER + i ] = silk_LSHIFT( cbk_ptr_Q7[ Ix * LTP_ORDER + i ], 7 );
+            }
+        }
+
+        /**********************/
+        /* Decode LTP scaling */
+        /**********************/
+        Ix = psDec->indices.LTP_scaleIndex;
+        psDecCtrl->LTP_scale_Q14 = silk_LTPScales_table_Q14[ Ix ];
+    } else {
+        silk_memset( psDecCtrl->pitchL,      0,             psDec->nb_subfr * sizeof( opus_int   ) );
+        silk_memset( psDecCtrl->LTPCoef_Q14, 0, LTP_ORDER * psDec->nb_subfr * sizeof( opus_int16 ) );
+        psDec->indices.PERIndex  = 0;
+        psDecCtrl->LTP_scale_Q14 = 0;
+    }
+}
--- /dev/null
+++ b/silk/decode_pitch.c
@@ -1,0 +1,77 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/***********************************************************
+* Pitch analyser function
+********************************************************** */
+#include "SigProc_FIX.h"
+#include "pitch_est_defines.h"
+
+void silk_decode_pitch(
+    opus_int16       lagIndex,                        /* I                             */
+    opus_int8        contourIndex,                    /* O                             */
+    opus_int         pitch_lags[],                    /* O pitch values                */
+    const opus_int   Fs_kHz,                          /* I sampling frequency (kHz)    */
+    const opus_int   nb_subfr                         /* I number of sub frames        */
+)
+{
+    opus_int   lag, k, min_lag, max_lag, cbk_size;
+    const opus_int8 *Lag_CB_ptr;
+
+    if( Fs_kHz == 8 ) {
+        if( nb_subfr == PE_MAX_NB_SUBFR ) {
+            Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
+            cbk_size   = PE_NB_CBKS_STAGE2_EXT;
+        } else {
+            silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+            Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
+            cbk_size   = PE_NB_CBKS_STAGE2_10MS;
+        }
+    } else {
+        if( nb_subfr == PE_MAX_NB_SUBFR ) {
+            Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
+            cbk_size   = PE_NB_CBKS_STAGE3_MAX;
+        } else {
+            silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+            Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
+            cbk_size   = PE_NB_CBKS_STAGE3_10MS;
+        }
+    }
+
+    min_lag = silk_SMULBB( PE_MIN_LAG_MS, Fs_kHz );
+    max_lag = silk_SMULBB( PE_MAX_LAG_MS, Fs_kHz );
+    lag = min_lag + lagIndex;
+
+    for( k = 0; k < nb_subfr; k++ ) {
+        pitch_lags[ k ] = lag + matrix_ptr( Lag_CB_ptr, k, contourIndex, cbk_size );
+        pitch_lags[ k ] = silk_LIMIT( pitch_lags[ k ], min_lag, max_lag );
+    }
+}
--- /dev/null
+++ b/silk/decode_pulses.c
@@ -1,0 +1,113 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/*********************************************/
+/* Decode quantization indices of excitation */
+/*********************************************/
+void silk_decode_pulses(
+    ec_dec                          *psRangeDec,        /* I/O  Compressor data structure                   */
+    opus_int                         pulses[],           /* O    Excitation signal                           */
+    const opus_int                   signalType,         /* I    Sigtype                                     */
+    const opus_int                   quantOffsetType,    /* I    quantOffsetType                             */
+    const opus_int                   frame_length        /* I    Frame length                                */
+)
+{
+    opus_int   i, j, k, iter, abs_q, nLS, RateLevelIndex;
+    opus_int   sum_pulses[ MAX_NB_SHELL_BLOCKS ], nLshifts[ MAX_NB_SHELL_BLOCKS ];
+    opus_int   *pulses_ptr;
+    const opus_uint8 *cdf_ptr;
+
+    /*********************/
+    /* Decode rate level */
+    /*********************/
+    RateLevelIndex = ec_dec_icdf( psRangeDec, silk_rate_levels_iCDF[ signalType >> 1 ], 8 );
+
+    /* Calculate number of shell blocks */
+    silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
+    iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
+    if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ){
+        silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+        iter++;
+    }
+
+    /***************************************************/
+    /* Sum-Weighted-Pulses Decoding                    */
+    /***************************************************/
+    cdf_ptr = silk_pulses_per_block_iCDF[ RateLevelIndex ];
+    for( i = 0; i < iter; i++ ) {
+        nLshifts[ i ] = 0;
+        sum_pulses[ i ] = ec_dec_icdf( psRangeDec, cdf_ptr, 8 );
+
+        /* LSB indication */
+        while( sum_pulses[ i ] == MAX_PULSES + 1 ) {
+            nLshifts[ i ]++;
+            /* When we've already got 10 LSBs, we shift the table to not allow (MAX_PULSES + 1) */
+            sum_pulses[ i ] = ec_dec_icdf( psRangeDec,
+                    silk_pulses_per_block_iCDF[ N_RATE_LEVELS - 1] + (nLshifts[ i ]==10), 8 );
+        }
+    }
+
+    /***************************************************/
+    /* Shell decoding                                  */
+    /***************************************************/
+    for( i = 0; i < iter; i++ ) {
+        if( sum_pulses[ i ] > 0 ) {
+            silk_shell_decoder( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], psRangeDec, sum_pulses[ i ] );
+        } else {
+            silk_memset( &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof( opus_int ) );
+        }
+    }
+
+    /***************************************************/
+    /* LSB Decoding                                    */
+    /***************************************************/
+    for( i = 0; i < iter; i++ ) {
+        if( nLshifts[ i ] > 0 ) {
+            nLS = nLshifts[ i ];
+            pulses_ptr = &pulses[ silk_SMULBB( i, SHELL_CODEC_FRAME_LENGTH ) ];
+            for( k = 0; k < SHELL_CODEC_FRAME_LENGTH; k++ ) {
+                abs_q = pulses_ptr[ k ];
+                for( j = 0; j < nLS; j++ ) {
+                    abs_q = silk_LSHIFT( abs_q, 1 );
+                    abs_q += ec_dec_icdf( psRangeDec, silk_lsb_iCDF, 8 );
+                }
+                pulses_ptr[ k ] = abs_q;
+            }
+        }
+    }
+
+    /****************************************/
+    /* Decode and add signs to pulse signal */
+    /****************************************/
+    silk_decode_signs( psRangeDec, pulses, frame_length, signalType, quantOffsetType, sum_pulses );
+}
--- /dev/null
+++ b/silk/decoder_set_fs.c
@@ -1,0 +1,97 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "main.h"
+
+/* Set decoder sampling rate */
+void silk_decoder_set_fs(
+    silk_decoder_state              *psDec,             /* I/O  Decoder state pointer                       */
+    opus_int                         fs_kHz              /* I    Sampling frequency (kHz)                    */
+)
+{
+    opus_int frame_length;
+
+    silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+    silk_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
+
+    psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz );
+    frame_length = silk_SMULBB( psDec->nb_subfr, psDec->subfr_length );
+    if( psDec->fs_kHz != fs_kHz || frame_length != psDec->frame_length ) {
+        psDec->fs_kHz  = fs_kHz;
+        psDec->frame_length   = frame_length;
+        psDec->ltp_mem_length = silk_SMULBB( LTP_MEM_LENGTH_MS, fs_kHz );
+        if( psDec->fs_kHz == 8 ) {
+            if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+                psDec->pitch_contour_iCDF = silk_pitch_contour_NB_iCDF;
+            } else {
+                psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_NB_iCDF;
+            }
+        } else {
+            if( psDec->nb_subfr == MAX_NB_SUBFR ) {
+                psDec->pitch_contour_iCDF = silk_pitch_contour_iCDF;
+            } else {
+                psDec->pitch_contour_iCDF = silk_pitch_contour_10_ms_iCDF;
+            }
+        }
+        if( psDec->fs_kHz == 8 || psDec->fs_kHz == 12 ) {
+            psDec->LPC_order = MIN_LPC_ORDER;
+            psDec->psNLSF_CB = &silk_NLSF_CB_NB_MB;
+        } else {
+            psDec->LPC_order = MAX_LPC_ORDER;
+            psDec->psNLSF_CB = &silk_NLSF_CB_WB;
+        }
+
+        /* Reset part of the decoder state */
+        silk_memset( psDec->sLPC_Q14,     0,                    sizeof( psDec->sLPC_Q14 ) );
+        silk_memset( psDec->outBuf,       0, MAX_FRAME_LENGTH * sizeof( opus_int16 ) );
+        silk_memset( psDec->prevNLSF_Q15, 0,                    sizeof( psDec->prevNLSF_Q15 ) );
+
+        psDec->lagPrev                 = 100;
+        psDec->LastGainIndex           = 10;
+        psDec->prevSignalType          = TYPE_NO_VOICE_ACTIVITY;
+        psDec->first_frame_after_reset = 1;
+
+        if( fs_kHz == 16 ) {
+            psDec->pitch_lag_low_bits_iCDF = silk_uniform8_iCDF;
+        } else if( fs_kHz == 12 ) {
+            psDec->pitch_lag_low_bits_iCDF = silk_uniform6_iCDF;
+        } else if( fs_kHz == 8 ) {
+            psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
+        } else {
+            /* unsupported sampling rate */
+            silk_assert( 0 );
+        }
+    }
+
+    /* Check that settings are valid */
+    silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
+}
+
--- /dev/null
+++ b/silk/define.h
@@ -1,0 +1,233 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Skype Limited, nor the names of specific
+contributors, may be used to endorse or promote products derived from
+this software without specific prior written permission.
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
+BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_DEFINE_H
+#define SILK_DEFINE_H
+
+#include "errors.h"
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Max number of encoder channels (1/2) */
+#define ENCODER_NUM_CHANNELS                    2
+/* Number of decoder channels (1/2) */
+#define DECODER_NUM_CHANNELS                    2
+
+#define MAX_FRAMES_PER_PACKET                   3
+
+/* Limits on bitrate */
+#define MIN_TARGET_RATE_BPS                     5000
+#define MAX_TARGET_RATE_BPS                     80000
+#define TARGET_RATE_TAB_SZ                      8
+
+/* LBRR thresholds */
+#define LBRR_NB_MIN_RATE_BPS                    12000
+#define LBRR_MB_MIN_RATE_BPS                    14000
+#define LBRR_WB_MIN_RATE_BPS                    16000
+
+/* DTX settings */
+#define NB_SPEECH_FRAMES_BEFORE_DTX             10      /* eq 200 ms */
+#define MAX_CONSECUTIVE_DTX                     20      /* eq 400 ms */
+
+/* Maximum sampling frequency, should be 16 for embedded */
+#define MAX_FS_KHZ                              16
+#define MAX_API_FS_KHZ                          48
+
+/* Signal types */
+#define TYPE_NO_VOICE_ACTIVITY                  0
+#define TYPE_UNVOICED                           1
+#define TYPE_VOICED                             2
+
+/* Settings for stereo processing */
+#define STEREO_QUANT_TAB_SIZE                   16
+#define STEREO_QUANT_SUB_STEPS                  5
+#define STEREO_INTERP_LEN_MS                    8           /* must be even */
+#define STEREO_RATIO_SMOOTH_COEF                0.01        /* smoothing coef for signal norms and stereo width */
+
+/* Range of pitch lag estimates */
+#define PITCH_EST_MIN_LAG_MS                    2           /* 2 ms -> 500 Hz */
+#define PITCH_EST_MAX_LAG_MS                    18          /* 18 ms -> 56 Hz */
+
+/* Maximum number of subframes */
+#define MAX_NB_SUBFR                            4
+
+/* Number of samples per frame */
+#define LTP_MEM_LENGTH_MS                       20
+#define SUB_FRAME_LENGTH_MS                     5
+#define MAX_SUB_FRAME_LENGTH                    ( SUB_FRAME_LENGTH_MS * MAX_FS_KHZ )
+#define MAX_FRAME_LENGTH_MS                     ( SUB_FRAME_LENGTH_MS * MAX_NB_SUBFR )
+#define MAX_FRAME_LENGTH                        ( MAX_FRAME_LENGTH_MS * MAX_FS_KHZ )
+
+/* Milliseconds of lookahead for pitch analysis */
+#define LA_PITCH_MS                             2
+#define LA_PITCH_MAX                            ( LA_PITCH_MS * MAX_FS_KHZ )
+
+/* Order of LPC used in find pitch */
+#define MAX_FIND_PITCH_LPC_ORDER                16
+
+/* Length of LPC window used in find pitch */
+#define FIND_PITCH_LPC_WIN_MS                   ( 20 + (LA_PITCH_MS << 1) )
+#define FIND_PITCH_LPC_WIN_MS_2_SF              ( 10 + (LA_PITCH_MS << 1) )
+#define FIND_PITCH_LPC_WIN_MAX                  ( FIND_PITCH_LPC_WIN_MS * MAX_FS_KHZ )
+
+/* Milliseconds of lookahead for noise shape analysis */
+#define LA_SHAPE_MS                             5
+#define LA_SHAPE_MAX                            ( LA_SHAPE_MS * MAX_FS_KHZ )
+
+/* Maximum length of LPC window used in noise shape analysis */
+#define SHAPE_LPC_WIN_MAX                       ( 15 * MAX_FS_KHZ )
+
+/* dB level of lowest gain quantization level */
+#define MIN_QGAIN_DB                            2
+/* dB level of highest gain quantization level */
+#define MAX_QGAIN_DB                            88
+/* Number of gain quantization levels */
+#define N_LEVELS_QGAIN                          64
+/* Max increase in gain quantization index */
+#define MAX_DELTA_GAIN_QUANT                    36
+/* Max decrease in gain quantization index */
+#define MIN_DELTA_GAIN_QUANT                    -4
+
+/* Quantization offsets (multiples of 4) */
+#define OFFSET_VL_Q10                           32
+#define OFFSET_VH_Q10                           100
+#define OFFSET_UVL_Q10                          100
+#define OFFSET_UVH_Q10                          240
+
+#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_ORDER                           16
+#define MIN_LPC_ORDER                           10
+
+/* Find Pred Coef defines */
+#define LTP_ORDER                               5
+
+/* LTP quantization settings */
+#define NB_LTP_CBKS                             3
+
+/* Flag to use harmonic noise shaping */
+#define USE_HARM_SHAPING                        1
+
+/* Max LPC order of noise shaping filters */
+#define MAX_SHAPE_LPC_ORDER                     16
+
+#define HARM_SHAPE_FIR_TAPS                     3
+
+/* Maximum number of delayed decision states */
+#define MAX_DEL_DEC_STATES                      4
+
+#define LTP_BUF_LENGTH                          512
+#define LTP_MASK                                ( LTP_BUF_LENGTH - 1 )
+
+#define DECISION_DELAY                          32
+#define DECISION_DELAY_MASK                     ( DECISION_DELAY - 1 )
+
+/* Number of subframes for excitation entropy coding */
+#define SHELL_CODEC_FRAME_LENGTH                16
+#define LOG2_SHELL_CODEC_FRAME_LENGTH           4
+#define MAX_NB_SHELL_BLOCKS                     ( MAX_FRAME_LENGTH / SHELL_CODEC_FRAME_LENGTH )
+
+/* Number of rate levels, for entropy coding of excitation */
+#define N_RATE_LEVELS                           10
+
+/* Maximum sum of pulses per shell coding frame */
+#define MAX_PULSES                              16
+
+#define MAX_MATRIX_SIZE                         MAX_LPC_ORDER /* Max of LPC Order and LTP order */
+
+#if( MAX_LPC_ORDER > DECISION_DELAY )
+# define NSQ_LPC_BUF_LENGTH                     MAX_LPC_ORDER
+#else
+# define NSQ_LPC_BUF_LENGTH                     DECISION_DELAY
+#endif
+
+/***********************/
+/* High pass filtering */
+/***********************/
+#define HIGH_PASS_INPUT                         1
+
+/***************************/
+/* Voice activity detector */
+/***************************/
+#define VAD_N_BANDS                             4
+
+#define VAD_INTERNAL_SUBFRAMES_LOG2             2
+#define VAD_INTERNAL_SUBFRAMES                  (1 << VAD_INTERNAL_SUBFRAMES_LOG2)
+
+#define VAD_NOISE_LEVEL_SMOOTH_COEF_Q16         1024    /* Must be <  4096                                  */
+#define VAD_NOISE_LEVELS_BIAS                   50
+
+/* Sigmoid settings */
+#define VAD_NEGATIVE_OFFSET_Q5                  128     /* sigmoid is 0 at -128                             */
+#define VAD_SNR_FACTOR_Q16                      45000
+
+/* smoothing for SNR measurement */
+#define VAD_SNR_SMOOTH_COEF_Q18                 4096
+
+/* Size of the piecewise linear cosine approximation table for the LSFs */
+#define LSF_COS_TAB_SZ_FIX                      128
+
+/******************/
+/* NLSF quantizer */
+/******************/
+#define NLSF_W_Q                                2
+#define NLSF_VQ_MAX_VECTORS                     32
+#define NLSF_VQ_MAX_SURVIVORS                   32
+#define NLSF_QUANT_MAX_AMPLITUDE                4
+#define NLSF_QUANT_MAX_AMPLITUDE_EXT            10
+#define NLSF_QUANT_LEVEL_ADJ                    0.1
+#define NLSF_QUANT_DEL_DEC_STATES_LOG2          2
+#define NLSF_QUANT_DEL_DEC_STATES               ( 1 << NLSF_QUANT_DEL_DEC_STATES_LOG2 )
+
+/* Transition filtering for mode switching */
+#  define TRANSITION_TIME_MS                    5120 /* 5120 = 64 * FRAME_LENGTH_MS * ( TRANSITION_INT_NUM - 1 ) = 64*(20*4)*/
+#  define TRANSITION_NB                         3 /* Hardcoded in tables */
+#  define TRANSITION_NA                         2 /* Hardcoded in tables */
+#  define TRANSITION_INT_NUM                    5 /* Hardcoded in tables */
+#  define TRANSITION_FRAMES                     ( TRANSITION_TIME_MS / MAX_FRAME_LENGTH_MS ) /* todo: needs to be made flexible for 10 ms frames*/
+#  define TRANSITION_INT_STEPS                  ( TRANSITION_FRAMES  / ( TRANSITION_INT_NUM - 1 ) )
+
+/* BWE factors to apply after packet loss */
+#define BWE_AFTER_LOSS_Q16                      63570
+
+/* Defines for CN generation */
+#define CNG_BUF_MASK_MAX                        255             /* 2^floor(log2(MAX_FRAME_LENGTH))-1    */
+#define CNG_GAIN_SMTH_Q16                       4634            /* 0.25^(1/4)                           */
+#define CNG_NLSF_SMTH_Q16                       16348           /* 0.25                                 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+++ b/silk/enc_API.c
@@ -1,0 +1,418 @@
+/***********************************************************************
+Copyright (c) 2006-2011, Skype Limited. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, (subject to the limitations in the disclaimer below)
+are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentat