Bug 1372393 - opus: Update to 1.2-rc1. r=kinetik draft
authorRalph Giles <giles@mozilla.com>
Mon, 12 Jun 2017 14:29:32 -0700
changeset 594880 52f1b69cc24fccc13781686c636d37323af0a640
parent 594879 9a581ef7160dfd297eca08ddd1cb1dc744527f18
child 594881 2f7fc83cbe0184b38710dd5c2e74d9e7a494c31f
push id64188
push userbmo:giles@thaumas.net
push dateThu, 15 Jun 2017 17:37:30 +0000
reviewerskinetik
bugs1372393
milestone56.0a1
Bug 1372393 - opus: Update to 1.2-rc1. r=kinetik Update our in-tree implementation of the opus audio codec to the 1.2 release candidiate. This gives us some wider testing before making the first stable release of the new series. This release improves the quality and compactness of encoded audio, and optimizes performance on ARM NEON platforms. MozReview-Commit-ID: 30bM6iVBamd
media/libopus/README_MOZILLA
media/libopus/celt/_kiss_fft_guts.h
media/libopus/celt/arch.h
media/libopus/celt/arm/arm2gnu.pl
media/libopus/celt/arm/arm_celt_map.c
media/libopus/celt/arm/celt_ne10_fft.c
media/libopus/celt/arm/celt_neon_intr.c
media/libopus/celt/arm/celt_pitch_xcorr_arm.s
media/libopus/celt/arm/fft_arm.h
media/libopus/celt/arm/fixed_armv4.h
media/libopus/celt/arm/fixed_armv5e.h
media/libopus/celt/arm/mdct_arm.h
media/libopus/celt/arm/pitch_arm.h
media/libopus/celt/arm/pitch_neon_intr.c
media/libopus/celt/bands.c
media/libopus/celt/bands.h
media/libopus/celt/celt.c
media/libopus/celt/celt.h
media/libopus/celt/celt_decoder.c
media/libopus/celt/celt_encoder.c
media/libopus/celt/celt_lpc.c
media/libopus/celt/celt_lpc.h
media/libopus/celt/fixed_debug.h
media/libopus/celt/fixed_generic.h
media/libopus/celt/float_cast.h
media/libopus/celt/kiss_fft.c
media/libopus/celt/mathops.h
media/libopus/celt/mdct.c
media/libopus/celt/mips/vq_mipsr1.h
media/libopus/celt/modes.c
media/libopus/celt/pitch.c
media/libopus/celt/pitch.h
media/libopus/celt/quant_bands.c
media/libopus/celt/rate.c
media/libopus/celt/static_modes_fixed_arm_ne10.h
media/libopus/celt/static_modes_float_arm_ne10.h
media/libopus/celt/vq.c
media/libopus/celt/vq.h
media/libopus/celt/x86/celt_lpc_sse.c
media/libopus/celt/x86/celt_lpc_sse.h
media/libopus/celt/x86/vq_sse.h
media/libopus/celt/x86/vq_sse2.c
media/libopus/celt/x86/x86_celt_map.c
media/libopus/include/opus_defines.h
media/libopus/include/opus_multistream.h
media/libopus/include/opus_types.h
media/libopus/moz.build
media/libopus/silk/A2NLSF.c
media/libopus/silk/CNG.c
media/libopus/silk/LPC_analysis_filter.c
media/libopus/silk/LPC_fit.c
media/libopus/silk/LPC_inv_pred_gain.c
media/libopus/silk/LP_variable_cutoff.c
media/libopus/silk/MacroCount.h
media/libopus/silk/MacroDebug.h
media/libopus/silk/NLSF2A.c
media/libopus/silk/NLSF_VQ.c
media/libopus/silk/NLSF_decode.c
media/libopus/silk/NLSF_del_dec_quant.c
media/libopus/silk/NLSF_encode.c
media/libopus/silk/NSQ.c
media/libopus/silk/NSQ_del_dec.c
media/libopus/silk/PLC.c
media/libopus/silk/SigProc_FIX.h
media/libopus/silk/VQ_WMat_EC.c
media/libopus/silk/arm/LPC_inv_pred_gain_arm.h
media/libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c
media/libopus/silk/arm/NSQ_del_dec_arm.h
media/libopus/silk/arm/NSQ_del_dec_neon_intr.c
media/libopus/silk/arm/NSQ_neon.h
media/libopus/silk/arm/arm_silk_map.c
media/libopus/silk/arm/biquad_alt_arm.h
media/libopus/silk/arm/biquad_alt_neon_intr.c
media/libopus/silk/arm/macros_armv4.h
media/libopus/silk/arm/macros_armv5e.h
media/libopus/silk/biquad_alt.c
media/libopus/silk/bwexpander.c
media/libopus/silk/control.h
media/libopus/silk/control_SNR.c
media/libopus/silk/control_codec.c
media/libopus/silk/debug.h
media/libopus/silk/decode_core.c
media/libopus/silk/decode_frame.c
media/libopus/silk/decode_parameters.c
media/libopus/silk/define.h
media/libopus/silk/enc_API.c
media/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h
media/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c
media/libopus/silk/fixed/burg_modified_FIX.c
media/libopus/silk/fixed/corrMatrix_FIX.c
media/libopus/silk/fixed/encode_frame_FIX.c
media/libopus/silk/fixed/find_LPC_FIX.c
media/libopus/silk/fixed/find_LTP_FIX.c
media/libopus/silk/fixed/find_pitch_lags_FIX.c
media/libopus/silk/fixed/find_pred_coefs_FIX.c
media/libopus/silk/fixed/k2a_FIX.c
media/libopus/silk/fixed/k2a_Q16_FIX.c
media/libopus/silk/fixed/main_FIX.h
media/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
media/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h
media/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
media/libopus/silk/fixed/noise_shape_analysis_FIX.c
media/libopus/silk/fixed/pitch_analysis_core_FIX.c
media/libopus/silk/fixed/prefilter_FIX.c
media/libopus/silk/fixed/schur64_FIX.c
media/libopus/silk/fixed/schur_FIX.c
media/libopus/silk/fixed/solve_LS_FIX.c
media/libopus/silk/fixed/structs_FIX.h
media/libopus/silk/fixed/warped_autocorrelation_FIX.c
media/libopus/silk/fixed/x86/prefilter_FIX_sse.c
media/libopus/silk/float/LPC_inv_pred_gain_FLP.c
media/libopus/silk/float/SigProc_FLP.h
media/libopus/silk/float/encode_frame_FLP.c
media/libopus/silk/float/energy_FLP.c
media/libopus/silk/float/find_LPC_FLP.c
media/libopus/silk/float/find_LTP_FLP.c
media/libopus/silk/float/find_pred_coefs_FLP.c
media/libopus/silk/float/inner_product_FLP.c
media/libopus/silk/float/k2a_FLP.c
media/libopus/silk/float/levinsondurbin_FLP.c
media/libopus/silk/float/main_FLP.h
media/libopus/silk/float/noise_shape_analysis_FLP.c
media/libopus/silk/float/pitch_analysis_core_FLP.c
media/libopus/silk/float/prefilter_FLP.c
media/libopus/silk/float/schur_FLP.c
media/libopus/silk/float/solve_LS_FLP.c
media/libopus/silk/float/structs_FLP.h
media/libopus/silk/float/wrappers_FLP.c
media/libopus/silk/gain_quant.c
media/libopus/silk/init_decoder.c
media/libopus/silk/lin2log.c
media/libopus/silk/macros.h
media/libopus/silk/main.h
media/libopus/silk/mips/NSQ_del_dec_mipsr1.h
media/libopus/silk/mips/sigproc_fix_mipsr1.h
media/libopus/silk/process_NLSFs.c
media/libopus/silk/quant_LTP_gains.c
media/libopus/silk/structs.h
media/libopus/silk/sum_sqr_shift.c
media/libopus/silk/tables.h
media/libopus/silk/tables_LTP.c
media/libopus/silk/tables_NLSF_CB_NB_MB.c
media/libopus/silk/tables_NLSF_CB_WB.c
media/libopus/silk/tuning_parameters.h
media/libopus/silk/x86/NSQ_del_dec_sse.c
media/libopus/silk/x86/NSQ_sse.c
media/libopus/silk/x86/main_sse.h
media/libopus/silk/x86/x86_silk_map.c
media/libopus/sources.mozbuild
media/libopus/src/analysis.c
media/libopus/src/analysis.h
media/libopus/src/mlp_data.c
media/libopus/src/opus.c
media/libopus/src/opus_decoder.c
media/libopus/src/opus_encoder.c
media/libopus/src/opus_multistream_decoder.c
media/libopus/src/opus_multistream_encoder.c
media/libopus/src/opus_private.h
--- a/media/libopus/README_MOZILLA
+++ b/media/libopus/README_MOZILLA
@@ -3,9 +3,9 @@ IETF Opus audio codec reference implemen
 The source in this directory was copied from an opus
 repository checkout by running the ./update.sh script.
 Any changes made to this version of the source should
 be reflected in that script, e.g. by applying patch
 files after the copy step.
 
 The upstream repository is https://git.xiph.org/opus.git
 
-The git tag/revision used was v1.1.5.
+The git tag/revision used was v1.2-rc1.
--- a/media/libopus/celt/_kiss_fft_guts.h
+++ b/media/libopus/celt/_kiss_fft_guts.h
@@ -53,46 +53,46 @@
 #define TRIG_UPSCALE 1
 
 #define SAMP_MIN -SAMP_MAX
 
 
 #   define S_MUL(a,b) MULT16_32_Q15(b, a)
 
 #   define C_MUL(m,a,b) \
-      do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
-          (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
+      do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+          (m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
 
 #   define C_MULC(m,a,b) \
-      do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
-          (m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
+      do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+          (m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
 
 #   define C_MULBYSCALAR( c, s ) \
       do{ (c).r =  S_MUL( (c).r , s ) ;\
           (c).i =  S_MUL( (c).i , s ) ; }while(0)
 
 #   define DIVSCALAR(x,k) \
         (x) = S_MUL(  x, (TWID_MAX-((k)>>1))/(k)+1 )
 
 #   define C_FIXDIV(c,div) \
         do {    DIVSCALAR( (c).r , div);  \
                 DIVSCALAR( (c).i  , div); }while (0)
 
 #define  C_ADD( res, a,b)\
-    do {(res).r=ADD32((a).r,(b).r);  (res).i=ADD32((a).i,(b).i); \
+    do {(res).r=ADD32_ovflw((a).r,(b).r);  (res).i=ADD32_ovflw((a).i,(b).i); \
     }while(0)
 #define  C_SUB( res, a,b)\
-    do {(res).r=SUB32((a).r,(b).r);  (res).i=SUB32((a).i,(b).i); \
+    do {(res).r=SUB32_ovflw((a).r,(b).r);  (res).i=SUB32_ovflw((a).i,(b).i); \
     }while(0)
 #define C_ADDTO( res , a)\
-    do {(res).r = ADD32((res).r, (a).r);  (res).i = ADD32((res).i,(a).i);\
+    do {(res).r = ADD32_ovflw((res).r, (a).r);  (res).i = ADD32_ovflw((res).i,(a).i);\
     }while(0)
 
 #define C_SUBFROM( res , a)\
-    do {(res).r = ADD32((res).r,(a).r);  (res).i = SUB32((res).i,(a).i); \
+    do {(res).r = ADD32_ovflw((res).r,(a).r);  (res).i = SUB32_ovflw((res).i,(a).i); \
     }while(0)
 
 #if defined(OPUS_ARM_INLINE_ASM)
 #include "arm/kiss_fft_armv4.h"
 #endif
 
 #if defined(OPUS_ARM_INLINE_EDSP)
 #include "arm/kiss_fft_armv5e.h"
--- a/media/libopus/celt/arch.h
+++ b/media/libopus/celt/arch.h
@@ -41,16 +41,24 @@
 #  if defined(__GNUC__)&&defined(__GNUC_MINOR__)
 #   define __GNUC_PREREQ(_maj,_min) \
  ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
 #  else
 #   define __GNUC_PREREQ(_maj,_min) 0
 #  endif
 # endif
 
+#if OPUS_GNUC_PREREQ(3, 0)
+#define opus_likely(x)       (__builtin_expect(!!(x), 1))
+#define opus_unlikely(x)     (__builtin_expect(!!(x), 0))
+#else
+#define opus_likely(x)       (!!(x))
+#define opus_unlikely(x)     (!!(x))
+#endif
+
 #define CELT_SIG_SCALE 32768.f
 
 #define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__);
 #ifdef ENABLE_ASSERTIONS
 #include <stdio.h>
 #include <stdlib.h>
 #ifdef __GNUC__
 __attribute__((noreturn))
@@ -88,24 +96,28 @@ static OPUS_INLINE void _celt_fatal(cons
 #endif
 
 #define PRINT_MIPS(file)
 
 #ifdef FIXED_POINT
 
 typedef opus_int16 opus_val16;
 typedef opus_int32 opus_val32;
+typedef opus_int64 opus_val64;
 
 typedef opus_val32 celt_sig;
 typedef opus_val16 celt_norm;
 typedef opus_val32 celt_ener;
 
 #define Q15ONE 32767
 
 #define SIG_SHIFT 12
+/* Safe saturation value for 32-bit signals. Should be less than
+   2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/
+#define SIG_SAT (300000000)
 
 #define NORM_SCALING 16384
 
 #define DB_SHIFT 10
 
 #define EPSILON 1
 #define VERY_SMALL 0
 #define VERY_LARGE16 ((opus_val16)32767)
@@ -142,16 +154,17 @@ static OPUS_INLINE opus_int16 SAT16(opus
 #endif
 
 #endif
 
 #else /* FIXED_POINT */
 
 typedef float opus_val16;
 typedef float opus_val32;
+typedef float opus_val64;
 
 typedef float celt_sig;
 typedef float celt_norm;
 typedef float celt_ener;
 
 #ifdef FLOAT_APPROX
 /* This code should reliably detect NaN/inf even when -ffast-math is used.
    Assumes IEEE 754 format. */
@@ -181,39 +194,43 @@ static OPUS_INLINE int celt_isnan(float 
 #define ABS16(x) ((float)fabs(x))
 #define ABS32(x) ((float)fabs(x))
 
 #define QCONST16(x,bits) (x)
 #define QCONST32(x,bits) (x)
 
 #define NEG16(x) (-(x))
 #define NEG32(x) (-(x))
+#define NEG32_ovflw(x) (-(x))
 #define EXTRACT16(x) (x)
 #define EXTEND32(x) (x)
 #define SHR16(a,shift) (a)
 #define SHL16(a,shift) (a)
 #define SHR32(a,shift) (a)
 #define SHL32(a,shift) (a)
 #define PSHR32(a,shift) (a)
 #define VSHR32(a,shift) (a)
 
 #define PSHR(a,shift)   (a)
 #define SHR(a,shift)    (a)
 #define SHL(a,shift)    (a)
 #define SATURATE(x,a)   (x)
 #define SATURATE16(x)   (x)
 
 #define ROUND16(a,shift)  (a)
+#define SROUND16(a,shift) (a)
 #define HALF16(x)       (.5f*(x))
 #define HALF32(x)       (.5f*(x))
 
 #define ADD16(a,b) ((a)+(b))
 #define SUB16(a,b) ((a)-(b))
 #define ADD32(a,b) ((a)+(b))
 #define SUB32(a,b) ((a)-(b))
+#define ADD32_ovflw(a,b) ((a)+(b))
+#define SUB32_ovflw(a,b) ((a)-(b))
 #define MULT16_16_16(a,b)     ((a)*(b))
 #define MULT16_16(a,b)     ((opus_val32)(a)*(opus_val32)(b))
 #define MAC16_16(c,a,b)     ((c)+(opus_val32)(a)*(opus_val32)(b))
 
 #define MULT16_32_Q15(a,b)     ((a)*(b))
 #define MULT16_32_Q16(a,b)     ((a)*(b))
 
 #define MULT32_32_Q31(a,b)     ((a)*(b))
@@ -238,15 +255,15 @@ static OPUS_INLINE int celt_isnan(float 
 #define SCALEOUT(a)     ((a)*(1/CELT_SIG_SCALE))
 
 #define SIG2WORD16(x) (x)
 
 #endif /* !FIXED_POINT */
 
 #ifndef GLOBAL_STACK_SIZE
 #ifdef FIXED_POINT
-#define GLOBAL_STACK_SIZE 100000
+#define GLOBAL_STACK_SIZE 120000
 #else
-#define GLOBAL_STACK_SIZE 100000
+#define GLOBAL_STACK_SIZE 120000
 #endif
 #endif
 
 #endif /* ARCH_H */
--- a/media/libopus/celt/arm/arm2gnu.pl
+++ b/media/libopus/celt/arm/arm2gnu.pl
@@ -159,21 +159,21 @@ while (<>) {
     {
         my $prefix;
         my $proc;
         /^([A-Za-z_\.]\w+)\b/;
         $proc = $1;
         $prefix = "";
         if ($proc)
         {
-            $prefix = $prefix.sprintf("\t.type\t%s, %%function; ",$proc) unless ($apple);
+            $prefix = $prefix.sprintf("\t.type\t%s, %%function", $proc) unless ($apple);
             # Make sure we $prefix isn't empty here (for the $apple case).
             # We handle mangling the label here, make sure it doesn't match
             # the label handling below (if $prefix would be empty).
-            $prefix = "; ";
+            $prefix = $prefix."; ";
             push(@proc_stack, $proc);
             s/^[A-Za-z_\.]\w+/$symprefix$&:/;
         }
         $prefix = $prefix."\t.thumb_func; " if ($thumb);
         s/\bPROC\b/@ $&/;
         $_ = $prefix.$_;
     }
     s/^(\s*)(S|Q|SH|U|UQ|UH)ASX\b/$1$2ADDSUBX/;
--- a/media/libopus/celt/arm/arm_celt_map.c
+++ b/media/libopus/celt/arm/arm_celt_map.c
@@ -30,33 +30,50 @@
 #endif
 
 #include "pitch.h"
 #include "kiss_fft.h"
 #include "mdct.h"
 
 #if defined(OPUS_HAVE_RTCD)
 
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
+opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N) = {
+  celt_inner_prod_c,   /* ARMv4 */
+  celt_inner_prod_c,   /* EDSP */
+  celt_inner_prod_c,   /* Media */
+  celt_inner_prod_neon /* NEON */
+};
+
+void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+      int N, opus_val32 *xy1, opus_val32 *xy2) = {
+  dual_inner_prod_c,   /* ARMv4 */
+  dual_inner_prod_c,   /* EDSP */
+  dual_inner_prod_c,   /* Media */
+  dual_inner_prod_neon /* NEON */
+};
+# endif
+
 # if defined(FIXED_POINT)
 #  if ((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \
     (defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \
     (defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
 opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
-    const opus_val16 *, opus_val32 *, int , int) = {
+    const opus_val16 *, opus_val32 *, int, int, int) = {
   celt_pitch_xcorr_c,               /* ARMv4 */
   MAY_HAVE_EDSP(celt_pitch_xcorr),  /* EDSP */
   MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */
   MAY_HAVE_NEON(celt_pitch_xcorr)   /* NEON */
 };
 
 #  endif
 # else /* !FIXED_POINT */
 #  if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
 void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
-    const opus_val16 *, opus_val32 *, int, int) = {
+    const opus_val16 *, opus_val32 *, int, int, int) = {
   celt_pitch_xcorr_c,              /* ARMv4 */
   celt_pitch_xcorr_c,              /* EDSP */
   celt_pitch_xcorr_c,              /* Media */
   celt_pitch_xcorr_float_neon      /* Neon */
 };
 #  endif
 # endif /* FIXED_POINT */
 
--- a/media/libopus/celt/arm/celt_ne10_fft.c
+++ b/media/libopus/celt/arm/celt_ne10_fft.c
@@ -31,17 +31,16 @@
 */
 
 #ifndef SKIP_CONFIG_H
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #endif
 
-#include <NE10_init.h>
 #include <NE10_dsp.h>
 #include "os_support.h"
 #include "kiss_fft.h"
 #include "stack_alloc.h"
 
 #if !defined(FIXED_POINT)
 # define NE10_FFT_ALLOC_C2C_TYPE_NEON ne10_fft_alloc_c2c_float32_neon
 # define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_float32_t
--- a/media/libopus/celt/arm/celt_neon_intr.c
+++ b/media/libopus/celt/arm/celt_neon_intr.c
@@ -186,126 +186,26 @@ static void xcorr_kernel_neon_float(cons
    }
 
    XX_2 = vld1_dup_f32(xi);
    SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0);
 
    vst1q_f32(sum, SUMM);
 }
 
-/*
- * Function: xcorr_kernel_neon_float_process1
- * ---------------------------------
- * Computes single correlation values and stores in *sum
- */
-static void xcorr_kernel_neon_float_process1(const float32_t *x,
-      const float32_t *y, float32_t *sum, int len) {
-   float32x4_t XX[4];
-   float32x4_t YY[4];
-   float32x2_t XX_2;
-   float32x2_t YY_2;
-   float32x4_t SUMM;
-   float32x2_t SUMM_2[2];
-   const float32_t *xi = x;
-   const float32_t *yi = y;
-
-   SUMM = vdupq_n_f32(0);
-
-   /* Work on 16 values per iteration */
-   while (len >= 16) {
-      XX[0] = vld1q_f32(xi);
-      xi += 4;
-      XX[1] = vld1q_f32(xi);
-      xi += 4;
-      XX[2] = vld1q_f32(xi);
-      xi += 4;
-      XX[3] = vld1q_f32(xi);
-      xi += 4;
-
-      YY[0] = vld1q_f32(yi);
-      yi += 4;
-      YY[1] = vld1q_f32(yi);
-      yi += 4;
-      YY[2] = vld1q_f32(yi);
-      yi += 4;
-      YY[3] = vld1q_f32(yi);
-      yi += 4;
-
-      SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
-      SUMM = vmlaq_f32(SUMM, YY[1], XX[1]);
-      SUMM = vmlaq_f32(SUMM, YY[2], XX[2]);
-      SUMM = vmlaq_f32(SUMM, YY[3], XX[3]);
-      len -= 16;
-   }
-
-   /* Work on 8 values */
-   if (len >= 8) {
-      XX[0] = vld1q_f32(xi);
-      xi += 4;
-      XX[1] = vld1q_f32(xi);
-      xi += 4;
-
-      YY[0] = vld1q_f32(yi);
-      yi += 4;
-      YY[1] = vld1q_f32(yi);
-      yi += 4;
-
-      SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
-      SUMM = vmlaq_f32(SUMM, YY[1], XX[1]);
-      len -= 8;
-   }
-
-   /* Work on 4 values */
-   if (len >= 4) {
-      XX[0] = vld1q_f32(xi);
-      xi += 4;
-      YY[0] = vld1q_f32(yi);
-      yi += 4;
-      SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
-      len -= 4;
-   }
-
-   /* Start accumulating results */
-   SUMM_2[0] = vget_low_f32(SUMM);
-   if (len >= 2) {
-      /* While at it, consume 2 more values if available */
-      XX_2 = vld1_f32(xi);
-      xi += 2;
-      YY_2 = vld1_f32(yi);
-      yi += 2;
-      SUMM_2[0] = vmla_f32(SUMM_2[0], YY_2, XX_2);
-      len -= 2;
-   }
-   SUMM_2[1] = vget_high_f32(SUMM);
-   SUMM_2[0] = vadd_f32(SUMM_2[0], SUMM_2[1]);
-   SUMM_2[0] = vpadd_f32(SUMM_2[0], SUMM_2[0]);
-   /* Ok, now we have result accumulated in SUMM_2[0].0 */
-
-   if (len > 0) {
-      /* Case when you have one value left */
-      XX_2 = vld1_dup_f32(xi);
-      YY_2 = vld1_dup_f32(yi);
-      SUMM_2[0] = vmla_f32(SUMM_2[0], XX_2, YY_2);
-   }
-
-   vst1_lane_f32(sum, SUMM_2[0], 0);
-}
-
 void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
-                        opus_val32 *xcorr, int len, int max_pitch) {
+                        opus_val32 *xcorr, int len, int max_pitch, int arch) {
    int i;
+   (void)arch;
    celt_assert(max_pitch > 0);
    celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
 
    for (i = 0; i < (max_pitch-3); i += 4) {
       xcorr_kernel_neon_float((const float32_t *)_x, (const float32_t *)_y+i,
             (float32_t *)xcorr+i, len);
    }
 
-   /* In case max_pitch isn't multiple of 4
-    * compute single correlation value per iteration
-    */
+   /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
    for (; i < max_pitch; i++) {
-      xcorr_kernel_neon_float_process1((const float32_t *)_x,
-            (const float32_t *)_y+i, (float32_t *)xcorr+i, len);
+      xcorr[i] = celt_inner_prod_neon(_x, _y+i, len);
    }
 }
 #endif
--- a/media/libopus/celt/arm/celt_pitch_xcorr_arm.s
+++ b/media/libopus/celt/arm/celt_pitch_xcorr_arm.s
@@ -148,31 +148,33 @@ xcorr_kernel_neon_process1
   VSRI.64      d4, d5, #16
   ; Load last *x
   VLD1.16      {d6[]}, [r4]!
   VMLAL.S16    q0, d4, d6
   MOV          pc, lr
   ENDP
 
 ; opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y,
-;  opus_val32 *xcorr, int len, int max_pitch)
+;  opus_val32 *xcorr, int len, int max_pitch, int arch)
 celt_pitch_xcorr_neon PROC
   ; input:
   ;   r0  = opus_val16 *_x
   ;   r1  = opus_val16 *_y
   ;   r2  = opus_val32 *xcorr
   ;   r3  = int         len
   ; output:
   ;   r0  = int         maxcorr
   ; internal usage:
   ;   r4  = opus_val16 *x (for xcorr_kernel_neon())
   ;   r5  = opus_val16 *y (for xcorr_kernel_neon())
   ;   r6  = int         max_pitch
   ;   r12 = int         j
   ;   q15 = int         maxcorr[4] (q15 is not used by xcorr_kernel_neon())
+  ; ignored:
+  ;         int         arch
   STMFD        sp!, {r4-r6, lr}
   LDR          r6, [sp, #16]
   VMOV.S32     q15, #1
   ; if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
   SUBS         r6, r6, #4
   BLT celt_pitch_xcorr_neon_process4_done
 celt_pitch_xcorr_neon_process4
   ; xcorr_kernel_neon parameters:
@@ -353,16 +355,18 @@ celt_pitch_xcorr_edsp PROC
   ;   r4  = opus_val16 *x
   ;   r5  = opus_val16 *y
   ;   r6  = opus_val32  sum0
   ;   r7  = opus_val32  sum1
   ;   r8  = opus_val32  sum2
   ;   r9  = opus_val32  sum3
   ;   r1  = int         max_pitch
   ;   r12 = int         j
+  ; ignored:
+  ;         int         arch
   STMFD        sp!, {r4-r11, lr}
   MOV          r5, r1
   LDR          r1, [sp, #36]
   MOV          r4, r0
   TST          r5, #3
   ; maxcorr = 1
   MOV          r0, #1
   BEQ          celt_pitch_xcorr_edsp_process1u_done
--- a/media/libopus/celt/arm/fft_arm.h
+++ b/media/libopus/celt/arm/fft_arm.h
@@ -29,17 +29,16 @@
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 
 #if !defined(FFT_ARM_H)
 #define FFT_ARM_H
 
-#include "config.h"
 #include "kiss_fft.h"
 
 #if defined(HAVE_ARM_NE10)
 
 int opus_fft_alloc_arm_neon(kiss_fft_state *st);
 void opus_fft_free_arm_neon(kiss_fft_state *st);
 
 void opus_fft_neon(const kiss_fft_state *st,
--- a/media/libopus/celt/arm/fixed_armv4.h
+++ b/media/libopus/celt/arm/fixed_armv4.h
@@ -32,37 +32,37 @@
 static OPUS_INLINE opus_val32 MULT16_32_Q16_armv4(opus_val16 a, opus_val32 b)
 {
   unsigned rd_lo;
   int rd_hi;
   __asm__(
       "#MULT16_32_Q16\n\t"
       "smull %0, %1, %2, %3\n\t"
       : "=&r"(rd_lo), "=&r"(rd_hi)
-      : "%r"(b),"r"(a<<16)
+      : "%r"(b),"r"(SHL32(a,16))
   );
   return rd_hi;
 }
 #define MULT16_32_Q16(a, b) (MULT16_32_Q16_armv4(a, b))
 
 
 /** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */
 #undef MULT16_32_Q15
 static OPUS_INLINE opus_val32 MULT16_32_Q15_armv4(opus_val16 a, opus_val32 b)
 {
   unsigned rd_lo;
   int rd_hi;
   __asm__(
       "#MULT16_32_Q15\n\t"
       "smull %0, %1, %2, %3\n\t"
       : "=&r"(rd_lo), "=&r"(rd_hi)
-      : "%r"(b), "r"(a<<16)
+      : "%r"(b), "r"(SHL32(a,16))
   );
   /*We intentionally don't OR in the high bit of rd_lo for speed.*/
-  return rd_hi<<1;
+  return SHL32(rd_hi,1);
 }
 #define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv4(a, b))
 
 
 /** 16x32 multiply, followed by a 15-bit shift right and 32-bit add.
     b must fit in 31 bits.
     Result fits in 32 bits. */
 #undef MAC16_32_Q15
--- a/media/libopus/celt/arm/fixed_armv5e.h
+++ b/media/libopus/celt/arm/fixed_armv5e.h
@@ -54,34 +54,34 @@ static OPUS_INLINE opus_val32 MULT16_32_
 {
   int res;
   __asm__(
       "#MULT16_32_Q15\n\t"
       "smulwb %0, %1, %2\n\t"
       : "=r"(res)
       : "r"(b), "r"(a)
   );
-  return res<<1;
+  return SHL32(res,1);
 }
 #define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(a, b))
 
 
 /** 16x32 multiply, followed by a 15-bit shift right and 32-bit add.
     b must fit in 31 bits.
     Result fits in 32 bits. */
 #undef MAC16_32_Q15
 static OPUS_INLINE opus_val32 MAC16_32_Q15_armv5e(opus_val32 c, opus_val16 a,
  opus_val32 b)
 {
   int res;
   __asm__(
       "#MAC16_32_Q15\n\t"
       "smlawb %0, %1, %2, %3;\n"
       : "=r"(res)
-      : "r"(b<<1), "r"(a), "r"(c)
+      : "r"(SHL32(b,1)), "r"(a), "r"(c)
   );
   return res;
 }
 #define MAC16_32_Q15(c, a, b) (MAC16_32_Q15_armv5e(c, a, b))
 
 /** 16x32 multiply, followed by a 16-bit shift right and 32-bit add.
     Result fits in 32 bits. */
 #undef MAC16_32_Q16
--- a/media/libopus/celt/arm/mdct_arm.h
+++ b/media/libopus/celt/arm/mdct_arm.h
@@ -28,17 +28,16 @@
    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.
 */
 
 #if !defined(MDCT_ARM_H)
 #define MDCT_ARM_H
 
-#include "config.h"
 #include "mdct.h"
 
 #if defined(HAVE_ARM_NE10)
 /** Compute a forward MDCT and scale by 4/N, trashes the input array */
 void clt_mdct_forward_neon(const mdct_lookup *l, kiss_fft_scalar *in,
                            kiss_fft_scalar * OPUS_RESTRICT out,
                            const opus_val16 *window, int overlap,
                            int shift, int stride, int arch);
--- a/media/libopus/celt/arm/pitch_arm.h
+++ b/media/libopus/celt/arm/pitch_arm.h
@@ -25,50 +25,83 @@
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #if !defined(PITCH_ARM_H)
 # define PITCH_ARM_H
 
 # include "armcpu.h"
 
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N);
+void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01,
+        const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
+
+#  if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+#   define OVERRIDE_CELT_INNER_PROD (1)
+#   define OVERRIDE_DUAL_INNER_PROD (1)
+#   define celt_inner_prod(x, y, N, arch) ((void)(arch), PRESUME_NEON(celt_inner_prod)(x, y, N))
+#   define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), PRESUME_NEON(dual_inner_prod)(x, y01, y02, N, xy1, xy2))
+#  endif
+# endif
+
+# if !defined(OVERRIDE_CELT_INNER_PROD)
+#  if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N);
+#   define OVERRIDE_CELT_INNER_PROD (1)
+#   define celt_inner_prod(x, y, N, arch) ((*CELT_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y, N))
+#  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#   define OVERRIDE_CELT_INNER_PROD (1)
+#   define celt_inner_prod(x, y, N, arch) ((void)(arch), celt_inner_prod_neon(x, y, N))
+#  endif
+# endif
+
+# if !defined(OVERRIDE_DUAL_INNER_PROD)
+#  if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x,
+        const opus_val16 *y01, const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
+#   define OVERRIDE_DUAL_INNER_PROD (1)
+#   define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((*DUAL_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2))
+#  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#   define OVERRIDE_DUAL_INNER_PROD (1)
+#   define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), dual_inner_prod_neon(x, y01, y02, N, xy1, xy2))
+#  endif
+# endif
+
 # if defined(FIXED_POINT)
 
 #  if defined(OPUS_ARM_MAY_HAVE_NEON)
 opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y,
-    opus_val32 *xcorr, int len, int max_pitch);
+    opus_val32 *xcorr, int len, int max_pitch, int arch);
 #  endif
 
 #  if defined(OPUS_ARM_MAY_HAVE_MEDIA)
 #   define celt_pitch_xcorr_media MAY_HAVE_EDSP(celt_pitch_xcorr)
 #  endif
 
 #  if defined(OPUS_ARM_MAY_HAVE_EDSP)
 opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y,
-    opus_val32 *xcorr, int len, int max_pitch);
+    opus_val32 *xcorr, int len, int max_pitch, int arch);
 #  endif
 
 #  if defined(OPUS_HAVE_RTCD) && \
     ((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \
      (defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \
      (defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
 extern opus_val32
 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
-      const opus_val16 *, opus_val32 *, int, int);
+      const opus_val16 *, opus_val32 *, int, int, int);
 #   define OVERRIDE_PITCH_XCORR (1)
-#   define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
-  ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
-        xcorr, len, max_pitch))
+#   define celt_pitch_xcorr (*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])
 
 #  elif defined(OPUS_ARM_PRESUME_EDSP) || \
     defined(OPUS_ARM_PRESUME_MEDIA) || \
     defined(OPUS_ARM_PRESUME_NEON)
 #   define OVERRIDE_PITCH_XCORR (1)
-#   define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
-  ((void)(arch),PRESUME_NEON(celt_pitch_xcorr)(_x, _y, xcorr, len, max_pitch))
+#   define celt_pitch_xcorr (PRESUME_NEON(celt_pitch_xcorr))
 
 #  endif
 
 #  if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
 void xcorr_kernel_neon_fixed(
                     const opus_val16 *x,
                     const opus_val16 *y,
                     opus_val32       sum[4],
@@ -94,33 +127,30 @@ extern void (*const XCORR_KERNEL_IMPL[OP
       ((void)arch, xcorr_kernel_neon_fixed(x, y, sum, len))
 
 #  endif
 
 #else /* Start !FIXED_POINT */
 /* Float case */
 #if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
 void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
-                                 opus_val32 *xcorr, int len, int max_pitch);
+                                 opus_val32 *xcorr, int len, int max_pitch, int arch);
 #endif
 
 #  if defined(OPUS_HAVE_RTCD) && \
     (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
 extern void
 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
-      const opus_val16 *, opus_val32 *, int, int);
+      const opus_val16 *, opus_val32 *, int, int, int);
 
 #  define OVERRIDE_PITCH_XCORR (1)
-#  define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
-  ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
-        xcorr, len, max_pitch))
+#  define celt_pitch_xcorr (*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])
 
 #  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
 
 #   define OVERRIDE_PITCH_XCORR (1)
-#   define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
-   ((void)(arch),celt_pitch_xcorr_float_neon(_x, _y, xcorr, len, max_pitch))
+#   define celt_pitch_xcorr celt_pitch_xcorr_float_neon
 
 #  endif
 
 #endif /* end !FIXED_POINT */
 
 #endif
new file mode 100644
--- /dev/null
+++ b/media/libopus/celt/arm/pitch_neon_intr.c
@@ -0,0 +1,290 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <arm_neon.h>
+#include "pitch.h"
+
+#ifdef FIXED_POINT
+
+opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
+{
+    int i;
+    opus_val32 xy;
+    int16x8_t x_s16x8, y_s16x8;
+    int32x4_t xy_s32x4 = vdupq_n_s32(0);
+    int64x2_t xy_s64x2;
+    int64x1_t xy_s64x1;
+
+    for (i = 0; i < N - 7; i += 8) {
+        x_s16x8  = vld1q_s16(&x[i]);
+        y_s16x8  = vld1q_s16(&y[i]);
+        xy_s32x4 = vmlal_s16(xy_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y_s16x8));
+        xy_s32x4 = vmlal_s16(xy_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y_s16x8));
+    }
+
+    if (N - i >= 4) {
+        const int16x4_t x_s16x4 = vld1_s16(&x[i]);
+        const int16x4_t y_s16x4 = vld1_s16(&y[i]);
+        xy_s32x4 = vmlal_s16(xy_s32x4, x_s16x4, y_s16x4);
+        i += 4;
+    }
+
+    xy_s64x2 = vpaddlq_s32(xy_s32x4);
+    xy_s64x1 = vadd_s64(vget_low_s64(xy_s64x2), vget_high_s64(xy_s64x2));
+    xy       = vget_lane_s32(vreinterpret_s32_s64(xy_s64x1), 0);
+
+    for (; i < N; i++) {
+        xy = MAC16_16(xy, x[i], y[i]);
+    }
+
+#ifdef OPUS_CHECK_ASM
+    celt_assert(celt_inner_prod_c(x, y, N) == xy);
+#endif
+
+    return xy;
+}
+
+void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+        int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+    int i;
+    opus_val32 xy01, xy02;
+    int16x8_t x_s16x8, y01_s16x8, y02_s16x8;
+    int32x4_t xy01_s32x4 = vdupq_n_s32(0);
+    int32x4_t xy02_s32x4 = vdupq_n_s32(0);
+    int64x2_t xy01_s64x2, xy02_s64x2;
+    int64x1_t xy01_s64x1, xy02_s64x1;
+
+    for (i = 0; i < N - 7; i += 8) {
+        x_s16x8    = vld1q_s16(&x[i]);
+        y01_s16x8  = vld1q_s16(&y01[i]);
+        y02_s16x8  = vld1q_s16(&y02[i]);
+        xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y01_s16x8));
+        xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y02_s16x8));
+        xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y01_s16x8));
+        xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y02_s16x8));
+    }
+
+    if (N - i >= 4) {
+        const int16x4_t x_s16x4   = vld1_s16(&x[i]);
+        const int16x4_t y01_s16x4 = vld1_s16(&y01[i]);
+        const int16x4_t y02_s16x4 = vld1_s16(&y02[i]);
+        xy01_s32x4 = vmlal_s16(xy01_s32x4, x_s16x4, y01_s16x4);
+        xy02_s32x4 = vmlal_s16(xy02_s32x4, x_s16x4, y02_s16x4);
+        i += 4;
+    }
+
+    xy01_s64x2 = vpaddlq_s32(xy01_s32x4);
+    xy02_s64x2 = vpaddlq_s32(xy02_s32x4);
+    xy01_s64x1 = vadd_s64(vget_low_s64(xy01_s64x2), vget_high_s64(xy01_s64x2));
+    xy02_s64x1 = vadd_s64(vget_low_s64(xy02_s64x2), vget_high_s64(xy02_s64x2));
+    xy01       = vget_lane_s32(vreinterpret_s32_s64(xy01_s64x1), 0);
+    xy02       = vget_lane_s32(vreinterpret_s32_s64(xy02_s64x1), 0);
+
+    for (; i < N; i++) {
+        xy01 = MAC16_16(xy01, x[i], y01[i]);
+        xy02 = MAC16_16(xy02, x[i], y02[i]);
+    }
+    *xy1 = xy01;
+    *xy2 = xy02;
+
+#ifdef OPUS_CHECK_ASM
+    {
+        opus_val32 xy1_c, xy2_c;
+        dual_inner_prod_c(x, y01, y02, N, &xy1_c, &xy2_c);
+        celt_assert(xy1_c == *xy1);
+        celt_assert(xy2_c == *xy2);
+    }
+#endif
+}
+
+#else /* !FIXED_POINT */
+
+/* ========================================================================== */
+
+#ifdef OPUS_CHECK_ASM
+
+/* This part of code simulates floating-point NEON operations. */
+
+/* celt_inner_prod_neon_float_c_simulation() simulates the floating-point   */
+/* operations of celt_inner_prod_neon(), and both functions should have bit */
+/* exact output.                                                            */
+static opus_val32 celt_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y, int N)
+{
+   int i;
+   opus_val32 xy, xy0 = 0, xy1 = 0, xy2 = 0, xy3 = 0;
+   for (i = 0; i < N - 3; i += 4) {
+      xy0 = MAC16_16(xy0, x[i + 0], y[i + 0]);
+      xy1 = MAC16_16(xy1, x[i + 1], y[i + 1]);
+      xy2 = MAC16_16(xy2, x[i + 2], y[i + 2]);
+      xy3 = MAC16_16(xy3, x[i + 3], y[i + 3]);
+   }
+   xy0 += xy2;
+   xy1 += xy3;
+   xy = xy0 + xy1;
+   for (; i < N; i++) {
+      xy = MAC16_16(xy, x[i], y[i]);
+   }
+   return xy;
+}
+
+/* dual_inner_prod_neon_float_c_simulation() simulates the floating-point   */
+/* operations of dual_inner_prod_neon(), and both functions should have bit */
+/* exact output.                                                            */
+static void dual_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+      int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+   int i;
+   opus_val32 xy01, xy02, xy01_0 = 0, xy01_1 = 0, xy01_2 = 0, xy01_3 = 0, xy02_0 = 0, xy02_1 = 0, xy02_2 = 0, xy02_3 = 0;
+   for (i = 0; i < N - 3; i += 4) {
+      xy01_0 = MAC16_16(xy01_0, x[i + 0], y01[i + 0]);
+      xy01_1 = MAC16_16(xy01_1, x[i + 1], y01[i + 1]);
+      xy01_2 = MAC16_16(xy01_2, x[i + 2], y01[i + 2]);
+      xy01_3 = MAC16_16(xy01_3, x[i + 3], y01[i + 3]);
+      xy02_0 = MAC16_16(xy02_0, x[i + 0], y02[i + 0]);
+      xy02_1 = MAC16_16(xy02_1, x[i + 1], y02[i + 1]);
+      xy02_2 = MAC16_16(xy02_2, x[i + 2], y02[i + 2]);
+      xy02_3 = MAC16_16(xy02_3, x[i + 3], y02[i + 3]);
+   }
+   xy01_0 += xy01_2;
+   xy02_0 += xy02_2;
+   xy01_1 += xy01_3;
+   xy02_1 += xy02_3;
+   xy01 = xy01_0 + xy01_1;
+   xy02 = xy02_0 + xy02_1;
+   for (; i < N; i++) {
+      xy01 = MAC16_16(xy01, x[i], y01[i]);
+      xy02 = MAC16_16(xy02, x[i], y02[i]);
+   }
+   *xy1 = xy01;
+   *xy2 = xy02;
+}
+
+#endif /* OPUS_CHECK_ASM */
+
+/* ========================================================================== */
+
+opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
+{
+    int i;
+    opus_val32 xy;
+    float32x4_t xy_f32x4 = vdupq_n_f32(0);
+    float32x2_t xy_f32x2;
+
+    for (i = 0; i < N - 7; i += 8) {
+        float32x4_t x_f32x4, y_f32x4;
+        x_f32x4  = vld1q_f32(&x[i]);
+        y_f32x4  = vld1q_f32(&y[i]);
+        xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
+        x_f32x4  = vld1q_f32(&x[i + 4]);
+        y_f32x4  = vld1q_f32(&y[i + 4]);
+        xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
+    }
+
+    if (N - i >= 4) {
+        const float32x4_t x_f32x4 = vld1q_f32(&x[i]);
+        const float32x4_t y_f32x4 = vld1q_f32(&y[i]);
+        xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
+        i += 4;
+    }
+
+    xy_f32x2 = vadd_f32(vget_low_f32(xy_f32x4), vget_high_f32(xy_f32x4));
+    xy_f32x2 = vpadd_f32(xy_f32x2, xy_f32x2);
+    xy       = vget_lane_f32(xy_f32x2, 0);
+
+    for (; i < N; i++) {
+        xy = MAC16_16(xy, x[i], y[i]);
+    }
+
+#ifdef OPUS_CHECK_ASM
+    celt_assert(ABS32(celt_inner_prod_neon_float_c_simulation(x, y, N) - xy) <= VERY_SMALL);
+#endif
+
+    return xy;
+}
+
+void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+        int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+    int i;
+    opus_val32 xy01, xy02;
+    float32x4_t xy01_f32x4 = vdupq_n_f32(0);
+    float32x4_t xy02_f32x4 = vdupq_n_f32(0);
+    float32x2_t xy01_f32x2, xy02_f32x2;
+
+    for (i = 0; i < N - 7; i += 8) {
+        float32x4_t x_f32x4, y01_f32x4, y02_f32x4;
+        x_f32x4    = vld1q_f32(&x[i]);
+        y01_f32x4  = vld1q_f32(&y01[i]);
+        y02_f32x4  = vld1q_f32(&y02[i]);
+        xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
+        xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
+        x_f32x4    = vld1q_f32(&x[i + 4]);
+        y01_f32x4  = vld1q_f32(&y01[i + 4]);
+        y02_f32x4  = vld1q_f32(&y02[i + 4]);
+        xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
+        xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
+    }
+
+    if (N - i >= 4) {
+        const float32x4_t x_f32x4   = vld1q_f32(&x[i]);
+        const float32x4_t y01_f32x4 = vld1q_f32(&y01[i]);
+        const float32x4_t y02_f32x4 = vld1q_f32(&y02[i]);
+        xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
+        xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
+        i += 4;
+    }
+
+    xy01_f32x2 = vadd_f32(vget_low_f32(xy01_f32x4), vget_high_f32(xy01_f32x4));
+    xy02_f32x2 = vadd_f32(vget_low_f32(xy02_f32x4), vget_high_f32(xy02_f32x4));
+    xy01_f32x2 = vpadd_f32(xy01_f32x2, xy01_f32x2);
+    xy02_f32x2 = vpadd_f32(xy02_f32x2, xy02_f32x2);
+    xy01       = vget_lane_f32(xy01_f32x2, 0);
+    xy02       = vget_lane_f32(xy02_f32x2, 0);
+
+    for (; i < N; i++) {
+        xy01 = MAC16_16(xy01, x[i], y01[i]);
+        xy02 = MAC16_16(xy02, x[i], y02[i]);
+    }
+    *xy1 = xy01;
+    *xy2 = xy02;
+
+#ifdef OPUS_CHECK_ASM
+    {
+        opus_val32 xy1_c, xy2_c;
+        dual_inner_prod_neon_float_c_simulation(x, y01, y02, N, &xy1_c, &xy2_c);
+        celt_assert(ABS32(xy1_c - *xy1) <= VERY_SMALL);
+        celt_assert(ABS32(xy2_c - *xy2) <= VERY_SMALL);
+    }
+#endif
+}
+
+#endif /* FIXED_POINT */
--- a/media/libopus/celt/bands.c
+++ b/media/libopus/celt/bands.c
@@ -60,47 +60,48 @@ int hysteresis_decision(opus_val16 val, 
 
 opus_uint32 celt_lcg_rand(opus_uint32 seed)
 {
    return 1664525 * seed + 1013904223;
 }
 
 /* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness
    with this approximation is important because it has an impact on the bit allocation */
-static opus_int16 bitexact_cos(opus_int16 x)
+opus_int16 bitexact_cos(opus_int16 x)
 {
    opus_int32 tmp;
    opus_int16 x2;
    tmp = (4096+((opus_int32)(x)*(x)))>>13;
    celt_assert(tmp<=32767);
    x2 = tmp;
    x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2)))));
    celt_assert(x2<=32766);
    return 1+x2;
 }
 
-static int bitexact_log2tan(int isin,int icos)
+int bitexact_log2tan(int isin,int icos)
 {
    int lc;
    int ls;
    lc=EC_ILOG(icos);
    ls=EC_ILOG(isin);
    icos<<=15-lc;
    isin<<=15-ls;
    return (ls-lc)*(1<<11)
          +FRAC_MUL16(isin, FRAC_MUL16(isin, -2597) + 7932)
          -FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932);
 }
 
 #ifdef FIXED_POINT
 /* Compute the amplitude (sqrt energy) in each of the bands */
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM)
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
 {
    int i, c, N;
    const opus_int16 *eBands = m->eBands;
+   (void)arch;
    N = m->shortMdctSize<<LM;
    c=0; do {
       for (i=0;i<end;i++)
       {
          int j;
          opus_val32 maxval=0;
          opus_val32 sum = 0;
 
@@ -150,26 +151,26 @@ void normalise_bands(const CELTMode *m, 
             X[j+c*N] = MULT16_16_Q15(VSHR32(freq[j+c*N],shift-1),g);
          } while (++j<M*eBands[i+1]);
       } while (++i<end);
    } while (++c<C);
 }
 
 #else /* FIXED_POINT */
 /* Compute the amplitude (sqrt energy) in each of the bands */
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM)
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
 {
    int i, c, N;
    const opus_int16 *eBands = m->eBands;
    N = m->shortMdctSize<<LM;
    c=0; do {
       for (i=0;i<end;i++)
       {
          opus_val32 sum;
-         sum = 1e-27f + celt_inner_prod_c(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM);
+         sum = 1e-27f + celt_inner_prod(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM, arch);
          bandE[i+c*m->nbEBands] = celt_sqrt(sum);
          /*printf ("%f ", bandE[i+c*m->nbEBands]);*/
       }
    } while (++c<C);
    /*printf ("\n");*/
 }
 
 /* Normalise each band such that the energy is one. */
@@ -219,39 +220,39 @@ void denormalise_bands(const CELTMode *m
       int j, band_end;
       opus_val16 g;
       opus_val16 lg;
 #ifdef FIXED_POINT
       int shift;
 #endif
       j=M*eBands[i];
       band_end = M*eBands[i+1];
-      lg = ADD16(bandLogE[i], SHL16((opus_val16)eMeans[i],6));
+      lg = SATURATE16(ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],6)));
 #ifndef FIXED_POINT
-      g = celt_exp2(lg);
+      g = celt_exp2(MIN32(32.f, lg));
 #else
       /* Handle the integer part of the log energy */
       shift = 16-(lg>>DB_SHIFT);
       if (shift>31)
       {
          shift=0;
          g=0;
       } else {
          /* Handle the fractional part. */
          g = celt_exp2_frac(lg&((1<<DB_SHIFT)-1));
       }
       /* Handle extreme gains with negative shift. */
       if (shift<0)
       {
-         /* For shift < -2 we'd be likely to overflow, so we're capping
-               the gain here. This shouldn't happen unless the bitstream is
-               already corrupted. */
-         if (shift < -2)
+         /* For shift <= -2 and g > 16384 we'd be likely to overflow, so we're
+            capping the gain here, which is equivalent to a cap of 18 on lg.
+            This shouldn't trigger unless the bitstream is already corrupted. */
+         if (shift <= -2)
          {
-            g = 32767;
+            g = 16384;
             shift = -2;
          }
          do {
             *f++ = SHL32(MULT16_16(*x++, g), -shift);
          } while (++j<band_end);
       } else
 #endif
          /* Be careful of the fixed-point "else" just above when changing this code */
@@ -355,16 +356,40 @@ void anti_collapse(const CELTMode *m, ce
          }
          /* We just added some energy, so we need to renormalise */
          if (renormalize)
             renormalise_vector(X, N0<<LM, Q15ONE, arch);
       } while (++c<C);
    }
 }
 
+/* Compute the weights to use for optimizing normalized distortion across
+   channels. We use the amplitude to weight square distortion, which means
+   that we use the square root of the value we would have been using if we
+   wanted to minimize the MSE in the non-normalized domain. This roughly
+   corresponds to some quick-and-dirty perceptual experiments I ran to
+   measure inter-aural masking (there doesn't seem to be any published data
+   on the topic). */
+static void compute_channel_weights(celt_ener Ex, celt_ener Ey, opus_val16 w[2])
+{
+   celt_ener minE;
+#if FIXED_POINT
+   int shift;
+#endif
+   minE = MIN32(Ex, Ey);
+   /* Adjustment to make the weights a bit more conservative. */
+   Ex = ADD32(Ex, minE/3);
+   Ey = ADD32(Ey, minE/3);
+#if FIXED_POINT
+   shift = celt_ilog2(EPSILON+MAX32(Ex, Ey))-14;
+#endif
+   w[0] = VSHR32(Ex, shift);
+   w[1] = VSHR32(Ey, shift);
+}
+
 static void intensity_stereo(const CELTMode *m, celt_norm * OPUS_RESTRICT X, const celt_norm * OPUS_RESTRICT Y, const celt_ener *bandE, int bandID, int N)
 {
    int i = bandID;
    int j;
    opus_val16 a1, a2;
    opus_val16 left, right;
    opus_val16 norm;
 #ifdef FIXED_POINT
@@ -642,26 +667,30 @@ static int compute_qn(int N, int b, int 
       qn = (qn+1)>>1<<1;
    }
    celt_assert(qn <= 256);
    return qn;
 }
 
 struct band_ctx {
    int encode;
+   int resynth;
    const CELTMode *m;
    int i;
    int intensity;
    int spread;
    int tf_change;
    ec_ctx *ec;
    opus_int32 remaining_bits;
    const celt_ener *bandE;
    opus_uint32 seed;
    int arch;
+   int theta_round;
+   int disable_inv;
+   int avoid_split_noise;
 };
 
 struct split_ctx {
    int inv;
    int imid;
    int iside;
    int delta;
    int itheta;
@@ -709,18 +738,45 @@ static void compute_theta(struct band_ct
          mid and side because we know that 1) they have unit norm and
          2) they are orthogonal. */
       itheta = stereo_itheta(X, Y, stereo, N, ctx->arch);
    }
    tell = ec_tell_frac(ec);
    if (qn!=1)
    {
       if (encode)
-         itheta = (itheta*(opus_int32)qn+8192)>>14;
-
+      {
+         if (!stereo || ctx->theta_round == 0)
+         {
+            itheta = (itheta*(opus_int32)qn+8192)>>14;
+            if (!stereo && ctx->avoid_split_noise && itheta > 0 && itheta < qn)
+            {
+               /* Check if the selected value of theta will cause the bit allocation
+                  to inject noise on one side. If so, make sure the energy of that side
+                  is zero. */
+               int unquantized = celt_udiv((opus_int32)itheta*16384, qn);
+               imid = bitexact_cos((opus_int16)unquantized);
+               iside = bitexact_cos((opus_int16)(16384-unquantized));
+               delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
+               if (delta > *b)
+                  itheta = qn;
+               else if (delta < -*b)
+                  itheta = 0;
+            }
+         } else {
+            int down;
+            /* Bias quantization towards itheta=0 and itheta=16384. */
+            int bias = itheta > 8192 ? 32767/qn : -32767/qn;
+            down = IMIN(qn-1, IMAX(0, (itheta*(opus_int32)qn + bias)>>14));
+            if (ctx->theta_round < 0)
+               itheta = down;
+            else
+               itheta = down+1;
+         }
+      }
       /* Entropy coding of the angle. We use a uniform pdf for the
          time split, a step for stereo, and a triangular one for the rest. */
       if (stereo && N>2)
       {
          int p0 = 3;
          int x = itheta;
          int x0 = qn/2;
          int ft = p0*(x0+1) + x0;
@@ -788,33 +844,36 @@ static void compute_theta(struct band_ct
          else
             stereo_split(X, Y, N);
       }
       /* NOTE: Renormalising X and Y *may* help fixed-point a bit at very high rate.
                Let's do that at higher complexity */
    } else if (stereo) {
       if (encode)
       {
-         inv = itheta > 8192;
+         inv = itheta > 8192 && !ctx->disable_inv;
          if (inv)
          {
             int j;
             for (j=0;j<N;j++)
                Y[j] = -Y[j];
          }
          intensity_stereo(m, X, Y, bandE, i, N);
       }
       if (*b>2<<BITRES && ctx->remaining_bits > 2<<BITRES)
       {
          if (encode)
             ec_enc_bit_logp(ec, inv, 2);
          else
             inv = ec_dec_bit_logp(ec, 2);
       } else
          inv = 0;
+      /* inv flag override to avoid problems with downmixing. */
+      if (ctx->disable_inv)
+         inv = 0;
       itheta = 0;
    }
    qalloc = ec_tell_frac(ec) - tell;
    *b -= qalloc;
 
    if (itheta == 0)
    {
       imid = 32767;
@@ -840,21 +899,16 @@ static void compute_theta(struct band_ct
    sctx->iside = iside;
    sctx->delta = delta;
    sctx->itheta = itheta;
    sctx->qalloc = qalloc;
 }
 static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b,
       celt_norm *lowband_out)
 {
-#ifdef RESYNTH
-   int resynth = 1;
-#else
-   int resynth = !ctx->encode;
-#endif
    int c;
    int stereo;
    celt_norm *x = X;
    int encode;
    ec_ctx *ec;
 
    encode = ctx->encode;
    ec = ctx->ec;
@@ -869,17 +923,17 @@ static unsigned quant_band_n1(struct ban
             sign = x[0]<0;
             ec_enc_bits(ec, sign, 1);
          } else {
             sign = ec_dec_bits(ec, 1);
          }
          ctx->remaining_bits -= 1<<BITRES;
          b-=1<<BITRES;
       }
-      if (resynth)
+      if (ctx->resynth)
          x[0] = sign ? -NORM_SCALING : NORM_SCALING;
       x = Y;
    } while (++c<1+stereo);
    if (lowband_out)
       lowband_out[0] = SHR16(X[0],4);
    return 1;
 }
 
@@ -894,21 +948,16 @@ static unsigned quant_partition(struct b
 {
    const unsigned char *cache;
    int q;
    int curr_bits;
    int imid=0, iside=0;
    int B0=B;
    opus_val16 mid=0, side=0;
    unsigned cm=0;
-#ifdef RESYNTH
-   int resynth = 1;
-#else
-   int resynth = !ctx->encode;
-#endif
    celt_norm *Y=NULL;
    int encode;
    const CELTMode *m;
    int i;
    int spread;
    ec_ctx *ec;
 
    encode = ctx->encode;
@@ -930,18 +979,17 @@ static unsigned quant_partition(struct b
 
       N >>= 1;
       Y = X+N;
       LM -= 1;
       if (B==1)
          fill = (fill&1)|(fill<<1);
       B = (B+1)>>1;
 
-      compute_theta(ctx, &sctx, X, Y, N, &b, B, B0,
-            LM, 0, &fill);
+      compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, LM, 0, &fill);
       imid = sctx.imid;
       iside = sctx.iside;
       delta = sctx.delta;
       itheta = sctx.itheta;
       qalloc = sctx.qalloc;
 #ifdef FIXED_POINT
       mid = imid;
       side = iside;
@@ -965,34 +1013,30 @@ static unsigned quant_partition(struct b
       ctx->remaining_bits -= qalloc;
 
       if (lowband)
          next_lowband2 = lowband+N; /* >32-bit split case */
 
       rebalance = ctx->remaining_bits;
       if (mbits >= sbits)
       {
-         cm = quant_partition(ctx, X, N, mbits, B,
-               lowband, LM,
+         cm = quant_partition(ctx, X, N, mbits, B, lowband, LM,
                MULT16_16_P15(gain,mid), fill);
          rebalance = mbits - (rebalance-ctx->remaining_bits);
          if (rebalance > 3<<BITRES && itheta!=0)
             sbits += rebalance - (3<<BITRES);
-         cm |= quant_partition(ctx, Y, N, sbits, B,
-               next_lowband2, LM,
+         cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
                MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
       } else {
-         cm = quant_partition(ctx, Y, N, sbits, B,
-               next_lowband2, LM,
+         cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
                MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
          rebalance = sbits - (rebalance-ctx->remaining_bits);
          if (rebalance > 3<<BITRES && itheta!=16384)
             mbits += rebalance - (3<<BITRES);
-         cm |= quant_partition(ctx, X, N, mbits, B,
-               lowband, LM,
+         cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM,
                MULT16_16_P15(gain,mid), fill);
       }
    } else {
       /* This is the basic no-split case */
       q = bits2pulses(m, i, LM, b);
       curr_bits = pulses2bits(m, i, LM, q);
       ctx->remaining_bits -= curr_bits;
 
@@ -1007,28 +1051,24 @@ static unsigned quant_partition(struct b
 
       if (q!=0)
       {
          int K = get_pulses(q);
 
          /* Finally do the actual quantization */
          if (encode)
          {
-            cm = alg_quant(X, N, K, spread, B, ec
-#ifdef RESYNTH
-                 , gain
-#endif
-                 );
+            cm = alg_quant(X, N, K, spread, B, ec, gain, ctx->resynth, ctx->arch);
          } else {
             cm = alg_unquant(X, N, K, spread, B, ec, gain);
          }
       } else {
          /* If there's no pulse, fill the band anyway */
          int j;
-         if (resynth)
+         if (ctx->resynth)
          {
             unsigned cm_mask;
             /* B can be as large as 16, so this shift might overflow an int on a
                16-bit platform; use a long to get defined behavior.*/
             cm_mask = (unsigned)(1UL<<B)-1;
             fill &= cm_mask;
             if (!fill)
             {
@@ -1075,21 +1115,16 @@ static unsigned quant_band(struct band_c
    int N0=N;
    int N_B=N;
    int N_B0;
    int B0=B;
    int time_divide=0;
    int recombine=0;
    int longBlocks;
    unsigned cm=0;
-#ifdef RESYNTH
-   int resynth = 1;
-#else
-   int resynth = !ctx->encode;
-#endif
    int k;
    int encode;
    int tf_change;
 
    encode = ctx->encode;
    tf_change = ctx->tf_change;
 
    longBlocks = B0==1;
@@ -1146,21 +1181,20 @@ static unsigned quant_band(struct band_c
    if (B0>1)
    {
       if (encode)
          deinterleave_hadamard(X, N_B>>recombine, B0<<recombine, longBlocks);
       if (lowband)
          deinterleave_hadamard(lowband, N_B>>recombine, B0<<recombine, longBlocks);
    }
 
-   cm = quant_partition(ctx, X, N, b, B, lowband,
-         LM, gain, fill);
+   cm = quant_partition(ctx, X, N, b, B, lowband, LM, gain, fill);
 
    /* This code is used by the decoder and by the resynthesis-enabled encoder */
-   if (resynth)
+   if (ctx->resynth)
    {
       /* Undo the sample reorganization going from time order to frequency order */
       if (B0>1)
          interleave_hadamard(X, N_B>>recombine, B0<<recombine, longBlocks);
 
       /* Undo time-freq changes that we did earlier */
       N_B = N_B0;
       B = B0;
@@ -1203,21 +1237,16 @@ static unsigned quant_band_stereo(struct
       int N, int b, int B, celt_norm *lowband,
       int LM, celt_norm *lowband_out,
       celt_norm *lowband_scratch, int fill)
 {
    int imid=0, iside=0;
    int inv = 0;
    opus_val16 mid=0, side=0;
    unsigned cm=0;
-#ifdef RESYNTH
-   int resynth = 1;
-#else
-   int resynth = !ctx->encode;
-#endif
    int mbits, sbits, delta;
    int itheta;
    int qalloc;
    struct split_ctx sctx;
    int orig_fill;
    int encode;
    ec_ctx *ec;
 
@@ -1227,18 +1256,17 @@ static unsigned quant_band_stereo(struct
    /* Special case for one sample */
    if (N==1)
    {
       return quant_band_n1(ctx, X, Y, b, lowband_out);
    }
 
    orig_fill = fill;
 
-   compute_theta(ctx, &sctx, X, Y, N, &b, B, B,
-         LM, 1, &fill);
+   compute_theta(ctx, &sctx, X, Y, N, &b, B, B, LM, 1, &fill);
    inv = sctx.inv;
    imid = sctx.imid;
    iside = sctx.iside;
    delta = sctx.delta;
    itheta = sctx.itheta;
    qalloc = sctx.qalloc;
 #ifdef FIXED_POINT
    mid = imid;
@@ -1276,23 +1304,23 @@ static unsigned quant_band_stereo(struct
             ec_enc_bits(ec, sign, 1);
          } else {
             sign = ec_dec_bits(ec, 1);
          }
       }
       sign = 1-2*sign;
       /* We use orig_fill here because we want to fold the side, but if
          itheta==16384, we'll have cleared the low bits of fill. */
-      cm = quant_band(ctx, x2, N, mbits, B, lowband,
-            LM, lowband_out, Q15ONE, lowband_scratch, orig_fill);
+      cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+            lowband_scratch, orig_fill);
       /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
          and there's no need to worry about mixing with the other channel. */
       y2[0] = -sign*x2[1];
       y2[1] = sign*x2[0];
-      if (resynth)
+      if (ctx->resynth)
       {
          celt_norm tmp;
          X[0] = MULT16_16_Q15(mid, X[0]);
          X[1] = MULT16_16_Q15(mid, X[1]);
          Y[0] = MULT16_16_Q15(side, Y[0]);
          Y[1] = MULT16_16_Q15(side, Y[1]);
          tmp = X[0];
          X[0] = SUB16(tmp,Y[0]);
@@ -1309,110 +1337,144 @@ static unsigned quant_band_stereo(struct
       sbits = b-mbits;
       ctx->remaining_bits -= qalloc;
 
       rebalance = ctx->remaining_bits;
       if (mbits >= sbits)
       {
          /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
             mid for folding later. */
-         cm = quant_band(ctx, X, N, mbits, B,
-               lowband, LM, lowband_out,
-               Q15ONE, lowband_scratch, fill);
+         cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+               lowband_scratch, fill);
          rebalance = mbits - (rebalance-ctx->remaining_bits);
          if (rebalance > 3<<BITRES && itheta!=0)
             sbits += rebalance - (3<<BITRES);
 
          /* For a stereo split, the high bits of fill are always zero, so no
             folding will be done to the side. */
-         cm |= quant_band(ctx, Y, N, sbits, B,
-               NULL, LM, NULL,
-               side, NULL, fill>>B);
+         cm |= quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B);
       } else {
          /* For a stereo split, the high bits of fill are always zero, so no
             folding will be done to the side. */
-         cm = quant_band(ctx, Y, N, sbits, B,
-               NULL, LM, NULL,
-               side, NULL, fill>>B);
+         cm = quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B);
          rebalance = sbits - (rebalance-ctx->remaining_bits);
          if (rebalance > 3<<BITRES && itheta!=16384)
             mbits += rebalance - (3<<BITRES);
          /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
             mid for folding later. */
-         cm |= quant_band(ctx, X, N, mbits, B,
-               lowband, LM, lowband_out,
-               Q15ONE, lowband_scratch, fill);
+         cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+               lowband_scratch, fill);
       }
    }
 
 
    /* This code is used by the decoder and by the resynthesis-enabled encoder */
-   if (resynth)
+   if (ctx->resynth)
    {
       if (N!=2)
          stereo_merge(X, Y, mid, N, ctx->arch);
       if (inv)
       {
          int j;
          for (j=0;j<N;j++)
             Y[j] = -Y[j];
       }
    }
    return cm;
 }
 
+static void special_hybrid_folding(const CELTMode *m, celt_norm *norm, celt_norm *norm2, int start, int M, int dual_stereo)
+{
+   int n1, n2;
+   const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+   n1 = M*(eBands[start+1]-eBands[start]);
+   n2 = M*(eBands[start+2]-eBands[start+1]);
+   /* Duplicate enough of the first band folding data to be able to fold the second band.
+      Copies no data for CELT-only mode. */
+   OPUS_COPY(&norm[n1], &norm[2*n1 - n2], n2-n1);
+   if (dual_stereo)
+      OPUS_COPY(&norm2[n1], &norm2[2*n1 - n2], n2-n1);
+}
 
 void quant_all_bands(int encode, const CELTMode *m, int start, int end,
       celt_norm *X_, celt_norm *Y_, unsigned char *collapse_masks,
       const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
       int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
       opus_int32 balance, ec_ctx *ec, int LM, int codedBands,
-      opus_uint32 *seed, int arch)
+      opus_uint32 *seed, int complexity, int arch, int disable_inv)
 {
    int i;
    opus_int32 remaining_bits;
    const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
    celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2;
    VARDECL(celt_norm, _norm);
+   VARDECL(celt_norm, _lowband_scratch);
+   VARDECL(celt_norm, X_save);
+   VARDECL(celt_norm, Y_save);
+   VARDECL(celt_norm, X_save2);
+   VARDECL(celt_norm, Y_save2);
+   VARDECL(celt_norm, norm_save2);
+   int resynth_alloc;
    celt_norm *lowband_scratch;
    int B;
    int M;
    int lowband_offset;
    int update_lowband = 1;
    int C = Y_ != NULL ? 2 : 1;
    int norm_offset;
+   int theta_rdo = encode && Y_!=NULL && !dual_stereo && complexity>=8;
 #ifdef RESYNTH
    int resynth = 1;
 #else
-   int resynth = !encode;
+   int resynth = !encode || theta_rdo;
 #endif
    struct band_ctx ctx;
    SAVE_STACK;
 
    M = 1<<LM;
    B = shortBlocks ? M : 1;
    norm_offset = M*eBands[start];
    /* No need to allocate norm for the last band because we don't need an
       output in that band. */
    ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm);
    norm = _norm;
    norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset;
-   /* We can use the last band as scratch space because we don't need that
-      scratch space for the last band. */
-   lowband_scratch = X_+M*eBands[m->nbEBands-1];
+
+   /* For decoding, we can use the last band as scratch space because we don't need that
+      scratch space for the last band and we don't care about the data there until we're
+      decoding the last band. */
+   if (encode && resynth)
+      resynth_alloc = M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]);
+   else
+      resynth_alloc = ALLOC_NONE;
+   ALLOC(_lowband_scratch, resynth_alloc, celt_norm);
+   if (encode && resynth)
+      lowband_scratch = _lowband_scratch;
+   else
+      lowband_scratch = X_+M*eBands[m->nbEBands-1];
+   ALLOC(X_save, resynth_alloc, celt_norm);
+   ALLOC(Y_save, resynth_alloc, celt_norm);
+   ALLOC(X_save2, resynth_alloc, celt_norm);
+   ALLOC(Y_save2, resynth_alloc, celt_norm);
+   ALLOC(norm_save2, resynth_alloc, celt_norm);
 
    lowband_offset = 0;
    ctx.bandE = bandE;
    ctx.ec = ec;
    ctx.encode = encode;
    ctx.intensity = intensity;
    ctx.m = m;
    ctx.seed = *seed;
    ctx.spread = spread;
    ctx.arch = arch;
+   ctx.disable_inv = disable_inv;
+   ctx.resynth = resynth;
+   ctx.theta_round = 0;
+   /* Avoid injecting noise in the first band on transients. */
+   ctx.avoid_split_noise = B > 1;
    for (i=start;i<end;i++)
    {
       opus_int32 tell;
       int b;
       int N;
       opus_int32 curr_balance;
       int effective_lowband=-1;
       celt_norm * OPUS_RESTRICT X, * OPUS_RESTRICT Y;
@@ -1440,44 +1502,55 @@ void quant_all_bands(int encode, const C
       if (i <= codedBands-1)
       {
          curr_balance = celt_sudiv(balance, IMIN(3, codedBands-i));
          b = IMAX(0, IMIN(16383, IMIN(remaining_bits+1,pulses[i]+curr_balance)));
       } else {
          b = 0;
       }
 
+#ifdef ENABLE_UPDATE_DRAFT
+      if (resynth && (M*eBands[i]-N >= M*eBands[start] || i==start+1) && (update_lowband || lowband_offset==0))
+            lowband_offset = i;
+      if (i == start+1)
+         special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+#else
       if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0))
             lowband_offset = i;
+#endif
 
       tf_change = tf_res[i];
       ctx.tf_change = tf_change;
       if (i>=m->effEBands)
       {
          X=norm;
          if (Y_!=NULL)
             Y = norm;
          lowband_scratch = NULL;
       }
-      if (i==end-1)
+      if (last && !theta_rdo)
          lowband_scratch = NULL;
 
       /* Get a conservative estimate of the collapse_mask's for the bands we're
          going to be folding from. */
       if (lowband_offset != 0 && (spread!=SPREAD_AGGRESSIVE || B>1 || tf_change<0))
       {
          int fold_start;
          int fold_end;
          int fold_i;
          /* This ensures we never repeat spectral content within one band */
          effective_lowband = IMAX(0, M*eBands[lowband_offset]-norm_offset-N);
          fold_start = lowband_offset;
          while(M*eBands[--fold_start] > effective_lowband+norm_offset);
          fold_end = lowband_offset-1;
+#ifdef ENABLE_UPDATE_DRAFT
+         while(++fold_end < i && M*eBands[fold_end] < effective_lowband+norm_offset+N);
+#else
          while(M*eBands[++fold_end] < effective_lowband+norm_offset+N);
+#endif
          x_cm = y_cm = 0;
          fold_i = fold_start; do {
            x_cm |= collapse_masks[fold_i*C+0];
            y_cm |= collapse_masks[fold_i*C+C-1];
          } while (++fold_i<fold_end);
       }
       /* Otherwise, we'll be using the LCG to fold, so all blocks will (almost
          always) be non-zero. */
@@ -1500,30 +1573,97 @@ void quant_all_bands(int encode, const C
                effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
                last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm);
          y_cm = quant_band(&ctx, Y, N, b/2, B,
                effective_lowband != -1 ? norm2+effective_lowband : NULL, LM,
                last?NULL:norm2+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, y_cm);
       } else {
          if (Y!=NULL)
          {
-            x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
-                  effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
-                        last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm);
+            if (theta_rdo && i < intensity)
+            {
+               ec_ctx ec_save, ec_save2;
+               struct band_ctx ctx_save, ctx_save2;
+               opus_val32 dist0, dist1;
+               unsigned cm, cm2;
+               int nstart_bytes, nend_bytes, save_bytes;
+               unsigned char *bytes_buf;
+               unsigned char bytes_save[1275];
+               opus_val16 w[2];
+               compute_channel_weights(bandE[i], bandE[i+m->nbEBands], w);
+               /* Make a copy. */
+               cm = x_cm|y_cm;
+               ec_save = *ec;
+               ctx_save = ctx;
+               OPUS_COPY(X_save, X, N);
+               OPUS_COPY(Y_save, Y, N);
+               /* Encode and round down. */
+               ctx.theta_round = -1;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm);
+               dist0 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch));
+
+               /* Save first result. */
+               cm2 = x_cm;
+               ec_save2 = *ec;
+               ctx_save2 = ctx;
+               OPUS_COPY(X_save2, X, N);
+               OPUS_COPY(Y_save2, Y, N);
+               if (!last)
+                  OPUS_COPY(norm_save2, norm+M*eBands[i]-norm_offset, N);
+               nstart_bytes = ec_save.offs;
+               nend_bytes = ec_save.storage;
+               bytes_buf = ec_save.buf+nstart_bytes;
+               save_bytes = nend_bytes-nstart_bytes;
+               OPUS_COPY(bytes_save, bytes_buf, save_bytes);
+
+               /* Restore */
+               *ec = ec_save;
+               ctx = ctx_save;
+               OPUS_COPY(X, X_save, N);
+               OPUS_COPY(Y, Y_save, N);
+               if (i == start+1)
+                  special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+               /* Encode and round up. */
+               ctx.theta_round = 1;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm);
+               dist1 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch));
+               if (dist0 >= dist1) {
+                  x_cm = cm2;
+                  *ec = ec_save2;
+                  ctx = ctx_save2;
+                  OPUS_COPY(X, X_save2, N);
+                  OPUS_COPY(Y, Y_save2, N);
+                  if (!last)
+                     OPUS_COPY(norm+M*eBands[i]-norm_offset, norm_save2, N);
+                  OPUS_COPY(bytes_buf, bytes_save, save_bytes);
+               }
+            } else {
+               ctx.theta_round = 0;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm);
+            }
          } else {
             x_cm = quant_band(&ctx, X, N, b, B,
                   effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
-                        last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm);
+                  last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm);
          }
          y_cm = x_cm;
       }
       collapse_masks[i*C+0] = (unsigned char)x_cm;
       collapse_masks[i*C+C-1] = (unsigned char)y_cm;
       balance += pulses[i] + tell;
 
       /* Update the folding position only as long as we have 1 bit/sample depth. */
       update_lowband = b>(N<<BITRES);
+      /* We only need to avoid noise on a split for the first band. After that, we
+         have folding. */
+      ctx.avoid_split_noise = 0;
    }
    *seed = ctx.seed;
 
    RESTORE_STACK;
 }
 
--- a/media/libopus/celt/bands.h
+++ b/media/libopus/celt/bands.h
@@ -31,22 +31,25 @@
 #define BANDS_H
 
 #include "arch.h"
 #include "modes.h"
 #include "entenc.h"
 #include "entdec.h"
 #include "rate.h"
 
+opus_int16 bitexact_cos(opus_int16 x);
+int bitexact_log2tan(int isin,int icos);
+
 /** Compute the amplitude (sqrt energy) in each of the bands
  * @param m Mode data
  * @param X Spectrum
  * @param bandE Square root of the energy for each band (returned)
  */
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM);
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch);
 
 /*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
 
 /** Normalise each band of X such that the energy in each band is
     equal to 1
  * @param m Mode data
  * @param X Spectrum (returned normalised)
  * @param bandE Square root of the energy for each band
@@ -100,17 +103,17 @@ void haar1(celt_norm *X, int N0, int str
  * @param seed Random generator seed
  * @param arch Run-time architecture (see opus_select_arch())
  */
 void quant_all_bands(int encode, const CELTMode *m, int start, int end,
       celt_norm * X, celt_norm * Y, unsigned char *collapse_masks,
       const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
       int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
       opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed,
-      int arch);
+      int complexity, int arch, int disable_inv);
 
 void anti_collapse(const CELTMode *m, celt_norm *X_,
       unsigned char *collapse_masks, int LM, int C, int size, int start,
       int end, const opus_val16 *logE, const opus_val16 *prev1logE,
       const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed,
       int arch);
 
 opus_uint32 celt_lcg_rand(opus_uint32 seed);
--- a/media/libopus/celt/celt.c
+++ b/media/libopus/celt/celt.c
@@ -106,46 +106,52 @@ void comb_filter_const_c(opus_val32 *y, 
    x1 = SHL32(x[-T+1], 1);
    for (i=0;i<N-4;i+=5)
    {
       opus_val32 t;
       x0=SHL32(x[i-T+2],1);
       t = MAC16_32_Q16(x[i], g10, x2);
       t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
       t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
+      t = SATURATE(t, SIG_SAT);
       y[i] = t;
       x4=SHL32(x[i-T+3],1);
       t = MAC16_32_Q16(x[i+1], g10, x1);
       t = MAC16_32_Q16(t, g11, ADD32(x0,x2));
       t = MAC16_32_Q16(t, g12, ADD32(x4,x3));
+      t = SATURATE(t, SIG_SAT);
       y[i+1] = t;
       x3=SHL32(x[i-T+4],1);
       t = MAC16_32_Q16(x[i+2], g10, x0);
       t = MAC16_32_Q16(t, g11, ADD32(x4,x1));
       t = MAC16_32_Q16(t, g12, ADD32(x3,x2));
+      t = SATURATE(t, SIG_SAT);
       y[i+2] = t;
       x2=SHL32(x[i-T+5],1);
       t = MAC16_32_Q16(x[i+3], g10, x4);
       t = MAC16_32_Q16(t, g11, ADD32(x3,x0));
       t = MAC16_32_Q16(t, g12, ADD32(x2,x1));
+      t = SATURATE(t, SIG_SAT);
       y[i+3] = t;
       x1=SHL32(x[i-T+6],1);
       t = MAC16_32_Q16(x[i+4], g10, x3);
       t = MAC16_32_Q16(t, g11, ADD32(x2,x4));
       t = MAC16_32_Q16(t, g12, ADD32(x1,x0));
+      t = SATURATE(t, SIG_SAT);
       y[i+4] = t;
    }
 #ifdef CUSTOM_MODES
    for (;i<N;i++)
    {
       opus_val32 t;
       x0=SHL32(x[i-T+2],1);
       t = MAC16_32_Q16(x[i], g10, x2);
       t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
       t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
+      t = SATURATE(t, SIG_SAT);
       y[i] = t;
       x4=x3;
       x3=x2;
       x2=x1;
       x1=x0;
    }
 #endif
 }
@@ -164,16 +170,17 @@ void comb_filter_const_c(opus_val32 *y, 
    x1 = x[-T+1];
    for (i=0;i<N;i++)
    {
       x0=x[i-T+2];
       y[i] = x[i]
                + MULT16_32_Q15(g10,x2)
                + MULT16_32_Q15(g11,ADD32(x1,x3))
                + MULT16_32_Q15(g12,ADD32(x0,x4));
+      y[i] = SATURATE(y[i], SIG_SAT);
       x4=x3;
       x3=x2;
       x2=x1;
       x1=x0;
    }
 
 }
 #endif
@@ -195,16 +202,20 @@ void comb_filter(opus_val32 *y, opus_val
 
    if (g0==0 && g1==0)
    {
       /* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
       if (x!=y)
          OPUS_MOVE(y, x, N);
       return;
    }
+   /* When the gain is zero, T0 and/or T1 is set to zero. We need
+      to have then be at least 2 to avoid processing garbage data. */
+   T0 = IMAX(T0, COMBFILTER_MINPERIOD);
+   T1 = IMAX(T1, COMBFILTER_MINPERIOD);
    g00 = MULT16_16_P15(g0, gains[tapset0][0]);
    g01 = MULT16_16_P15(g0, gains[tapset0][1]);
    g02 = MULT16_16_P15(g0, gains[tapset0][2]);
    g10 = MULT16_16_P15(g1, gains[tapset1][0]);
    g11 = MULT16_16_P15(g1, gains[tapset1][1]);
    g12 = MULT16_16_P15(g1, gains[tapset1][2]);
    x1 = x[-T1+1];
    x2 = x[-T1  ];
@@ -220,16 +231,17 @@ void comb_filter(opus_val32 *y, opus_val
       f = MULT16_16_Q15(window[i],window[i]);
       y[i] = x[i]
                + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0])
                + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1]))
                + MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2]))
                + MULT16_32_Q15(MULT16_16_Q15(f,g10),x2)
                + MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3))
                + MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4));
+      y[i] = SATURATE(y[i], SIG_SAT);
       x4=x3;
       x3=x2;
       x2=x1;
       x1=x0;
 
    }
    if (g1==0)
    {
@@ -239,21 +251,26 @@ void comb_filter(opus_val32 *y, opus_val
       return;
    }
 
    /* Compute the part with the constant filter. */
    comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12, arch);
 }
 #endif /* OVERRIDE_comb_filter */
 
+/* TF change table. Positive values mean better frequency resolution (longer
+   effective window), whereas negative values mean better time resolution
+   (shorter effective window). The second index is computed as:
+   4*isTransient + 2*tf_select + per_band_flag */
 const signed char tf_select_table[4][8] = {
-      {0, -1, 0, -1,    0,-1, 0,-1},
-      {0, -1, 0, -2,    1, 0, 1,-1},
-      {0, -2, 0, -3,    2, 0, 1,-1},
-      {0, -2, 0, -3,    3, 0, 1,-1},
+    /*isTransient=0     isTransient=1 */
+      {0, -1, 0, -1,    0,-1, 0,-1}, /* 2.5 ms */
+      {0, -1, 0, -2,    1, 0, 1,-1}, /* 5 ms */
+      {0, -2, 0, -3,    2, 0, 1,-1}, /* 10 ms */
+      {0, -2, 0, -3,    3, 0, 1,-1}, /* 20 ms */
 };
 
 
 void init_caps(const CELTMode *m,int *cap,int LM,int C)
 {
    int i;
    for (i=0;i<m->nbEBands;i++)
    {
--- a/media/libopus/celt/celt.h
+++ b/media/libopus/celt/celt.h
@@ -45,34 +45,44 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #define CELTEncoder OpusCustomEncoder
 #define CELTDecoder OpusCustomDecoder
 #define CELTMode OpusCustomMode
 
+#define LEAK_BANDS 19
+
 typedef struct {
    int valid;
    float tonality;
    float tonality_slope;
    float noisiness;
    float activity;
    float music_prob;
-   int        bandwidth;
-}AnalysisInfo;
+   float vad_prob;
+   int   bandwidth;
+   float activity_probability;
+   /* Store as Q6 char to save space. */
+   unsigned char leak_boost[LEAK_BANDS];
+} AnalysisInfo;
+
+typedef struct {
+   int signalType;
+   int offset;
+} SILKInfo;
 
 #define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
 
 #define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
 
-/* Encoder/decoder Requests */
+#define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
 
-/* Expose this option again when variable framesize actually works */
-#define OPUS_FRAMESIZE_VARIABLE              5010 /**< Optimize the frame size dynamically */
+/* Encoder/decoder Requests */
 
 
 #define CELT_SET_PREDICTION_REQUEST    10002
 /** Controls the use of interframe prediction.
     0=Independent frames
     1=Short term interframe prediction allowed
     2=Long term prediction allowed
  */
@@ -111,16 +121,19 @@ typedef struct {
 #define CELT_SET_ANALYSIS(x) CELT_SET_ANALYSIS_REQUEST, __celt_check_analysis_ptr(x)
 
 #define OPUS_SET_LFE_REQUEST    10024
 #define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, __opus_check_int(x)
 
 #define OPUS_SET_ENERGY_MASK_REQUEST    10026
 #define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x)
 
+#define CELT_SET_SILK_INFO_REQUEST    10028
+#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, __celt_check_silkinfo_ptr(x)
+
 /* Encoder stuff */
 
 int celt_encoder_get_size(int channels);
 
 int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
 
 int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels,
                       int arch);
--- a/media/libopus/celt/celt_decoder.c
+++ b/media/libopus/celt/celt_decoder.c
@@ -68,16 +68,17 @@ struct OpusCustomDecoder {
    const OpusCustomMode *mode;
    int overlap;
    int channels;
    int stream_channels;
 
    int downsample;
    int start, end;
    int signalling;
+   int disable_inv;
    int arch;
 
    /* Everything beyond this point gets cleared on a reset */
 #define DECODER_RESET_START rng
 
    opus_uint32 rng;
    int error;
    int last_pitch_index;
@@ -158,43 +159,86 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_dec
    st->mode = mode;
    st->overlap = mode->overlap;
    st->stream_channels = st->channels = channels;
 
    st->downsample = 1;
    st->start = 0;
    st->end = st->mode->effEBands;
    st->signalling = 1;
+#ifdef ENABLE_UPDATE_DRAFT
+   st->disable_inv = channels == 1;
+#else
+   st->disable_inv = 0;
+#endif
    st->arch = opus_select_arch();
 
    opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
 
    return OPUS_OK;
 }
 
 #ifdef CUSTOM_MODES
 void opus_custom_decoder_destroy(CELTDecoder *st)
 {
    opus_free(st);
 }
 #endif /* CUSTOM_MODES */
 
+#ifndef CUSTOM_MODES
+/* Special case for stereo with no downsampling and no accumulation. This is
+   quite common and we can make it faster by processing both channels in the
+   same loop, reducing overhead due to the dependency loop in the IIR filter. */
+static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0,
+      celt_sig *mem)
+{
+   celt_sig * OPUS_RESTRICT x0;
+   celt_sig * OPUS_RESTRICT x1;
+   celt_sig m0, m1;
+   int j;
+   x0=in[0];
+   x1=in[1];
+   m0 = mem[0];
+   m1 = mem[1];
+   for (j=0;j<N;j++)
+   {
+      celt_sig tmp0, tmp1;
+      /* Add VERY_SMALL to x[] first to reduce dependency chain. */
+      tmp0 = x0[j] + VERY_SMALL + m0;
+      tmp1 = x1[j] + VERY_SMALL + m1;
+      m0 = MULT16_32_Q15(coef0, tmp0);
+      m1 = MULT16_32_Q15(coef0, tmp1);
+      pcm[2*j  ] = SCALEOUT(SIG2WORD16(tmp0));
+      pcm[2*j+1] = SCALEOUT(SIG2WORD16(tmp1));
+   }
+   mem[0] = m0;
+   mem[1] = m1;
+}
+#endif
 
 #ifndef RESYNTH
 static
 #endif
 void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef,
       celt_sig *mem, int accum)
 {
    int c;
    int Nd;
    int apply_downsampling=0;
    opus_val16 coef0;
    VARDECL(celt_sig, scratch);
    SAVE_STACK;
+#ifndef CUSTOM_MODES
+   /* Short version for common case. */
+   if (downsample == 1 && C == 2 && !accum)
+   {
+      deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
+      return;
+   }
+#endif
 #ifndef FIXED_POINT
    (void)accum;
    celt_assert(accum==0);
 #endif
    ALLOC(scratch, N, celt_sig);
    coef0 = coef[0];
    Nd = N/downsample;
    c=0; do {
@@ -220,17 +264,17 @@ void deemphasis(celt_sig *in[], opus_val
          apply_downsampling=1;
       } else
 #endif
       if (downsample>1)
       {
          /* Shortcut for the standard (non-custom modes) case */
          for (j=0;j<N;j++)
          {
-            celt_sig tmp = x[j] + m + VERY_SMALL;
+            celt_sig tmp = x[j] + VERY_SMALL + m;
             m = MULT16_32_Q15(coef0, tmp);
             scratch[j] = tmp;
          }
          apply_downsampling=1;
       } else {
          /* Shortcut for the standard (non-custom modes) case */
 #ifdef FIXED_POINT
          if (accum)
@@ -241,17 +285,17 @@ void deemphasis(celt_sig *in[], opus_val
                m = MULT16_32_Q15(coef0, tmp);
                y[j*C] = SAT16(ADD32(y[j*C], SCALEOUT(SIG2WORD16(tmp))));
             }
          } else
 #endif
          {
             for (j=0;j<N;j++)
             {
-               celt_sig tmp = x[j] + m + VERY_SMALL;
+               celt_sig tmp = x[j] + VERY_SMALL + m;
                m = MULT16_32_Q15(coef0, tmp);
                y[j*C] = SCALEOUT(SIG2WORD16(tmp));
             }
          }
       }
       mem[c] = m;
 
       if (apply_downsampling)
@@ -328,28 +372,34 @@ void celt_synthesis(const CELTMode *mode
       celt_sig *freq2;
       freq2 = out_syn[0]+overlap/2;
       denormalise_bands(mode, X, freq, oldBandE, start, effEnd, M,
             downsample, silence);
       /* Use the output buffer as temp array before downmixing. */
       denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
             downsample, silence);
       for (i=0;i<N;i++)
-         freq[i] = HALF32(ADD32(freq[i],freq2[i]));
+         freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
       for (b=0;b<B;b++)
          clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
    } else {
       /* Normal case (mono or stereo) */
       c=0; do {
          denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
                downsample, silence);
          for (b=0;b<B;b++)
             clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
       } while (++c<CC);
    }
+   /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
+      or in the */
+   c=0; do {
+      for (i=0;i<N;i++)
+         out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
+   } while (++c<CC);
    RESTORE_STACK;
 }
 
 static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM, ec_dec *dec)
 {
    int i, curr, tf_select;
    int tf_select_rsv;
    int tf_changed;
@@ -501,31 +551,33 @@ static void celt_decode_lost(CELTDecoder
          OPUS_MOVE(decode_mem[c], decode_mem[c]+N,
                DECODE_BUFFER_SIZE-N+(overlap>>1));
       } while (++c<C);
 
       celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch);
    } else {
       /* Pitch-based PLC */
       const opus_val16 *window;
+      opus_val16 *exc;
       opus_val16 fade = Q15ONE;
       int pitch_index;
       VARDECL(opus_val32, etmp);
-      VARDECL(opus_val16, exc);
+      VARDECL(opus_val16, _exc);
 
       if (loss_count == 0)
       {
          st->last_pitch_index = pitch_index = celt_plc_pitch_search(decode_mem, C, st->arch);
       } else {
          pitch_index = st->last_pitch_index;
          fade = QCONST16(.8f,15);
       }
 
       ALLOC(etmp, overlap, opus_val32);
-      ALLOC(exc, MAX_PERIOD, opus_val16);
+      ALLOC(_exc, MAX_PERIOD+LPC_ORDER, opus_val16);
+      exc = _exc+LPC_ORDER;
       window = mode->window;
       c=0; do {
          opus_val16 decay;
          opus_val16 attenuation;
          opus_val32 S1=0;
          celt_sig *buf;
          int extrapolation_offset;
          int extrapolation_len;
@@ -556,32 +608,48 @@ static void celt_decode_lost(CELTDecoder
                /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
 #ifdef FIXED_POINT
                ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
 #else
                ac[i] -= ac[i]*(0.008f*0.008f)*i*i;
 #endif
             }
             _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
+#ifdef FIXED_POINT
+         /* For fixed-point, apply bandwidth expansion until we can guarantee that
+            no overflow can happen in the IIR filter. This means:
+            32768*sum(abs(filter)) < 2^31 */
+         while (1) {
+            opus_val16 tmp=Q15ONE;
+            opus_val32 sum=QCONST16(1., SIG_SHIFT);
+            for (i=0;i<LPC_ORDER;i++)
+               sum += ABS16(lpc[c*LPC_ORDER+i]);
+            if (sum < 65535) break;
+            for (i=0;i<LPC_ORDER;i++)
+            {
+               tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
+               lpc[c*LPC_ORDER+i] = MULT16_16_Q15(lpc[c*LPC_ORDER+i], tmp);
+            }
+         }
+#endif
          }
          /* We want the excitation for 2 pitch periods in order to look for a
             decaying signal, but we can't get more than MAX_PERIOD. */
          exc_length = IMIN(2*pitch_index, MAX_PERIOD);
          /* Initialize the LPC history with the samples just before the start
             of the region for which we're computing the excitation. */
          {
-            opus_val16 lpc_mem[LPC_ORDER];
             for (i=0;i<LPC_ORDER;i++)
             {
-               lpc_mem[i] =
-                     ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT);
+               exc[MAX_PERIOD-exc_length-LPC_ORDER+i] =
+                     ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-LPC_ORDER+i], SIG_SHIFT);
             }
             /* Compute the excitation for exc_length samples before the loss. */
             celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
-                  exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem, st->arch);
+                  exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, st->arch);
          }
 
          /* Check if the waveform is decaying, and if so how fast.
             We do this to avoid adding energy when concealing in a segment
             with decaying energy. */
          {
             opus_val32 E1=1, E2=1;
             int decay_length;
@@ -625,41 +693,44 @@ static void celt_decode_lost(CELTDecoder
             buf[DECODE_BUFFER_SIZE-N+i] =
                   SHL32(EXTEND32(MULT16_16_Q15(attenuation,
                         exc[extrapolation_offset+j])), SIG_SHIFT);
             /* Compute the energy of the previously decoded signal whose
                excitation we're copying. */
             tmp = ROUND16(
                   buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j],
                   SIG_SHIFT);
-            S1 += SHR32(MULT16_16(tmp, tmp), 8);
+            S1 += SHR32(MULT16_16(tmp, tmp), 10);
          }
-
          {
             opus_val16 lpc_mem[LPC_ORDER];
             /* Copy the last decoded samples (prior to the overlap region) to
                synthesis filter memory so we can have a continuous signal. */
             for (i=0;i<LPC_ORDER;i++)
                lpc_mem[i] = ROUND16(buf[DECODE_BUFFER_SIZE-N-1-i], SIG_SHIFT);
             /* Apply the synthesis filter to convert the excitation back into
                the signal domain. */
             celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
                   buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
                   lpc_mem, st->arch);
+#ifdef FIXED_POINT
+            for (i=0; i < extrapolation_len; i++)
+               buf[DECODE_BUFFER_SIZE-N+i] = SATURATE(buf[DECODE_BUFFER_SIZE-N+i], SIG_SAT);
+#endif
          }
 
          /* Check if the synthesis energy is higher than expected, which can
             happen with the signal changes during our window. If so,
             attenuate. */
          {
             opus_val32 S2=0;
             for (i=0;i<extrapolation_len;i++)
             {
                opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT);
-               S2 += SHR32(MULT16_16(tmp, tmp), 8);
+               S2 += SHR32(MULT16_16(tmp, tmp), 10);
             }
             /* This checks for an "explosion" in the synthesis. */
 #ifdef FIXED_POINT
             if (!(S1 > SHR32(S2,2)))
 #else
             /* The float test is written this way to catch NaNs in the output
                of the IIR filter at the same time. */
             if (!(S1 > 0.2f*S2))
@@ -974,17 +1045,18 @@ int celt_decode_with_ec(CELTDecoder * OP
       but it saves almost 4kB of stack. */
    X = (celt_norm*)(out_syn[CC-1]+overlap/2);
 #else
    ALLOC(X, C*N, celt_norm);   /**< Interleaved normalised MDCTs */
 #endif
 
    quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
          NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
-         len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, st->arch);
+         len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
+         st->arch, st->disable_inv);
 
    if (anti_collapse_rsv > 0)
    {
       anti_collapse_on = ec_dec_bits(dec, 1);
    }
 
    unquant_energy_finalise(mode, start, end, oldBandE,
          fine_quant, fine_priority, len*8-ec_tell(dec), dec, C);
@@ -1229,16 +1301,36 @@ int opus_custom_decoder_ctl(CELTDecoder 
       case OPUS_GET_FINAL_RANGE_REQUEST:
       {
          opus_uint32 * value = va_arg(ap, opus_uint32 *);
          if (value==0)
             goto bad_arg;
          *value=st->rng;
       }
       break;
+      case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+      {
+          opus_int32 value = va_arg(ap, opus_int32);
+          if(value<0 || value>1)
+          {
+             goto bad_arg;
+          }
+          st->disable_inv = value;
+      }
+      break;
+      case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+      {
+          opus_int32 *value = va_arg(ap, opus_int32*);
+          if (!value)
+          {
+             goto bad_arg;
+          }
+          *value = st->disable_inv;
+      }
+      break;
       default:
          goto bad_request;
    }
    va_end(ap);
    return OPUS_OK;
 bad_arg:
    va_end(ap);
    return OPUS_BAD_ARG;
--- a/media/libopus/celt/celt_encoder.c
+++ b/media/libopus/celt/celt_encoder.c
@@ -68,18 +68,18 @@ struct OpusCustomEncoder {
    int start, end;
 
    opus_int32 bitrate;
    int vbr;
    int signalling;
    int constrained_vbr;      /* If zero, VBR can do whatever it likes with the rate */
    int loss_rate;
    int lsb_depth;
-   int variable_duration;
    int lfe;
+   int disable_inv;
    int arch;
 
    /* Everything beyond this point gets cleared on a reset */
 #define ENCODER_RESET_START rng
 
    opus_uint32 rng;
    int spread_decision;
    opus_val32 delayedIntra;
@@ -93,16 +93,17 @@ struct OpusCustomEncoder {
    int prefilter_tapset;
 #ifdef RESYNTH
    int prefilter_period_old;
    opus_val16 prefilter_gain_old;
    int prefilter_tapset_old;
 #endif
    int consec_transient;
    AnalysisInfo analysis;
+   SILKInfo silk_info;
 
    opus_val32 preemph_memE[2];
    opus_val32 preemph_memD[2];
 
    /* VBR-related parameters */
    opus_int32 vbr_reservoir;
    opus_int32 vbr_drift;
    opus_int32 vbr_offset;
@@ -118,32 +119,34 @@ struct OpusCustomEncoder {
    celt_sig syn_mem[2][2*MAX_PERIOD+MAX_PERIOD/2];
 #endif
 
    celt_sig in_mem[1]; /* Size = channels*mode->overlap */
    /* celt_sig prefilter_mem[],  Size = channels*COMBFILTER_MAXPERIOD */
    /* opus_val16 oldBandE[],     Size = channels*mode->nbEBands */
    /* opus_val16 oldLogE[],      Size = channels*mode->nbEBands */
    /* opus_val16 oldLogE2[],     Size = channels*mode->nbEBands */
+   /* opus_val16 energyError[],  Size = channels*mode->nbEBands */
 };
 
 int celt_encoder_get_size(int channels)
 {
    CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
    return opus_custom_encoder_get_size(mode, channels);
 }
 
 OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int channels)
 {
    int size = sizeof(struct CELTEncoder)
          + (channels*mode->overlap-1)*sizeof(celt_sig)    /* celt_sig in_mem[channels*mode->overlap]; */
          + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */
-         + 3*channels*mode->nbEBands*sizeof(opus_val16);  /* opus_val16 oldBandE[channels*mode->nbEBands]; */
+         + 4*channels*mode->nbEBands*sizeof(opus_val16);  /* opus_val16 oldBandE[channels*mode->nbEBands]; */
                                                           /* opus_val16 oldLogE[channels*mode->nbEBands]; */
                                                           /* opus_val16 oldLogE2[channels*mode->nbEBands]; */
+                                                          /* opus_val16 energyError[channels*mode->nbEBands]; */
    return size;
 }
 
 #ifdef CUSTOM_MODES
 CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error)
 {
    int ret;
    CELTEncoder *st = (CELTEncoder *)opus_alloc(opus_custom_encoder_get_size(mode, channels));
@@ -173,17 +176,16 @@ static int opus_custom_encoder_init_arch
 
    st->mode = mode;
    st->stream_channels = st->channels = channels;
 
    st->upsample = 1;
    st->start = 0;
    st->end = st->mode->effEBands;
    st->signalling = 1;
-
    st->arch = arch;
 
    st->constrained_vbr = 1;
    st->clip = 1;
 
    st->bitrate = OPUS_BITRATE_MAX;
    st->vbr = 0;
    st->force_intra  = 0;
@@ -218,40 +220,60 @@ int celt_encoder_init(CELTEncoder *st, o
 void opus_custom_encoder_destroy(CELTEncoder *st)
 {
    opus_free(st);
 }
 #endif /* CUSTOM_MODES */
 
 
 static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C,
-                              opus_val16 *tf_estimate, int *tf_chan)
+                              opus_val16 *tf_estimate, int *tf_chan, int allow_weak_transients,
+                              int *weak_transient)
 {
    int i;
    VARDECL(opus_val16, tmp);
    opus_val32 mem0,mem1;
    int is_transient = 0;
    opus_int32 mask_metric = 0;
    int c;
    opus_val16 tf_max;
    int len2;
+   /* Forward masking: 6.7 dB/ms. */
+#ifdef FIXED_POINT
+   int forward_shift = 4;
+#else
+   opus_val16 forward_decay = QCONST16(.0625f,15);
+#endif
    /* Table of 6*64/x, trained on real data to minimize the average error */
    static const unsigned char inv_table[128] = {
          255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25,
           23, 22, 21, 20, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
           12, 12, 11, 11, 11, 10, 10, 10,  9,  9,  9,  9,  9,  9,  8,  8,
            8,  8,  8,  7,  7,  7,  7,  7,  7,  6,  6,  6,  6,  6,  6,  6,
            6,  6,  6,  6,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  5,  5,
            5,  5,  5,  5,  5,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,
            4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  3,  3,
            3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,
    };
    SAVE_STACK;
    ALLOC(tmp, len, opus_val16);
 
+   *weak_transient = 0;
+   /* For lower bitrates, let's be more conservative and have a forward masking
+      decay of 3.3 dB/ms. This avoids having to code transients at very low
+      bitrate (mostly for hybrid), which can result in unstable energy and/or
+      partial collapse. */
+   if (allow_weak_transients)
+   {
+#ifdef FIXED_POINT
+      forward_shift = 5;
+#else
+      forward_decay = QCONST16(.03125f,15);
+#endif
+   }
    len2=len/2;
    for (c=0;c<C;c++)
    {
       opus_val32 mean;
       opus_int32 unmask=0;
       opus_val32 norm;
       opus_val16 maxE;
       mem0=0;
@@ -264,28 +286,28 @@ static int transient_analysis(const opus
          y = ADD32(mem0, x);
 #ifdef FIXED_POINT
          mem0 = mem1 + y - SHL32(x,1);
          mem1 = x - SHR32(y,1);
 #else
          mem0 = mem1 + y - 2*x;
          mem1 = x - .5f*y;
 #endif
-         tmp[i] = EXTRACT16(SHR32(y,2));
+         tmp[i] = SROUND16(y, 2);
          /*printf("%f ", tmp[i]);*/
       }
       /*printf("\n");*/
       /* First few samples are bad because we don't propagate the memory */
       OPUS_CLEAR(tmp, 12);
 
 #ifdef FIXED_POINT
       /* Normalize tmp to max range */
       {
          int shift=0;
-         shift = 14-celt_ilog2(1+celt_maxabs16(tmp, len));
+         shift = 14-celt_ilog2(MAX16(1, celt_maxabs16(tmp, len)));
          if (shift!=0)
          {
             for (i=0;i<len;i++)
                tmp[i] = SHL16(tmp[i], shift);
          }
       }
 #endif
 
@@ -294,28 +316,29 @@ static int transient_analysis(const opus
       /* Grouping by two to reduce complexity */
       /* Forward pass to compute the post-echo threshold*/
       for (i=0;i<len2;i++)
       {
          opus_val16 x2 = PSHR32(MULT16_16(tmp[2*i],tmp[2*i]) + MULT16_16(tmp[2*i+1],tmp[2*i+1]),16);
          mean += x2;
 #ifdef FIXED_POINT
          /* FIXME: Use PSHR16() instead */
-         tmp[i] = mem0 + PSHR32(x2-mem0,4);
+         tmp[i] = mem0 + PSHR32(x2-mem0,forward_shift);
 #else
-         tmp[i] = mem0 + MULT16_16_P15(QCONST16(.0625f,15),x2-mem0);
+         tmp[i] = mem0 + MULT16_16_P15(forward_decay,x2-mem0);
 #endif
          mem0 = tmp[i];
       }
 
       mem0=0;
       maxE=0;
       /* Backward pass to compute the pre-echo threshold */
       for (i=len2-1;i>=0;i--)
       {
+         /* Backward masking: 13.9 dB/ms. */
 #ifdef FIXED_POINT
          /* FIXME: Use PSHR16() instead */
          tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3);
 #else
          tmp[i] = mem0 + MULT16_16_P15(QCONST16(0.125f,15),tmp[i]-mem0);
 #endif
          mem0 = tmp[i];
          maxE = MAX16(maxE, mem0);
@@ -354,17 +377,22 @@ static int transient_analysis(const opus
       unmask = 64*unmask*4/(6*(len2-17));
       if (unmask>mask_metric)
       {
          *tf_chan = c;
          mask_metric = unmask;
       }
    }
    is_transient = mask_metric>200;
-
+   /* For low bitrates, define "weak transients" that need to be
+      handled differently to avoid partial collapse. */
+   if (allow_weak_transients && is_transient && mask_metric<600) {
+      is_transient = 0;
+      *weak_transient = 1;
+   }
    /* Arbitrary metric for VBR boost */
    tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42);
    /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */
    *tf_estimate = celt_sqrt(MAX32(0, SHL32(MULT16_16(QCONST16(0.0069,14),MIN16(163,tf_max)),14)-QCONST32(0.139,28)));
    /*printf("%d %f\n", tf_max, mask_metric);*/
    RESTORE_STACK;
 #ifdef FUZZING
    is_transient = rand()&0x1;
@@ -544,17 +572,17 @@ static opus_val32 l1_metric(const celt_n
    /* When in doubt, prefer good freq resolution */
    L1 = MAC16_32_Q15(L1, LM*bias, L1);
    return L1;
 
 }
 
 static int tf_analysis(const CELTMode *m, int len, int isTransient,
       int *tf_res, int lambda, celt_norm *X, int N0, int LM,
-      int *tf_sum, opus_val16 tf_estimate, int tf_chan)
+      opus_val16 tf_estimate, int tf_chan)
 {
    int i;
    VARDECL(int, metric);
    int cost0;
    int cost1;
    VARDECL(int, path0);
    VARDECL(int, path1);
    VARDECL(celt_norm, tmp);
@@ -569,17 +597,16 @@ static int tf_analysis(const CELTMode *m
    /*printf("%f ", bias);*/
 
    ALLOC(metric, len, int);
    ALLOC(tmp, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm);
    ALLOC(tmp_1, (m->eBands[len]-m->eBands[len-1])<<LM, celt_norm);
    ALLOC(path0, len, int);
    ALLOC(path1, len, int);
 
-   *tf_sum = 0;
    for (i=0;i<len;i++)
    {
       int k, N;
       int narrow;
       opus_val32 L1, best_L1;
       int best_level=0;
       N = (m->eBands[i+1]-m->eBands[i])<<LM;
       /* band is too narrow to be split down to LM=-1 */
@@ -624,17 +651,16 @@ static int tf_analysis(const CELTMode *m
          }
       }
       /*printf ("%d ", isTransient ? LM-best_level : best_level);*/
       /* metric is in Q1 to be able to select the mid-point (-0.5) for narrower bands */
       if (isTransient)
          metric[i] = 2*best_level;
       else
          metric[i] = -2*best_level;
-      *tf_sum += (isTransient ? LM : 0) - metric[i]/2;
       /* For bands that can't be split to -1, set the metric to the half-way point to avoid
          biasing the decision */
       if (narrow && (metric[i]==0 || metric[i]==-2*LM))
          metric[i]-=1;
       /*printf("%d ", metric[i]);*/
    }
    /*printf("\n");*/
    /* Search for the optimal tf resolution, including tf_select */
@@ -749,24 +775,32 @@ static void tf_encode(int start, int end
       tf_res[i] = tf_select_table[LM][4*isTransient+2*tf_select+tf_res[i]];
    /*for(i=0;i<end;i++)printf("%d ", isTransient ? tf_res[i] : LM+tf_res[i]);printf("\n");*/
 }
 
 
 static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
       const opus_val16 *bandLogE, int end, int LM, int C, int N0,
       AnalysisInfo *analysis, opus_val16 *stereo_saving, opus_val16 tf_estimate,
-      int intensity, opus_val16 surround_trim, int arch)
+      int intensity, opus_val16 surround_trim, opus_int32 equiv_rate, int arch)
 {
    int i;
    opus_val32 diff=0;
    int c;
    int trim_index;
    opus_val16 trim = QCONST16(5.f, 8);
    opus_val16 logXC, logXC2;
+   /* At low bitrate, reducing the trim seems to help. At higher bitrates, it's less
+      clear what's best, so we're keeping it as it was before, at least for now. */
+   if (equiv_rate < 64000) {
+      trim = QCONST16(4.f, 8);
+   } else if (equiv_rate < 80000) {
+      opus_int32 frac = (equiv_rate-64000) >> 10;
+      trim = QCONST16(4.f, 8) + QCONST16(1.f/16.f, 8)*frac;
+   }
    if (C==2)
    {
       opus_val16 sum = 0; /* Q10 */
       opus_val16 minXC; /* Q10 */
       /* Compute inter-channel correlation for low frequencies */
       for (i=0;i<8;i++)
       {
          opus_val32 partial;
@@ -804,17 +838,17 @@ static int alloc_trim_analysis(const CEL
    c=0; do {
       for (i=0;i<end-1;i++)
       {
          diff += bandLogE[i+c*m->nbEBands]*(opus_int32)(2+2*i-end);
       }
    } while (++c<C);
    diff /= C*(end-1);
    /*printf("%f\n", diff);*/
-   trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), SHR16(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 ));
+   trim -= MAX32(-QCONST16(2.f, 8), MIN32(QCONST16(2.f, 8), SHR32(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 ));
    trim -= SHR16(surround_trim, DB_SHIFT-8);
    trim -= 2*SHR16(tf_estimate, 14-8);
 #ifndef DISABLE_FLOAT_API
    if (analysis->valid)
    {
       trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8),
             (opus_val16)(QCONST16(2.f, 8)*(analysis->tonality_slope+.05f))));
    }
@@ -925,17 +959,17 @@ static opus_val16 median_of_3(const opus
       return t2;
    else
       return t0;
 }
 
 static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2,
       int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN,
       int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM,
-      int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc)
+      int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc, AnalysisInfo *analysis)
 {
    int i, c;
    opus_int32 tot_boost=0;
    opus_val16 maxDepth;
    VARDECL(opus_val16, follower);
    VARDECL(opus_val16, noise_floor);
    SAVE_STACK;
    ALLOC(follower, C*nbEBands, opus_val16);
@@ -1015,43 +1049,55 @@ static opus_val16 dynalloc_analysis(cons
       /* For non-transient CBR/CVBR frames, halve the dynalloc contribution */
       if ((!vbr || constrained_vbr)&&!isTransient)
       {
          for (i=start;i<end;i++)
             follower[i] = HALF16(follower[i]);
       }
       for (i=start;i<end;i++)
       {
+         if (i<8)
+            follower[i] *= 2;
+         if (i>=12)
+            follower[i] = HALF16(follower[i]);
+      }
+#ifdef DISABLE_FLOAT_API
+      (void)analysis;
+#else
+      if (analysis->valid)
+      {
+         for (i=start;i<IMIN(LEAK_BANDS, end);i++)
+            follower[i] = follower[i] +  QCONST16(1.f/64.f, DB_SHIFT)*analysis->leak_boost[i];
+      }
+#endif
+      for (i=start;i<end;i++)
+      {
          int width;
          int boost;
          int boost_bits;
 
-         if (i<8)
-            follower[i] *= 2;
-         if (i>=12)
-            follower[i] = HALF16(follower[i]);
          follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT));
 
          width = C*(eBands[i+1]-eBands[i])<<LM;
          if (width<6)
          {
             boost = (int)SHR32(EXTEND32(follower[i]),DB_SHIFT);
             boost_bits = boost*width<<BITRES;
          } else if (width > 48) {
             boost = (int)SHR32(EXTEND32(follower[i])*8,DB_SHIFT);
             boost_bits = (boost*width<<BITRES)/8;
          } else {
             boost = (int)SHR32(EXTEND32(follower[i])*width/6,DB_SHIFT);
             boost_bits = boost*6<<BITRES;
          }
-         /* For CBR and non-transient CVBR frames, limit dynalloc to 1/4 of the bits */
+         /* For CBR and non-transient CVBR frames, limit dynalloc to 2/3 of the bits */
          if ((!vbr || (constrained_vbr&&!isTransient))
-               && (tot_boost+boost_bits)>>BITRES>>3 > effectiveBytes/4)
+               && (tot_boost+boost_bits)>>BITRES>>3 > 2*effectiveBytes/3)
          {
-            opus_int32 cap = ((effectiveBytes/4)<<BITRES<<3);
+            opus_int32 cap = ((2*effectiveBytes/3)<<BITRES<<3);
             offsets[i] = cap-tot_boost;
             tot_boost = cap;
             break;
          } else {
             offsets[i] = boost;
             tot_boost += boost_bits;
          }
       }
@@ -1188,17 +1234,17 @@ static int run_prefilter(CELTEncoder *st
    *qgain = qg;
    return pf_on;
 }
 
 static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32 base_target,
       int LM, opus_int32 bitrate, int lastCodedBands, int C, int intensity,
       int constrained_vbr, opus_val16 stereo_saving, int tot_boost,
       opus_val16 tf_estimate, int pitch_change, opus_val16 maxDepth,
-      int variable_duration, int lfe, int has_surround_mask, opus_val16 surround_masking,
+      int lfe, int has_surround_mask, opus_val16 surround_masking,
       opus_val16 temporal_vbr)
 {
    /* The target rate in 8th bits per frame */
    opus_int32 target;
    int coded_bins;
    int coded_bands;
    opus_val16 tf_calibration;
    int nbEBands;
@@ -1230,31 +1276,30 @@ static int compute_vbr(const CELTMode *m
       /* Maximum fraction of the bits we can save if the signal is mono. */
       max_frac = DIV32_16(MULT16_16(QCONST16(0.8f, 15), coded_stereo_dof), coded_bins);
       stereo_saving = MIN16(stereo_saving, QCONST16(1.f, 8));
       /*printf("%d %d %d ", coded_stereo_dof, coded_bins, tot_boost);*/
       target -= (opus_int32)MIN32(MULT16_32_Q15(max_frac,target),
                       SHR32(MULT16_16(stereo_saving-QCONST16(0.1f,8),(coded_stereo_dof<<BITRES)),8));
    }
    /* Boost the rate according to dynalloc (minus the dynalloc average for calibration). */
-   target += tot_boost-(16<<LM);
+   target += tot_boost-(19<<LM);
    /* Apply transient boost, compensating for average boost. */
-   tf_calibration = variable_duration==OPUS_FRAMESIZE_VARIABLE ?
-                    QCONST16(0.02f,14) : QCONST16(0.04f,14);
+   tf_calibration = QCONST16(0.044f,14);
    target += (opus_int32)SHL32(MULT16_32_Q15(tf_estimate-tf_calibration, target),1);
 
 #ifndef DISABLE_FLOAT_API
    /* Apply tonality boost */
    if (analysis->valid && !lfe)
    {
       opus_int32 tonal_target;
       float tonal;
 
       /* Tonality boost (compensating for the average). */
-      tonal = MAX16(0.f,analysis->tonality-.15f)-0.09f;
+      tonal = MAX16(0.f,analysis->tonality-.15f)-0.12f;
       tonal_target = target + (opus_int32)((coded_bins<<BITRES)*1.2f*tonal);
       if (pitch_change)
          tonal_target +=  (opus_int32)((coded_bins<<BITRES)*.8f);
       /*printf("%f %f ", analysis->tonality, tonal);*/
       target = tonal_target;
    }
 #else
    (void)analysis;
@@ -1274,31 +1319,21 @@ static int compute_vbr(const CELTMode *m
       bins = eBands[nbEBands-2]<<LM;
       /*floor_depth = SHR32(MULT16_16((C*bins<<BITRES),celt_log2(SHL32(MAX16(1,sample_max),13))), DB_SHIFT);*/
       floor_depth = (opus_int32)SHR32(MULT16_16((C*bins<<BITRES),maxDepth), DB_SHIFT);
       floor_depth = IMAX(floor_depth, target>>2);
       target = IMIN(target, floor_depth);
       /*printf("%f %d\n", maxDepth, floor_depth);*/
    }
 
-   if ((!has_surround_mask||lfe) && (constrained_vbr || bitrate<64000))
+   /* Make VBR less aggressive for constrained VBR because we can't keep a higher bitrate
+      for long. Needs tuning. */
+   if ((!has_surround_mask||lfe) && constrained_vbr)
    {
-      opus_val16 rate_factor = Q15ONE;
-      if (bitrate < 64000)
-      {
-#ifdef FIXED_POINT
-         rate_factor = MAX16(0,(bitrate-32000));
-#else
-         rate_factor = MAX16(0,(1.f/32768)*(bitrate-32000));
-#endif
-      }
-      if (constrained_vbr)
-         rate_factor = MIN16(rate_factor, QCONST16(0.67f, 15));
-      target = base_target + (opus_int32)MULT16_32_Q15(rate_factor, target-base_target);
-
+      target = base_target + (opus_int32)MULT16_32_Q15(QCONST16(0.67f, 15), target-base_target);
    }
 
    if (!has_surround_mask && tf_estimate < QCONST16(.2f, 14))
    {
       opus_val16 amount;
       opus_val16 tvbr_factor;
       amount = MULT16_16_Q15(QCONST16(.0000031f, 30), IMAX(0, IMIN(32000, 96000-bitrate)));
       tvbr_factor = SHR32(MULT16_16(temporal_vbr, amount), DB_SHIFT);
@@ -1326,40 +1361,40 @@ int celt_encode_with_ec(CELTEncoder * OP
    VARDECL(opus_val16, error);
    VARDECL(int, pulses);
    VARDECL(int, cap);
    VARDECL(int, offsets);
    VARDECL(int, fine_priority);
    VARDECL(int, tf_res);
    VARDECL(unsigned char, collapse_masks);
    celt_sig *prefilter_mem;
-   opus_val16 *oldBandE, *oldLogE, *oldLogE2;
+   opus_val16 *oldBandE, *oldLogE, *oldLogE2, *energyError;
    int shortBlocks=0;
    int isTransient=0;
    const int CC = st->channels;
    const int C = st->stream_channels;
    int LM, M;
    int tf_select;
    int nbFilledBytes, nbAvailableBytes;
    int start;
    int end;
    int effEnd;
    int codedBands;
-   int tf_sum;
    int alloc_trim;
    int pitch_index=COMBFILTER_MINPERIOD;
    opus_val16 gain1 = 0;
    int dual_stereo=0;
    int effectiveBytes;
    int dynalloc_logp;
    opus_int32 vbr_rate;
    opus_int32 total_bits;
    opus_int32 total_boost;
    opus_int32 balance;
    opus_int32 tell;
+   opus_int32 tell0_frac;
    int prefilter_tapset=0;
    int pf_on;
    int anti_collapse_rsv;
    int anti_collapse_on=0;
    int silence=0;
    int tf_chan = 0;
    opus_val16 tf_estimate;
    int pitch_change=0;
@@ -1371,26 +1406,29 @@ int celt_encode_with_ec(CELTEncoder * OP
    int overlap;
    const opus_int16 *eBands;
    int secondMdct;
    int signalBandwidth;
    int transient_got_disabled=0;
    opus_val16 surround_masking=0;
    opus_val16 temporal_vbr=0;
    opus_val16 surround_trim = 0;
-   opus_int32 equiv_rate = 510000;
+   opus_int32 equiv_rate;
+   int hybrid;
+   int weak_transient = 0;
    VARDECL(opus_val16, surround_dynalloc);
    ALLOC_STACK;
 
    mode = st->mode;
    nbEBands = mode->nbEBands;
    overlap = mode->overlap;
    eBands = mode->eBands;
    start = st->start;
    end = st->end;
+   hybrid = start != 0;
    tf_estimate = 0;
    if (nbCompressedBytes<2 || pcm==NULL)
    {
       RESTORE_STACK;
       return OPUS_BAD_ARG;
    }
 
    frame_size *= st->upsample;
@@ -1404,22 +1442,24 @@ int celt_encode_with_ec(CELTEncoder * OP
    }
    M=1<<LM;
    N = M*mode->shortMdctSize;
 
    prefilter_mem = st->in_mem+CC*(overlap);
    oldBandE = (opus_val16*)(st->in_mem+CC*(overlap+COMBFILTER_MAXPERIOD));
    oldLogE = oldBandE + CC*nbEBands;
    oldLogE2 = oldLogE + CC*nbEBands;
+   energyError = oldLogE2 + CC*nbEBands;
 
    if (enc==NULL)
    {
-      tell=1;
+      tell0_frac=tell=1;
       nbFilledBytes=0;
    } else {
+      tell0_frac=tell=ec_tell_frac(enc);
       tell=ec_tell(enc);
       nbFilledBytes=(tell+4)>>3;
    }
 
 #ifdef CUSTOM_MODES
    if (st->signalling && enc==NULL)
    {
       int tmp = (mode->effEBands-end)>>1;
@@ -1462,20 +1502,21 @@ int celt_encode_with_ec(CELTEncoder * OP
       opus_int32 tmp;
       vbr_rate = 0;
       tmp = st->bitrate*frame_size;
       if (tell>1)
          tmp += tell;
       if (st->bitrate!=OPUS_BITRATE_MAX)
          nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes,
                (tmp+4*mode->Fs)/(8*mode->Fs)-!!st->signalling));
-      effectiveBytes = nbCompressedBytes;
+      effectiveBytes = nbCompressedBytes - nbFilledBytes;
    }
+   equiv_rate = ((opus_int32)nbCompressedBytes*8*50 >> (3-LM)) - (40*C+20)*((400>>LM) - 50);
    if (st->bitrate != OPUS_BITRATE_MAX)
-      equiv_rate = st->bitrate - (40*C+20)*((400>>LM) - 50);
+      equiv_rate = IMIN(equiv_rate, st->bitrate - (40*C+20)*((400>>LM) - 50));
 
    if (enc==NULL)
    {
       ec_enc_init(&_enc, compressed, nbCompressedBytes);
       enc = &_enc;
    }
 
    if (vbr_rate>0)
@@ -1553,27 +1594,27 @@ int celt_encode_with_ec(CELTEncoder * OP
    } while (++c<CC);
 
 
 
    /* Find pitch period and gain */
    {
       int enabled;
       int qg;
-      enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && start==0 && !silence && !st->disable_pf
-            && st->complexity >= 5 && !(st->consec_transient && LM!=3 && st->variable_duration==OPUS_FRAMESIZE_VARIABLE);
+      enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && !hybrid && !silence && !st->disable_pf
+            && st->complexity >= 5;
 
       prefilter_tapset = st->tapset_decision;
       pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes);
       if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3)
             && (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period))
          pitch_change = 1;
       if (pf_on==0)
       {
-         if(start==0 && tell+16<=total_bits)
+         if(!hybrid && tell+16<=total_bits)
             ec_enc_bit_logp(enc, 0, 1);
       } else {
          /*This block is not gated by a total bits check only because
            of the nbAvailableBytes check above.*/
          int octave;
          ec_enc_bit_logp(enc, 1, 1);
          pitch_index += 1;
          octave = EC_ILOG(pitch_index)-5;
@@ -1584,18 +1625,22 @@ int celt_encode_with_ec(CELTEncoder * OP
          ec_enc_icdf(enc, prefilter_tapset, tapset_icdf, 2);
       }
    }
 
    isTransient = 0;
    shortBlocks = 0;
    if (st->complexity >= 1 && !st->lfe)
    {
+      /* Reduces the likelihood of energy instability on fricatives at low bitrate
+         in hybrid mode. It seems like we still want to have real transients on vowels
+         though (small SILK quantization offset value). */
+      int allow_weak_transients = hybrid && effectiveBytes<15 && st->silk_info.offset >= 100;
       isTransient = transient_analysis(in, N+overlap, CC,
-            &tf_estimate, &tf_chan);
+            &tf_estimate, &tf_chan, allow_weak_transients, &weak_transient);
    }
    if (LM>0 && ec_tell(enc)+3<=total_bits)
    {
       if (isTransient)
          shortBlocks = M;
    } else {
       isTransient = 0;
       transient_got_disabled=1;
@@ -1605,41 +1650,41 @@ int celt_encode_with_ec(CELTEncoder * OP
    ALLOC(bandE,nbEBands*CC, celt_ener);
    ALLOC(bandLogE,nbEBands*CC, opus_val16);
 
    secondMdct = shortBlocks && st->complexity>=8;
    ALLOC(bandLogE2, C*nbEBands, opus_val16);
    if (secondMdct)
    {
       compute_mdcts(mode, 0, in, freq, C, CC, LM, st->upsample, st->arch);
-      compute_band_energies(mode, freq, bandE, effEnd, C, LM);
+      compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
       amp2Log2(mode, effEnd, end, bandE, bandLogE2, C);
       for (i=0;i<C*nbEBands;i++)
          bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT));
    }
 
    compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch);
    if (CC==2&&C==1)
       tf_chan = 0;
-   compute_band_energies(mode, freq, bandE, effEnd, C, LM);
+   compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
 
    if (st->lfe)
    {
       for (i=2;i<end;i++)
       {
          bandE[i] = IMIN(bandE[i], MULT16_32_Q15(QCONST16(1e-4f,15),bandE[0]));
          bandE[i] = MAX32(bandE[i], EPSILON);
       }
    }
    amp2Log2(mode, effEnd, end, bandE, bandLogE, C);
 
    ALLOC(surround_dynalloc, C*nbEBands, opus_val16);
    OPUS_CLEAR(surround_dynalloc, end);
    /* This computes how much masking takes place between surround channels */
-   if (start==0&&st->energy_mask&&!st->lfe)
+   if (!hybrid&&st->energy_mask&&!st->lfe)
    {
       int mask_end;
       int midband;
       int count_dynalloc;
       opus_val32 mask_avg=0;
       opus_val32 diff=0;
       int count=0;
       mask_end = IMAX(2,st->lastCodedBands);
@@ -1731,24 +1776,24 @@ int celt_encode_with_ec(CELTEncoder * OP
 
    if (!secondMdct)
    {
       OPUS_COPY(bandLogE2, bandLogE, C*nbEBands);
    }
 
    /* Last chance to catch any transient we might have missed in the
       time-domain analysis */
-   if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe)
+   if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe && !hybrid)
    {
       if (patch_transient_decision(bandLogE, oldBandE, nbEBands, start, end, C))
       {
          isTransient = 1;
          shortBlocks = M;
          compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch);
-         compute_band_energies(mode, freq, bandE, effEnd, C, LM);
+         compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
          amp2Log2(mode, effEnd, end, bandE, bandLogE, C);
          /* Compensate for the scaling of short vs long mdcts */
          for (i=0;i<C*nbEBands;i++)
             bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT));
          tf_estimate = QCONST16(.2f,14);
       }
    }
 
@@ -1757,53 +1802,79 @@ int celt_encode_with_ec(CELTEncoder * OP
 
    ALLOC(X, C*N, celt_norm);         /**< Interleaved normalised MDCTs */
 
    /* Band normalisation */
    normalise_bands(mode, freq, X, bandE, effEnd, C, M);
 
    ALLOC(tf_res, nbEBands, int);
    /* Disable variable tf resolution for hybrid and at very low bitrate */
-   if (effectiveBytes>=15*C && start==0 && st->complexity>=2 && !st->lfe)
+   if (effectiveBytes>=15*C && !hybrid && st->complexity>=2 && !st->lfe)
    {
       int lambda;
-      if (effectiveBytes<40)
-         lambda = 12;
-      else if (effectiveBytes<60)
-         lambda = 6;
-      else if (effectiveBytes<100)
-         lambda = 4;
-      else
-         lambda = 3;
-      lambda*=2;
-      tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, &tf_sum, tf_estimate, tf_chan);
+      lambda = IMAX(5, 1280/effectiveBytes + 2);
+      tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, tf_estimate, tf_chan);
       for (i=effEnd;i<end;i++)
          tf_res[i] = tf_res[effEnd-1];
+   } else if (hybrid && weak_transient)
+   {
+      /* For weak transients, we rely on the fact that improving time resolution using
+         TF on a long window is imperfect and will not result in an energy collapse at
+         low bitrate. */
+      for (i=0;i<end;i++)
+         tf_res[i] = 1;
+      tf_select=0;
+   } else if (hybrid && effectiveBytes<15)
+   {
+      /* For low bitrate hybrid, we force temporal resolution to 5 ms rather than 2.5 ms. */
+      for (i=0;i<end;i++)
+         tf_res[i] = 0;
+      tf_select=isTransient;
    } else {
-      tf_sum = 0;
       for (i=0;i<end;i++)
          tf_res[i] = isTransient;
       tf_select=0;
    }
 
    ALLOC(error, C*nbEBands, opus_val16);
+   c=0;
+   do {
+      for (i=start;i<end;i++)
+      {
+         /* When the energy is stable, slightly bias energy quantization towards
+            the previous error to make the gain more stable (a constant offset is
+            better than fluctuations). */
+         if (ABS32(SUB32(bandLogE[i+c*nbEBands], oldBandE[i+c*nbEBands])) < QCONST16(2.f, DB_SHIFT))
+         {
+            bandLogE[i+c*nbEBands] -= MULT16_16_Q15(energyError[i+c*nbEBands], QCONST16(0.25f, 15));
+         }
+      }
+   } while (++c < C);
    quant_coarse_energy(mode, start, end, effEnd, bandLogE,
          oldBandE, total_bits, error, enc,
          C, LM, nbAvailableBytes, st->force_intra,
          &st->delayedIntra, st->complexity >= 4, st->loss_rate, st->lfe);
 
    tf_encode(start, end, isTransient, tf_res, LM, tf_select, enc);
 
    if (ec_tell(enc)+4<=total_bits)
    {
       if (st->lfe)
       {
          st->tapset_decision = 0;
          st->spread_decision = SPREAD_NORMAL;
-      } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C || start != 0)
+      } else if (hybrid)
+      {
+         if (st->complexity == 0)
+            st->spread_decision = SPREAD_NONE;
+         else if (isTransient)
+            st->spread_decision = SPREAD_NORMAL;
+         else
+            st->spread_decision = SPREAD_AGGRESSIVE;
+      } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C)
       {
          if (st->complexity == 0)
             st->spread_decision = SPREAD_NONE;
          else
             st->spread_decision = SPREAD_NORMAL;
       } else {
          /* Disable new spreading+tapset estimator until we can show it works
             better than the old one. So far it seems like spreading_decision()
@@ -1829,17 +1900,17 @@ int celt_encode_with_ec(CELTEncoder * OP
       }
       ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5);
    }
 
    ALLOC(offsets, nbEBands, int);
 
    maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets,
          st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr,
-         eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc);
+         eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc, &st->analysis);
    /* For LFE, everything interesting is in the first band */
    if (st->lfe)
       offsets[0] = IMIN(8, effectiveBytes/3);
    ALLOC(cap, nbEBands, int);
    init_caps(mode,cap,LM,C);
 
    dynalloc_logp = 6;
    total_bits<<=BITRES;
@@ -1891,22 +1962,25 @@ int celt_encode_with_ec(CELTEncoder * OP
       st->intensity = hysteresis_decision((opus_val16)(equiv_rate/1000),
             intensity_thresholds, intensity_histeresis, 21, st->intensity);
       st->intensity = IMIN(end,IMAX(start, st->intensity));
    }
 
    alloc_trim = 5;
    if (tell+(6<<BITRES) <= total_bits - total_boost)
    {
-      if (st->lfe)
+      if (start > 0 || st->lfe)
+      {
+         st->stereo_saving = 0;
          alloc_trim = 5;
-      else
+      } else {
          alloc_trim = alloc_trim_analysis(mode, X, bandLogE,
             end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate,
-            st->intensity, surround_trim, st->arch);
+            st->intensity, surround_trim, equiv_rate, st->arch);
+      }
       ec_enc_icdf(enc, alloc_trim, trim_icdf, 7);
       tell = ec_tell_frac(enc);
    }
 
    /* Variable bitrate */
    if (vbr_rate>0)
    {
      opus_val16 alpha;
@@ -1914,39 +1988,63 @@ int celt_encode_with_ec(CELTEncoder * OP
      /* The target rate in 8th bits per frame */
      opus_int32 target, base_target;
      opus_int32 min_allowed;
      int lm_diff = mode->maxLM - LM;
 
      /* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms.
         The CELT allocator will just not be able to use more than that anyway. */
      nbCompressedBytes = IMIN(nbCompressedBytes,1275>>(3-LM));
-     base_target = vbr_rate - ((40*C+20)<<BITRES);
+     if (!hybrid)
+     {
+        base_target = vbr_rate - ((40*C+20)<<BITRES);
+     } else {
+        base_target = IMAX(0, vbr_rate - ((9*C+4)<<BITRES));
+     }
 
      if (st->constrained_vbr)
         base_target += (st->vbr_offset>>lm_diff);
 
-     target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate,
+     if (!hybrid)
+     {
+        target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate,
            st->lastCodedBands, C, st->intensity, st->constrained_vbr,
            st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth,
-           st->variable_duration, st->lfe, st->energy_mask!=NULL, surround_masking,
+           st->lfe, st->energy_mask!=NULL, surround_masking,
            temporal_vbr);
-
+     } else {
+        target = base_target;
+        /* Tonal frames (offset<100) need more bits than noisy (offset>100) ones. */
+        if (st->silk_info.offset < 100) target += 12 << BITRES >> (3-LM);
+        if (st->silk_info.offset > 100) target -= 18 << BITRES >> (3-LM);
+        /* Boosting bitrate on transients and vowels with significant temporal
+           spikes. */
+        target += (opus_int32)MULT16_16_Q14(tf_estimate-QCONST16(.25f,14), (50<<BITRES));
+        /* If we have a strong transient, let's make sure it has enough bits to code
+           the first two bands, so that it can use folding rather than noise. */
+        if (tf_estimate > QCONST16(.7f,14))
+           target = IMAX(target, 50<<BITRES);
+     }
      /* The current offset is removed from the target and the space used
         so far is added*/
      target=target+tell;
      /* In VBR mode the frame size must not be reduced so much that it would
          result in the encoder running out of bits.
         The margin of 2 bytes ensures that none of the bust-prevention logic
          in the decoder will have triggered so far. */
-     min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes;
+     min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2;
+     /* Take into account the 37 bits we need to have left in the packet to
+        signal a redundant frame in hybrid mode. Creating a shorter packet would
+        create an entropy coder desync. */
+     if (hybrid)
+        min_allowed = IMAX(min_allowed, (tell0_frac+(37<<BITRES)+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3));
 
      nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3);
      nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes);
-     nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes;
+     nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes);
 
      /* By how much did we "miss" the target on that frame */
      delta = target - vbr_rate;
 
      target=nbAvailableBytes<<(BITRES+3);
 
      /*If the frame is silent we don't adjust our drift, otherwise
        the encoder will shoot to very high rates after hitting a
@@ -1983,17 +2081,17 @@ int celt_encode_with_ec(CELTEncoder * OP
      {
         /* We're under the min value -- increase rate */
         int adjust = (-st->vbr_reservoir)/(8<<BITRES);
         /* Unless we're just coding silence */
         nbAvailableBytes += silence?0:adjust;
         st->vbr_reservoir = 0;
         /*printf ("+%d\n", adjust);*/
      }
-     nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
+     nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes);
      /*printf("%d\n", nbCompressedBytes*50*8);*/
      /* This moves the raw bits to take into account the new compressed size */
      ec_enc_shrink(enc, nbCompressedBytes);
    }
 
    /* Bit allocation */
    ALLOC(fine_quant, nbEBands, int);
    ALLOC(pulses, nbEBands, int);
@@ -2033,27 +2131,35 @@ int celt_encode_with_ec(CELTEncoder * OP
 
    quant_fine_energy(mode, start, end, oldBandE, error, fine_quant, enc, C);
 
    /* Residual quantisation */
    ALLOC(collapse_masks, C*nbEBands, unsigned char);
    quant_all_bands(1, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
          bandE, pulses, shortBlocks, st->spread_decision,
          dual_stereo, st->intensity, tf_res, nbCompressedBytes*(8<<BITRES)-anti_collapse_rsv,
-         balance, enc, LM, codedBands, &st->rng, st->arch);
+         balance, enc, LM, codedBands, &st->rng, st->complexity, st->arch, st->disable_inv);
 
    if (anti_collapse_rsv > 0)
    {
       anti_collapse_on = st->consec_transient<2;
 #ifdef FUZZING
       anti_collapse_on = rand()&0x1;
 #endif
       ec_enc_bits(enc, anti_collapse_on, 1);
    }
    quant_energy_finalise(mode, start, end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C);
+   OPUS_CLEAR(energyError, nbEBands*CC);
+   c=0;
+   do {
+      for (i=start;i<end;i++)
+      {
+         energyError[i+c*nbEBands] = MAX16(-QCONST16(0.5f, 15), MIN16(QCONST16(0.5f, 15), error[i+c*nbEBands]));
+      }
+   } while (++c < C);
 
    if (silence)
    {
       for (i=0;i<C*nbEBands;i++)
          oldBandE[i] = -QCONST16(28.f,DB_SHIFT);
    }
 
 #ifdef RESYNTH
@@ -2316,20 +2422,34 @@ int opus_custom_encoder_ctl(CELTEncoder 
       }
       break;
       case OPUS_GET_LSB_DEPTH_REQUEST:
       {
           opus_int32 *value = va_arg(ap, opus_int32*);
           *value=st->lsb_depth;
       }
       break;
-      case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
+      case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
       {
           opus_int32 value = va_arg(ap, opus_int32);
-          st->variable_duration = value;
+          if(value<0 || value>1)
+          {
+             goto bad_arg;
+          }
+          st->disable_inv = value;
+      }
+      break;
+      case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+      {
+          opus_int32 *value = va_arg(ap, opus_int32*);
+          if (!value)
+          {
+             goto bad_arg;
+          }
+          *value = st->disable_inv;
       }
       break;
       case OPUS_RESET_STATE:
       {
          int i;
          opus_val16 *oldBandE, *oldLogE, *oldLogE2;
          oldBandE = (opus_val16*)(st->in_mem+st->channels*(st->mode->overlap+COMBFILTER_MAXPERIOD));
          oldLogE = oldBandE + st->channels*st->mode->nbEBands;
@@ -2363,16 +2483,23 @@ int opus_custom_encoder_ctl(CELTEncoder 
       break;
       case CELT_SET_ANALYSIS_REQUEST:
       {
          AnalysisInfo *info = va_arg(ap, AnalysisInfo *);
          if (info)
             OPUS_COPY(&st->analysis, info, 1);
       }
       break;
+      case CELT_SET_SILK_INFO_REQUEST:
+      {
+         SILKInfo *info = va_arg(ap, SILKInfo *);
+         if (info)
+            OPUS_COPY(&st->silk_info, info, 1);
+      }
+      break;
       case CELT_GET_MODE_REQUEST:
       {
          const CELTMode ** value = va_arg(ap, const CELTMode**);
          if (value==0)
             goto bad_arg;
          *value=st->mode;
       }
       break;
--- a/media/libopus/celt/celt_lpc.c
+++ b/media/libopus/celt/celt_lpc.c
@@ -84,68 +84,50 @@ int          p
 #ifdef FIXED_POINT
    for (i=0;i<p;i++)
       _lpc[i] = ROUND16(lpc[i],16);
 #endif
 }
 
 
 void celt_fir_c(
-         const opus_val16 *_x,
+         const opus_val16 *x,
          const opus_val16 *num,
-         opus_val16 *_y,
+         opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch)
 {
    int i,j;
    VARDECL(opus_val16, rnum);
-   VARDECL(opus_val16, x);
    SAVE_STACK;
 
    ALLOC(rnum, ord, opus_val16);
-   ALLOC(x, N+ord, opus_val16);
    for(i=0;i<ord;i++)
       rnum[i] = num[ord-i-1];
-   for(i=0;i<ord;i++)
-      x[i] = mem[ord-i-1];
-   for (i=0;i<N;i++)
-      x[i+ord]=_x[i];
-   for(i=0;i<ord;i++)
-      mem[i] = _x[N-i-1];
-#ifdef SMALL_FOOTPRINT
-   (void)arch;
-   for (i=0;i<N;i++)
-   {
-      opus_val32 sum = SHL32(EXTEND32(_x[i]), SIG_SHIFT);
-      for (j=0;j<ord;j++)
-      {
-         sum = MAC16_16(sum,rnum[j],x[i+j]);
-      }
-      _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
-   }
-#else
    for (i=0;i<N-3;i+=4)
    {
-      opus_val32 sum[4]={0,0,0,0};
-      xcorr_kernel(rnum, x+i, sum, ord, arch);
-      _y[i  ] = SATURATE16(ADD32(EXTEND32(_x[i  ]), PSHR32(sum[0], SIG_SHIFT)));
-      _y[i+1] = SATURATE16(ADD32(EXTEND32(_x[i+1]), PSHR32(sum[1], SIG_SHIFT)));
-      _y[i+2] = SATURATE16(ADD32(EXTEND32(_x[i+2]), PSHR32(sum[2], SIG_SHIFT)));
-      _y[i+3] = SATURATE16(ADD32(EXTEND32(_x[i+3]), PSHR32(sum[3], SIG_SHIFT)));
+      opus_val32 sum[4];
+      sum[0] = SHL32(EXTEND32(x[i  ]), SIG_SHIFT);
+      sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT),
+      sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
+      sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
+      xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
+      y[i  ] = ROUND16(sum[0], SIG_SHIFT);
+      y[i+1] = ROUND16(sum[1], SIG_SHIFT);
+      y[i+2] = ROUND16(sum[2], SIG_SHIFT);
+      y[i+3] = ROUND16(sum[3], SIG_SHIFT);
    }
    for (;i<N;i++)
    {
-      opus_val32 sum = 0;
+      opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
       for (j=0;j<ord;j++)
-         sum = MAC16_16(sum,rnum[j],x[i+j]);
-      _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT)));
+         sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
+      y[i] = ROUND16(sum, SIG_SHIFT);
    }
-#endif
    RESTORE_STACK;
 }
 
 void celt_iir(const opus_val32 *_x,
          const opus_val16 *den,
          opus_val32 *_y,
          int N,
          int ord,
@@ -161,17 +143,17 @@ void celt_iir(const opus_val32 *_x,
       for (j=0;j<ord;j++)
       {
          sum -= MULT16_16(den[j],mem[j]);
       }
       for (j=ord-1;j>=1;j--)
       {
          mem[j]=mem[j-1];
       }
-      mem[0] = ROUND16(sum,SIG_SHIFT);
+      mem[0] = SROUND16(sum, SIG_SHIFT);
       _y[i] = sum;
    }
 #else
    int i,j;
    VARDECL(opus_val16, rden);
    VARDECL(opus_val16, y);
    SAVE_STACK;
 
@@ -190,38 +172,38 @@ void celt_iir(const opus_val32 *_x,
       opus_val32 sum[4];
       sum[0]=_x[i];
       sum[1]=_x[i+1];
       sum[2]=_x[i+2];
       sum[3]=_x[i+3];
       xcorr_kernel(rden, y+i, sum, ord, arch);
 
       /* Patch up the result to compensate for the fact that this is an IIR */
-      y[i+ord  ] = -ROUND16(sum[0],SIG_SHIFT);
+      y[i+ord  ] = -SROUND16(sum[0],SIG_SHIFT);
       _y[i  ] = sum[0];
       sum[1] = MAC16_16(sum[1], y[i+ord  ], den[0]);
-      y[i+ord+1] = -ROUND16(sum[1],SIG_SHIFT);
+      y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
       _y[i+1] = sum[1];
       sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
       sum[2] = MAC16_16(sum[2], y[i+ord  ], den[1]);
-      y[i+ord+2] = -ROUND16(sum[2],SIG_SHIFT);
+      y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
       _y[i+2] = sum[2];
 
       sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
       sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
       sum[3] = MAC16_16(sum[3], y[i+ord  ], den[2]);
-      y[i+ord+3] = -ROUND16(sum[3],SIG_SHIFT);
+      y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
       _y[i+3] = sum[3];
    }
    for (;i<N;i++)
    {
       opus_val32 sum = _x[i];
       for (j=0;j<ord;j++)
          sum -= MULT16_16(rden[j],y[i+j]);
-      y[i+ord] = ROUND16(sum,SIG_SHIFT);
+      y[i+ord] = SROUND16(sum,SIG_SHIFT);
       _y[i] = sum;
    }
    for(i=0;i<ord;i++)
       mem[i] = _y[N-i-1];
    RESTORE_STACK;
 #endif
 }
 
--- a/media/libopus/celt/celt_lpc.h
+++ b/media/libopus/celt/celt_lpc.h
@@ -40,22 +40,21 @@
 void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p);
 
 void celt_fir_c(
          const opus_val16 *x,
          const opus_val16 *num,
          opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch);
 
 #if !defined(OVERRIDE_CELT_FIR)
-#define celt_fir(x, num, y, N, ord, mem, arch) \
-    (celt_fir_c(x, num, y, N, ord, mem, arch))
+#define celt_fir(x, num, y, N, ord, arch) \
+    (celt_fir_c(x, num, y, N, ord, arch))
 #endif
 
 void celt_iir(const opus_val32 *x,
          const opus_val16 *den,
          opus_val32 *y,
          int N,
          int ord,
          opus_val16 *mem,
--- a/media/libopus/celt/fixed_debug.h
+++ b/media/libopus/celt/fixed_debug.h
@@ -54,16 +54,24 @@ extern opus_int64 celt_mips;
 
 #define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
 #define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
 #define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
 
 #define SHR(a,b) SHR32(a,b)
 #define PSHR(a,b) PSHR32(a,b)
 
+/** Add two 32-bit values, ignore any overflows */
+#define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
+/** Subtract two 32-bit values, ignore any overflows */
+#define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
+/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
+/** Negate 32-bit value, ignore any overflows */
+#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
+
 static OPUS_INLINE short NEG16(int x)
 {
    int res;
    if (!VERIFY_SHORT(x))
    {
       fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
 #ifdef FIXED_DEBUG_ASSERT
       celt_assert(0);
@@ -222,22 +230,21 @@ static OPUS_INLINE int SHL32_(opus_int64
    celt_mips+=2;
    return res;
 }
 
 #define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((opus_val32)(1)<<((shift))>>1))),shift))
 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
 
 #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
+#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767)));
+
 #define HALF16(x)  (SHR16(x,1))
 #define HALF32(x)  (SHR32(x,1))
 
-//#define SHR(a,shift) ((a) >> (shift))
-//#define SHL(a,shift) ((a) << (shift))
-
 #define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
 static OPUS_INLINE short ADD16_(int a, int b, char *file, int line)
 {
    int res;
    if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
    {
       fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
 #ifdef FIXED_DEBUG_ASSERT
--- a/media/libopus/celt/fixed_generic.h
+++ b/media/libopus/celt/fixed_generic.h
@@ -99,29 +99,40 @@
 #define SHL(a,shift) SHL32(a,shift)
 #define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
 #define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
 
 #define SATURATE16(x) (EXTRACT16((x)>32767 ? 32767 : (x)<-32768 ? -32768 : (x)))
 
 /** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */
 #define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
+/** Shift by a and round-to-neareast 32-bit value. Result is a saturated 16-bit value */
+#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767));
+
 /** Divide by two */
 #define HALF16(x)  (SHR16(x,1))
 #define HALF32(x)  (SHR32(x,1))
 
 /** Add two 16-bit values */
 #define ADD16(a,b) ((opus_val16)((opus_val16)(a)+(opus_val16)(b)))
 /** Subtract two 16-bit values */
 #define SUB16(a,b) ((opus_val16)(a)-(opus_val16)(b))
 /** Add two 32-bit values */
 #define ADD32(a,b) ((opus_val32)(a)+(opus_val32)(b))
 /** Subtract two 32-bit values */
 #define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b))
 
+/** Add two 32-bit values, ignore any overflows */
+#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
+/** Subtract two 32-bit values, ignore any overflows */
+#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
+/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
+/** Negate 32-bit value, ignore any overflows */
+#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a)))
+
 /** 16x16 multiplication where the result fits in 16 bits */
 #define MULT16_16_16(a,b)     ((((opus_val16)(a))*((opus_val16)(b))))
 
 /* (opus_val32)(opus_val16) gives TI compiler a hint that it's 16x16->32 multiply */
 /** 16x16 multiplication where the result fits in 32 bits */
 #define MULT16_16(a,b)     (((opus_val32)(opus_val16)(a))*((opus_val32)(opus_val16)(b)))
 
 /** 16x16 multiply-add where the result fits in 32 bits */
--- a/media/libopus/celt/float_cast.h
+++ b/media/libopus/celt/float_cast.h
@@ -56,17 +56,23 @@
 **              long int lrint  (double x) ;
 */
 
 /*      The presence of the required functions are detected during the configure
 **      process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
 **      the config.h file.
 */
 
-#if (HAVE_LRINTF)
+/* With GCC, when SSE is available, the fastest conversion is cvtss2si. */
+#if defined(__GNUC__) && defined(__SSE__)
+
+#include <xmmintrin.h>
+static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));}
+
+#elif defined(HAVE_LRINTF)
 
 /*      These defines enable functionality introduced with the 1999 ISO C
 **      standard. They must be defined before the inclusion of math.h to
 **      engage them. If optimisation is enabled, these functions will be
 **      inlined. With optimisation switched off, you have to link in the
 **      maths library using -lm.
 */
 
--- a/media/libopus/celt/kiss_fft.c
+++ b/media/libopus/celt/kiss_fft.c
@@ -77,28 +77,28 @@ static void kf_bfly2(
       for (i=0;i<N;i++)
       {
          kiss_fft_cpx t;
          Fout2 = Fout + 4;
          t = Fout2[0];
          C_SUB( Fout2[0] ,  Fout[0] , t );
          C_ADDTO( Fout[0] ,  t );
 
-         t.r = S_MUL(Fout2[1].r+Fout2[1].i, tw);
-         t.i = S_MUL(Fout2[1].i-Fout2[1].r, tw);
+         t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
+         t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
          C_SUB( Fout2[1] ,  Fout[1] , t );
          C_ADDTO( Fout[1] ,  t );
 
          t.r = Fout2[2].i;
          t.i = -Fout2[2].r;
          C_SUB( Fout2[2] ,  Fout[2] , t );
          C_ADDTO( Fout[2] ,  t );
 
-         t.r = S_MUL(Fout2[3].i-Fout2[3].r, tw);
-         t.i = S_MUL(-Fout2[3].i-Fout2[3].r, tw);
+         t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
+         t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw);
          C_SUB( Fout2[3] ,  Fout[3] , t );
          C_ADDTO( Fout[3] ,  t );
          Fout += 8;
       }
    }
 }
 
 static void kf_bfly4(
@@ -121,20 +121,20 @@ static void kf_bfly4(
 
          C_SUB( scratch0 , *Fout, Fout[2] );
          C_ADDTO(*Fout, Fout[2]);
          C_ADD( scratch1 , Fout[1] , Fout[3] );
          C_SUB( Fout[2], *Fout, scratch1 );
          C_ADDTO( *Fout , scratch1 );
          C_SUB( scratch1 , Fout[1] , Fout[3] );
 
-         Fout[1].r = scratch0.r + scratch1.i;
-         Fout[1].i = scratch0.i - scratch1.r;
-         Fout[3].r = scratch0.r - scratch1.i;
-         Fout[3].i = scratch0.i + scratch1.r;
+         Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
+         Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
+         Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
+         Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
          Fout+=4;
       }
    } else {
       int j;
       kiss_fft_cpx scratch[6];
       const kiss_twiddle_cpx *tw1,*tw2,*tw3;
       const int m2=2*m;
       const int m3=3*m;
@@ -155,20 +155,20 @@ static void kf_bfly4(
             C_ADD( scratch[3] , scratch[0] , scratch[2] );
             C_SUB( scratch[4] , scratch[0] , scratch[2] );
             C_SUB( Fout[m2], *Fout, scratch[3] );
             tw1 += fstride;
             tw2 += fstride*2;
             tw3 += fstride*3;
             C_ADDTO( *Fout , scratch[3] );
 
-            Fout[m].r = scratch[5].r + scratch[4].i;
-            Fout[m].i = scratch[5].i - scratch[4].r;
-            Fout[m3].r = scratch[5].r - scratch[4].i;
-            Fout[m3].i = scratch[5].i + scratch[4].r;
+            Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
+            Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
+            Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
+            Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
             ++Fout;
          }
       }
    }
 }
 
 
 #ifndef RADIX_TWO_ONLY
@@ -207,28 +207,28 @@ static void kf_bfly3(
          C_MUL(scratch[1],Fout[m] , *tw1);
          C_MUL(scratch[2],Fout[m2] , *tw2);
 
          C_ADD(scratch[3],scratch[1],scratch[2]);
          C_SUB(scratch[0],scratch[1],scratch[2]);
          tw1 += fstride;
          tw2 += fstride*2;
 
-         Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
-         Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
+         Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r));
+         Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i));
 
          C_MULBYSCALAR( scratch[0] , epi3.i );
 
          C_ADDTO(*Fout,scratch[3]);
 
-         Fout[m2].r = Fout[m].r + scratch[0].i;
-         Fout[m2].i = Fout[m].i - scratch[0].r;
+         Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i);
+         Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r);
 
-         Fout[m].r -= scratch[0].i;
-         Fout[m].i += scratch[0].r;
+         Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i);
+         Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r);
 
          ++Fout;
       } while(--k);
    }
 }
 
 
 #ifndef OVERRIDE_kf_bfly5
@@ -277,32 +277,32 @@ static void kf_bfly5(
          C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
          C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
 
          C_ADD( scratch[7],scratch[1],scratch[4]);
          C_SUB( scratch[10],scratch[1],scratch[4]);
          C_ADD( scratch[8],scratch[2],scratch[3]);
          C_SUB( scratch[9],scratch[2],scratch[3]);
 
-         Fout0->r += scratch[7].r + scratch[8].r;
-         Fout0->i += scratch[7].i + scratch[8].i;
+         Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r));
+         Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i));
 
-         scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
-         scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
+         scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r)));
+         scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r)));
 
-         scratch[6].r =  S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
-         scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
+         scratch[6].r =  ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i));
+         scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i)));
 
          C_SUB(*Fout1,scratch[5],scratch[6]);
          C_ADD(*Fout4,scratch[5],scratch[6]);
 
-         scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
-         scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
-         scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
-         scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
+         scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r)));
+         scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r)));
+         scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i));
+         scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i));
 
          C_ADD(*Fout2,scratch[11],scratch[12]);
          C_SUB(*Fout3,scratch[11],scratch[12]);
 
          ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
       }
    }
 }
--- a/media/libopus/celt/mathops.h
+++ b/media/libopus/celt/mathops.h
@@ -33,21 +33,54 @@
 
 #ifndef MATHOPS_H
 #define MATHOPS_H
 
 #include "arch.h"
 #include "entcode.h"
 #include "os_support.h"
 
+#define PI 3.141592653f
+
 /* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
 #define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15)
 
 unsigned isqrt32(opus_uint32 _val);
 
+/* CELT doesn't need it for fixed-point, by analysis.c does. */
+#if !defined(FIXED_POINT) || defined(ANALYSIS_C)
+#define cA 0.43157974f
+#define cB 0.67848403f
+#define cC 0.08595542f
+#define cE ((float)PI/2)
+static OPUS_INLINE float fast_atan2f(float y, float x) {
+   float x2, y2;
+   x2 = x*x;
+   y2 = y*y;
+   /* For very small values, we don't care about the answer, so
+      we can just return 0. */
+   if (x2 + y2 < 1e-18f)
+   {
+      return 0;
+   }
+   if(x2<y2){
+      float den = (y2 + cB*x2) * (y2 + cC*x2);
+      return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
+   }else{
+      float den = (x2 + cB*y2) * (x2 + cC*y2);
+      return  x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
+   }
+}
+#undef cA
+#undef cB
+#undef cC
+#undef cD
+#endif
+
+
 #ifndef OVERRIDE_CELT_MAXABS16
 static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len)
 {
    int i;
    opus_val16 maxval = 0;
    opus_val16 minval = 0;
    for (i=0;i<len;i++)
    {
@@ -75,17 +108,16 @@ static OPUS_INLINE opus_val32 celt_maxab
 #else
 #define celt_maxabs32(x,len) celt_maxabs16(x,len)
 #endif
 #endif
 
 
 #ifndef FIXED_POINT
 
-#define PI 3.141592653f
 #define celt_sqrt(x) ((float)sqrt(x))
 #define celt_rsqrt(x) (1.f/celt_sqrt(x))
 #define celt_rsqrt_norm(x) (celt_rsqrt(x))
 #define celt_cos_norm(x) ((float)cos((.5f*PI)*(x)))
 #define celt_rcp(x) (1.f/(x))
 #define celt_div(a,b) ((a)/(b))
 #define frac_div32(a,b) ((float)(a)/(b))
 
--- a/media/libopus/celt/mdct.c
+++ b/media/libopus/celt/mdct.c
@@ -265,18 +265,18 @@ void clt_mdct_backward_c(const mdct_look
       kiss_fft_scalar * OPUS_RESTRICT yp = out+(overlap>>1);
       const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0];
       const opus_int16 * OPUS_RESTRICT bitrev = l->kfft[shift]->bitrev;
       for(i=0;i<N4;i++)
       {
          int rev;
          kiss_fft_scalar yr, yi;
          rev = *bitrev++;
-         yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]);
-         yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]);
+         yr = ADD32_ovflw(S_MUL(*xp2, t[i]), S_MUL(*xp1, t[N4+i]));
+         yi = SUB32_ovflw(S_MUL(*xp1, t[i]), S_MUL(*xp2, t[N4+i]));
          /* We swap real and imag because we use an FFT instead of an IFFT. */
          yp[2*rev+1] = yr;
          yp[2*rev] = yi;
          /* Storing the pre-rotation directly in the bitrev order. */
          xp1+=2*stride;
          xp2-=2*stride;
       }
    }
@@ -296,29 +296,29 @@ void clt_mdct_backward_c(const mdct_look
          kiss_fft_scalar re, im, yr, yi;
          kiss_twiddle_scalar t0, t1;
          /* We swap real and imag because we're using an FFT instead of an IFFT. */
          re = yp0[1];
          im = yp0[0];
          t0 = t[i];
          t1 = t[N4+i];
          /* We'd scale up by 2 here, but instead it's done when mixing the windows */
-         yr = S_MUL(re,t0) + S_MUL(im,t1);
-         yi = S_MUL(re,t1) - S_MUL(im,t0);
+         yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
+         yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
          /* We swap real and imag because we're using an FFT instead of an IFFT. */
          re = yp1[1];
          im = yp1[0];
          yp0[0] = yr;
          yp1[1] = yi;
 
          t0 = t[(N4-i-1)];
          t1 = t[(N2-i-1)];
          /* We'd scale up by 2 here, but instead it's done when mixing the windows */
-         yr = S_MUL(re,t0) + S_MUL(im,t1);
-         yi = S_MUL(re,t1) - S_MUL(im,t0);
+         yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
+         yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
          yp1[0] = yr;
          yp0[1] = yi;
          yp0 += 2;
          yp1 -= 2;
       }
    }
 
    /* Mirror on both sides for TDAC */
@@ -328,16 +328,16 @@ void clt_mdct_backward_c(const mdct_look
       const opus_val16 * OPUS_RESTRICT wp1 = window;
       const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
 
       for(i = 0; i < overlap/2; i++)
       {
          kiss_fft_scalar x1, x2;
          x1 = *xp1;
          x2 = *yp1;
-         *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1);
-         *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1);
+         *yp1++ = SUB32_ovflw(MULT16_32_Q15(*wp2, x2), MULT16_32_Q15(*wp1, x1));
+         *xp1-- = ADD32_ovflw(MULT16_32_Q15(*wp1, x2), MULT16_32_Q15(*wp2, x1));
          wp1++;
          wp2--;
       }
    }
 }
 #endif /* OVERRIDE_clt_mdct_backward */
--- a/media/libopus/celt/mips/vq_mipsr1.h
+++ b/media/libopus/celt/mips/vq_mipsr1.h
@@ -31,19 +31,16 @@
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "mathops.h"
 #include "arch.h"
 
-static unsigned extract_collapse_mask(int *iy, int N, int B);
-static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, int N, opus_val32 Ryy, opus_val16 gain);
-static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
 static void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch);
 
 #define OVERRIDE_vq_exp_rotation1
 static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
 {
    int i;
    opus_val16 ms;
    celt_norm *Xptr;
--- a/media/libopus/celt/modes.c
+++ b/media/libopus/celt/modes.c
@@ -422,17 +422,17 @@ void opus_custom_mode_destroy(CELTMode *
         if (mode == static_mode_list[i])
         {
            return;
         }
      }
    }
 #endif /* CUSTOM_MODES_ONLY */
    opus_free((opus_int16*)mode->eBands);
-   opus_free((opus_int16*)mode->allocVectors);
+   opus_free((unsigned char*)mode->allocVectors);
 
    opus_free((opus_val16*)mode->window);
    opus_free((opus_int16*)mode->logN);
 
    opus_free((opus_int16*)mode->cache.index);
    opus_free((unsigned char*)mode->cache.bits);
    opus_free((unsigned char*)mode->cache.caps);
    clt_mdct_clear(&mode->mdct, arch);
--- a/media/libopus/celt/pitch.c
+++ b/media/libopus/celt/pitch.c
@@ -215,23 +215,18 @@ void pitch_downsample(celt_sig * OPUS_RE
 }
 
 /* Pure C implementation. */
 #ifdef FIXED_POINT
 opus_val32
 #else
 void
 #endif
-#if defined(OVERRIDE_PITCH_XCORR)
 celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
-      opus_val32 *xcorr, int len, int max_pitch)
-#else
-celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
       opus_val32 *xcorr, int len, int max_pitch, int arch)
-#endif
 {
 
 #if 0 /* This is a simple version of the pitch correlation that should work
          well on DSPs like Blackfin and TI C5x/C6x */
    int i, j;
 #ifdef FIXED_POINT
    opus_val32 maxcorr=1;
 #endif
@@ -260,41 +255,33 @@ celt_pitch_xcorr(const opus_val16 *_x, c
 #ifdef FIXED_POINT
    opus_val32 maxcorr=1;
 #endif
    celt_assert(max_pitch>0);
    celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
    for (i=0;i<max_pitch-3;i+=4)
    {
       opus_val32 sum[4]={0,0,0,0};
-#if defined(OVERRIDE_PITCH_XCORR)
-      xcorr_kernel_c(_x, _y+i, sum, len);
-#else
       xcorr_kernel(_x, _y+i, sum, len, arch);
-#endif
       xcorr[i]=sum[0];
       xcorr[i+1]=sum[1];
       xcorr[i+2]=sum[2];
       xcorr[i+3]=sum[3];
 #ifdef FIXED_POINT
       sum[0] = MAX32(sum[0], sum[1]);
       sum[2] = MAX32(sum[2], sum[3]);
       sum[0] = MAX32(sum[0], sum[2]);
       maxcorr = MAX32(maxcorr, sum[0]);
 #endif
    }
    /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
    for (;i<max_pitch;i++)
    {
       opus_val32 sum;
-#if defined(OVERRIDE_PITCH_XCORR)
-      sum = celt_inner_prod_c(_x, _y+i, len);
-#else
       sum = celt_inner_prod(_x, _y+i, len, arch);
-#endif
       xcorr[i] = sum;
 #ifdef FIXED_POINT
       maxcorr = MAX32(maxcorr, sum);
 #endif
    }
 #ifdef FIXED_POINT
    return maxcorr;
 #endif
@@ -373,17 +360,17 @@ void pitch_search(const opus_val16 * OPU
       xcorr[i] = 0;
       if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
          continue;
 #ifdef FIXED_POINT
       sum = 0;
       for (j=0;j<len>>1;j++)
          sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
 #else
-      sum = celt_inner_prod_c(x_lp, y+i, len>>1);
+      sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
 #endif
       xcorr[i] = MAX32(-1, sum);
 #ifdef FIXED_POINT
       maxcorr = MAX32(maxcorr, sum);
 #endif
    }
    find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
 #ifdef FIXED_POINT
@@ -419,17 +406,17 @@ static opus_val16 compute_pitch_gain(opu
    int sx, sy, shift;
    opus_val32 g;
    opus_val16 den;
    if (xy == 0 || xx == 0 || yy == 0)
       return 0;
    sx = celt_ilog2(xx)-14;
    sy = celt_ilog2(yy)-14;
    shift = sx + sy;
-   x2y2 = MULT16_16_Q14(VSHR32(xx, sx), VSHR32(yy, sy));
+   x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
    if (shift & 1) {
       if (x2y2 < 32768)
       {
          x2y2 <<= 1;
          shift--;
       } else {
          x2y2 >>= 1;
          shift++;
--- a/media/libopus/celt/pitch.h
+++ b/media/libopus/celt/pitch.h
@@ -41,18 +41,17 @@
   || ((defined(OPUS_X86_MAY_HAVE_SSE4_1) || defined(OPUS_X86_MAY_HAVE_SSE2)) && defined(FIXED_POINT))
 #include "x86/pitch_sse.h"
 #endif
 
 #if defined(MIPSr1_ASM)
 #include "mips/pitch_mipsr1.h"
 #endif
 
-#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
-  || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
 # include "arm/pitch_arm.h"
 #endif
 
 void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
       int len, int C, int arch);
 
 void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
                   int len, int max_pitch, int *pitch, int arch);
@@ -179,22 +178,15 @@ void comb_filter_const_c(opus_val32 *y, 
 
 
 #ifdef FIXED_POINT
 opus_val32
 #else
 void
 #endif
 celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
-      opus_val32 *xcorr, int len, int max_pitch);
-
-#if !defined(OVERRIDE_PITCH_XCORR)
-#ifdef FIXED_POINT
-opus_val32
-#else
-void
-#endif
-celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
       opus_val32 *xcorr, int len, int max_pitch, int arch);
 
+#ifndef OVERRIDE_PITCH_XCORR
+# define celt_pitch_xcorr celt_pitch_xcorr_c
 #endif
 
 #endif
--- a/media/libopus/celt/quant_bands.c
+++ b/media/libopus/celt/quant_bands.c
@@ -413,16 +413,17 @@ void quant_energy_finalise(const CELTMod
             q2 = error[i+c*m->nbEBands]<0 ? 0 : 1;
             ec_enc_bits(enc, q2, 1);
 #ifdef FIXED_POINT
             offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1);
 #else
             offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
 #endif
             oldEBands[i+c*m->nbEBands] += offset;
+            error[i+c*m->nbEBands] -= offset;
             bits_left--;
          } while (++c < C);
       }
    }
 }
 
 void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM)
 {
@@ -542,15 +543,21 @@ void unquant_energy_finalise(const CELTM
 
 void amp2Log2(const CELTMode *m, int effEnd, int end,
       celt_ener *bandE, opus_val16 *bandLogE, int C)
 {
    int c, i;
    c=0;
    do {
       for (i=0;i<effEnd;i++)
+      {
          bandLogE[i+c*m->nbEBands] =
-               celt_log2(SHL32(bandE[i+c*m->nbEBands],2))
+               celt_log2(bandE[i+c*m->nbEBands])
                - SHL16((opus_val16)eMeans[i],6);
+#ifdef FIXED_POINT
+         /* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */
+         bandLogE[i+c*m->nbEBands] += QCONST16(2.f, DB_SHIFT);
+#endif
+      }
       for (i=effEnd;i<end;i++)
          bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT);
    } while (++c < C);
 }
--- a/media/libopus/celt/rate.c
+++ b/media/libopus/celt/rate.c
@@ -343,22 +343,27 @@ static OPUS_INLINE int interp_bits2pulse
         This ensures that we have enough bits to code the skip flag.*/
       if (band_bits >= IMAX(thresh[j], alloc_floor+(1<<BITRES)))
       {
          if (encode)
          {
             /*This if() block is the only part of the allocation function that
                is not a mandatory part of the bitstream: any bands we choose to
                skip here must be explicitly signaled.*/
-            /*Choose a threshold with some hysteresis to keep bands from
-               fluctuating in and out.*/
+            int depth_threshold;
+            /*We choose a threshold with some hysteresis to keep bands from
+               fluctuating in and out, but we try not to fold below a certain point. */
+            if (codedBands > 17)
+               depth_threshold = j<prev ? 7 : 9;
+            else
+               depth_threshold = 0;
 #ifdef FUZZING
             if ((rand()&0x1) == 0)
 #else
-            if (codedBands<=start+2 || (band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
+            if (codedBands<=start+2 || (band_bits > (depth_threshold*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
 #endif
             {
                ec_enc_bit_logp(ec, 1, 1);
                break;
             }
             ec_enc_bit_logp(ec, 0, 1);
          } else if (ec_dec_bit_logp(ec, 1)) {
             break;
--- a/media/libopus/celt/static_modes_fixed_arm_ne10.h
+++ b/media/libopus/celt/static_modes_fixed_arm_ne10.h
@@ -1,12 +1,12 @@
 /* The contents of this file was automatically generated by
  * dump_mode_arm_ne10.c with arguments: 48000 960
  * It contains static definitions for some pre-defined modes. */
-#include <NE10_init.h>
+#include <NE10_types.h>
 
 #ifndef NE10_FFT_PARAMS48000_960
 #define NE10_FFT_PARAMS48000_960
 static const ne10_int32_t ne10_factors_480[64] = {
 4, 40, 4, 30, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
--- a/media/libopus/celt/static_modes_float_arm_ne10.h
+++ b/media/libopus/celt/static_modes_float_arm_ne10.h
@@ -1,12 +1,12 @@
 /* The contents of this file was automatically generated by
  * dump_mode_arm_ne10.c with arguments: 48000 960
  * It contains static definitions for some pre-defined modes. */
-#include <NE10_init.h>
+#include <NE10_types.h>
 
 #ifndef NE10_FFT_PARAMS48000_960
 #define NE10_FFT_PARAMS48000_960
 static const ne10_int32_t ne10_factors_480[64] = {
 4, 40, 4, 30, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
--- a/media/libopus/celt/vq.c
+++ b/media/libopus/celt/vq.c
@@ -62,17 +62,17 @@ static void exp_rotation1(celt_norm *X, 
       x1 = Xptr[0];
       x2 = Xptr[stride];
       Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2),  s, x1), 15));
       *Xptr--      = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
    }
 }
 #endif /* OVERRIDE_vq_exp_rotation1 */
 
-static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
+void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
 {
    static const int SPREAD_FACTOR[3]={15,10,5};
    int i;
    opus_val16 c, s;
    opus_val16 gain, theta;
    int stride2=0;
    int factor;
 
@@ -153,52 +153,37 @@ static unsigned extract_collapse_mask(in
       j=0; do {
          tmp |= iy[i*N0+j];
       } while (++j<N0);
       collapse_mask |= (tmp!=0)<<i;
    } while (++i<B);
    return collapse_mask;
 }
 
-unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
-#ifdef RESYNTH
-   , opus_val16 gain
-#endif
-   )
+opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
 {
    VARDECL(celt_norm, y);
-   VARDECL(int, iy);
-   VARDECL(opus_val16, signx);
+   VARDECL(int, signx);
    int i, j;
-   opus_val16 s;
    int pulsesLeft;
    opus_val32 sum;
    opus_val32 xy;
    opus_val16 yy;
-   unsigned collapse_mask;
    SAVE_STACK;
 
-   celt_assert2(K>0, "alg_quant() needs at least one pulse");
-   celt_assert2(N>1, "alg_quant() needs at least two dimensions");
-
+   (void)arch;
    ALLOC(y, N, celt_norm);
-   ALLOC(iy, N, int);
-   ALLOC(signx, N, opus_val16);
-
-   exp_rotation(X, N, 1, B, K, spread);
+   ALLOC(signx, N, int);
 
    /* Get rid of the sign */
    sum = 0;
    j=0; do {
-      if (X[j]>0)
-         signx[j]=1;
-      else {
-         signx[j]=-1;
-         X[j]=-X[j];
-      }
+      signx[j] = X[j]<0;
+      /* OPT: Make sure the compiler doesn't use a branch on ABS16(). */
+      X[j] = ABS16(X[j]);
       iy[j] = 0;
       y[j] = 0;
    } while (++j<N);
 
    xy = yy = 0;
 
    pulsesLeft = K;
 
@@ -220,109 +205,154 @@ unsigned alg_quant(celt_norm *X, int N, 
 #endif
       {
          X[0] = QCONST16(1.f,14);
          j=1; do
             X[j]=0;
          while (++j<N);
          sum = QCONST16(1.f,14);
       }
-      rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum)));
+#ifdef FIXED_POINT
+      rcp = EXTRACT16(MULT16_32_Q16(K, celt_rcp(sum)));
+#else
+      /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
+      rcp = EXTRACT16(MULT16_32_Q16(K+0.8f, celt_rcp(sum)));
+#endif
       j=0; do {
 #ifdef FIXED_POINT
          /* It's really important to round *towards zero* here */
          iy[j] = MULT16_16_Q15(X[j],rcp);
 #else
          iy[j] = (int)floor(rcp*X[j]);
 #endif
          y[j] = (celt_norm)iy[j];
          yy = MAC16_16(yy, y[j],y[j]);
          xy = MAC16_16(xy, X[j],y[j]);
          y[j] *= 2;
          pulsesLeft -= iy[j];
       }  while (++j<N);
    }
-   celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass");
+   celt_assert2(pulsesLeft>=0, "Allocated too many pulses in the quick pass");
 
    /* This should never happen, but just in case it does (e.g. on silence)
       we fill the first bin with pulses. */
 #ifdef FIXED_POINT_DEBUG
    celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass");
 #endif
    if (pulsesLeft > N+3)
    {
       opus_val16 tmp = (opus_val16)pulsesLeft;
       yy = MAC16_16(yy, tmp, tmp);
       yy = MAC16_16(yy, tmp, y[0]);
       iy[0] += pulsesLeft;
       pulsesLeft=0;
    }
 
-   s = 1;
    for (i=0;i<pulsesLeft;i++)
    {
+      opus_val16 Rxy, Ryy;
       int best_id;
-      opus_val32 best_num = -VERY_LARGE16;
-      opus_val16 best_den = 0;
+      opus_val32 best_num;
+      opus_val16 best_den;
 #ifdef FIXED_POINT
       int rshift;
 #endif
 #ifdef FIXED_POINT
       rshift = 1+celt_ilog2(K-pulsesLeft+i+1);
 #endif
       best_id = 0;
       /* The squared magnitude term gets added anyway, so we might as well
          add it outside the loop */
       yy = ADD16(yy, 1);
-      j=0;
+
+      /* Calculations for position 0 are out of the loop, in part to reduce
+         mispredicted branches (since the if condition is usually false)
+         in the loop. */
+      /* Temporary sums of the new pulse(s) */
+      Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[0])),rshift));
+      /* We're multiplying y[j] by two so we don't have to do it here */
+      Ryy = ADD16(yy, y[0]);
+
+      /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
+         Rxy is positive because the sign is pre-computed) */
+      Rxy = MULT16_16_Q15(Rxy,Rxy);
+      best_den = Ryy;
+      best_num = Rxy;
+      j=1;
       do {
-         opus_val16 Rxy, Ryy;
          /* Temporary sums of the new pulse(s) */
          Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
          /* We're multiplying y[j] by two so we don't have to do it here */
          Ryy = ADD16(yy, y[j]);
 
          /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
             Rxy is positive because the sign is pre-computed) */
          Rxy = MULT16_16_Q15(Rxy,Rxy);
          /* The idea is to check for num/den >= best_num/best_den, but that way
             we can do it without any division */
-         /* OPT: Make sure to use conditional moves here */
-         if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num))
+         /* OPT: It's not clear whether a cmov is faster than a branch here
+            since the condition is more often false than true and using
+            a cmov introduces data dependencies across iterations. The optimal
+            choice may be architecture-dependent. */
+         if (opus_unlikely(MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)))
          {
             best_den = Ryy;
             best_num = Rxy;
             best_id = j;
          }
       } while (++j<N);
 
       /* Updating the sums of the new pulse(s) */
       xy = ADD32(xy, EXTEND32(X[best_id]));
       /* We're multiplying y[j] by two so we don't have to do it here */
       yy = ADD16(yy, y[best_id]);
 
       /* Only now that we've made the final choice, update y/iy */
       /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
-      y[best_id] += 2*s;
+      y[best_id] += 2;
       iy[best_id]++;
    }
 
    /* Put the original sign back */
    j=0;
    do {
-      X[j] = MULT16_16(signx[j],X[j]);
-      if (signx[j] < 0)
-         iy[j] = -iy[j];
+      /*iy[j] = signx[j] ? -iy[j] : iy[j];*/
+      /* OPT: The is more likely to be compiled without a branch than the code above
+         but has the same performance otherwise. */
+      iy[j] = (iy[j]^-signx[j]) + signx[j];
    } while (++j<N);
+   RESTORE_STACK;
+   return yy;
+}
+
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
+      opus_val16 gain, int resynth, int arch)
+{
+   VARDECL(int, iy);
+   opus_val16 yy;
+   unsigned collapse_mask;
+   SAVE_STACK;
+
+   celt_assert2(K>0, "alg_quant() needs at least one pulse");
+   celt_assert2(N>1, "alg_quant() needs at least two dimensions");
+
+   /* Covers vectorization by up to 4. */
+   ALLOC(iy, N+3, int);
+
+   exp_rotation(X, N, 1, B, K, spread);
+
+   yy = op_pvq_search(X, iy, K, N, arch);
+
    encode_pulses(iy, N, K, enc);
 
-#ifdef RESYNTH
-   normalise_residual(iy, X, N, yy, gain);
-   exp_rotation(X, N, -1, B, K, spread);
-#endif
+   if (resynth)
+   {
+      normalise_residual(iy, X, N, yy, gain);
+      exp_rotation(X, N, -1, B, K, spread);
+   }
 
    collapse_mask = extract_collapse_mask(iy, N, B);
    RESTORE_STACK;
    return collapse_mask;
 }
 
 /** Decode pulse vector and combine the result with the pitch vector to produce
     the final normalised signal in the current band. */
@@ -396,13 +426,13 @@ int stereo_itheta(const celt_norm *X, co
       Eside += celt_inner_prod(Y, Y, N, arch);
    }
    mid = celt_sqrt(Emid);
    side = celt_sqrt(Eside);
 #ifdef FIXED_POINT
    /* 0.63662 = 2/pi */
    itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
 #else
-   itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid));
+   itheta = (int)floor(.5f+16384*0.63662f*fast_atan2f(side,mid));
 #endif
 
    return itheta;
 }
--- a/media/libopus/celt/vq.h
+++ b/media/libopus/celt/vq.h
@@ -32,36 +32,44 @@
 
 #ifndef VQ_H
 #define VQ_H
 
 #include "entenc.h"
 #include "entdec.h"
 #include "modes.h"
 
+#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT))
+#include "x86/vq_sse.h"
+#endif
+
 #if defined(MIPSr1_ASM)
 #include "mips/vq_mipsr1.h"
 #endif
 
+void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
+
+opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch);
+
+#if !defined(OVERRIDE_OP_PVQ_SEARCH)
+#define op_pvq_search(x, iy, K, N, arch) \
+    (op_pvq_search_c(x, iy, K, N, arch))
+#endif
 
 /** Algebraic pulse-vector quantiser. The signal x is replaced by the sum of
   * the pitch and a combination of pulses such that its norm is still equal
   * to 1. This is the function that will typically require the most CPU.
  * @param X Residual signal to quantise/encode (returns quantised version)
  * @param N Number of samples to encode
  * @param K Number of pulses to use
  * @param enc Entropy encoder state
  * @ret A mask indicating which blocks in the band received pulses
 */
-unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B,
-      ec_enc *enc
-#ifdef RESYNTH
-      , opus_val16 gain
-#endif
-      );
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
+      opus_val16 gain, int resynth, int arch);
 
 /** Algebraic pulse decoder
  * @param X Decoded normalised spectrum (returned)
  * @param N Number of samples to decode
  * @param K Number of pulses to use
  * @param dec Entropy decoder state
  * @ret A mask indicating which blocks in the band received pulses
  */
--- a/media/libopus/celt/x86/celt_lpc_sse.c
+++ b/media/libopus/celt/x86/celt_lpc_sse.c
@@ -35,98 +35,55 @@
 #include "celt_lpc.h"
 #include "stack_alloc.h"
 #include "mathops.h"
 #include "pitch.h"
 #include "x86cpu.h"
 
 #if defined(FIXED_POINT)
 
-void celt_fir_sse4_1(const opus_val16 *_x,
+void celt_fir_sse4_1(const opus_val16 *x,
          const opus_val16 *num,
-         opus_val16 *_y,
+         opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch)
 {
     int i,j;
     VARDECL(opus_val16, rnum);
-    VARDECL(opus_val16, x);
 
     __m128i vecNoA;
     opus_int32 noA ;
     SAVE_STACK;
 
    ALLOC(rnum, ord, opus_val16);
-   ALLOC(x, N+ord, opus_val16);
    for(i=0;i<ord;i++)
       rnum[i] = num[ord-i-1];
-   for(i=0;i<ord;i++)
-      x[i] = mem[ord-i-1];
-
-   for (i=0;i<N-7;i+=8)
-   {
-       x[i+ord  ]=_x[i  ];
-       x[i+ord+1]=_x[i+1];
-       x[i+ord+2]=_x[i+2];
-       x[i+ord+3]=_x[i+3];
-       x[i+ord+4]=_x[i+4];
-       x[i+ord+5]=_x[i+5];
-       x[i+ord+6]=_x[i+6];
-       x[i+ord+7]=_x[i+7];
-   }
-
-   for (;i<N-3;i+=4)
-   {
-       x[i+ord  ]=_x[i  ];
-       x[i+ord+1]=_x[i+1];
-       x[i+ord+2]=_x[i+2];
-       x[i+ord+3]=_x[i+3];
-   }
-
-   for (;i<N;i++)
-         x[i+ord]=_x[i];
-
-   for(i=0;i<ord;i++)
-      mem[i] = _x[N-i-1];
-#ifdef SMALL_FOOTPRINT
-   for (i=0;i<N;i++)
-   {
-      opus_val32 sum = SHL32(EXTEND32(_x[i]), SIG_SHIFT);
-      for (j=0;j<ord;j++)
-      {
-         sum = MAC16_16(sum,rnum[j],x[i+j]);
-      }
-      _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
-   }
-#else
    noA = EXTEND32(1) << SIG_SHIFT >> 1;
    vecNoA = _mm_set_epi32(noA, noA, noA, noA);
 
    for (i=0;i<N-3;i+=4)
    {
       opus_val32 sums[4] = {0};
       __m128i vecSum, vecX;
 
-      xcorr_kernel(rnum, x+i, sums, ord, arch);
+      xcorr_kernel(rnum, x+i-ord, sums, ord, arch);
 
       vecSum = _mm_loadu_si128((__m128i *)sums);
       vecSum = _mm_add_epi32(vecSum, vecNoA);
       vecSum = _mm_srai_epi32(vecSum, SIG_SHIFT);
-      vecX = OP_CVTEPI16_EPI32_M64(_x + i);
+      vecX = OP_CVTEPI16_EPI32_M64(x + i);
       vecSum = _mm_add_epi32(vecSum, vecX);
       vecSum = _mm_packs_epi32(vecSum, vecSum);
-      _mm_storel_epi64((__m128i *)(_y + i), vecSum);
+      _mm_storel_epi64((__m128i *)(y + i), vecSum);
    }
    for (;i<N;i++)
    {
       opus_val32 sum = 0;
       for (j=0;j<ord;j++)
-         sum = MAC16_16(sum, rnum[j], x[i + j]);
-      _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT)));
+         sum = MAC16_16(sum, rnum[j], x[i+j-ord]);
+      y[i] = SATURATE16(ADD32(EXTEND32(x[i]), PSHR32(sum, SIG_SHIFT)));
    }
 
-#endif
    RESTORE_STACK;
 }
 
 #endif
--- a/media/libopus/celt/x86/celt_lpc_sse.h
+++ b/media/libopus/celt/x86/celt_lpc_sse.h
@@ -36,33 +36,31 @@
 #define OVERRIDE_CELT_FIR
 
 void celt_fir_sse4_1(
          const opus_val16 *x,
          const opus_val16 *num,
          opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch);
 
 #if defined(OPUS_X86_PRESUME_SSE4_1)
-#define celt_fir(x, num, y, N, ord, mem, arch) \
-    ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, mem, arch))
+#define celt_fir(x, num, y, N, ord, arch) \
+    ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, arch))
 
 #else
 
 extern void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
          const opus_val16 *x,
          const opus_val16 *num,
          opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch);
 
-#  define celt_fir(x, num, y, N, ord, mem, arch) \
-    ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, mem, arch))
+#  define celt_fir(x, num, y, N, ord, arch) \
+    ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, arch))
 
 #endif
 #endif
 
 #endif
new file mode 100644
--- /dev/null
+++ b/media/libopus/celt/x86/vq_sse.h
@@ -0,0 +1,50 @@
+/* Copyright (c) 2016  Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   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 VQ_SSE_H
+#define VQ_SSE_H
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT)
+#define OVERRIDE_OP_PVQ_SEARCH
+
+opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch);
+
+#if defined(OPUS_X86_PRESUME_SSE2)
+#define op_pvq_search(x, iy, K, N, arch) \
+    (op_pvq_search_sse2(x, iy, K, N, arch))
+
+#else
+
+extern opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
+      celt_norm *_X, int *iy, int K, int N, int arch);
+
+#  define op_pvq_search(X, iy, K, N, arch) \
+    ((*OP_PVQ_SEARCH_IMPL[(arch) & OPUS_ARCHMASK])(X, iy, K, N, arch))
+
+#endif
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/libopus/celt/x86/vq_sse2.c
@@ -0,0 +1,217 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2007-2016 Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   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 <xmmintrin.h>
+#include <emmintrin.h>
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "vq.h"
+#include "x86cpu.h"
+
+
+#ifndef FIXED_POINT
+
+opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch)
+{
+   int i, j;
+   int pulsesLeft;
+   float xy, yy;
+   VARDECL(celt_norm, y);
+   VARDECL(celt_norm, X);
+   VARDECL(float, signy);
+   __m128 signmask;
+   __m128 sums;
+   __m128i fours;
+   SAVE_STACK;
+
+   (void)arch;
+   /* All bits set to zero, except for the sign bit. */
+   signmask = _mm_set_ps1(-0.f);
+   fours = _mm_set_epi32(4, 4, 4, 4);
+   ALLOC(y, N+3, celt_norm);
+   ALLOC(X, N+3, celt_norm);
+   ALLOC(signy, N+3, float);
+
+   OPUS_COPY(X, _X, N);
+   X[N] = X[N+1] = X[N+2] = 0;
+   sums = _mm_setzero_ps();
+   for (j=0;j<N;j+=4)
+   {
+      __m128 x4, s4;
+      x4 = _mm_loadu_ps(&X[j]);
+      s4 = _mm_cmplt_ps(x4, _mm_setzero_ps());
+      /* Get rid of the sign */
+      x4 = _mm_andnot_ps(signmask, x4);
+      sums = _mm_add_ps(sums, x4);
+      /* Clear y and iy in case we don't do the projection. */
+      _mm_storeu_ps(&y[j], _mm_setzero_ps());
+      _mm_storeu_si128((__m128i*)&iy[j], _mm_setzero_si128());
+      _mm_storeu_ps(&X[j], x4);
+      _mm_storeu_ps(&signy[j], s4);
+   }
+   sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(1, 0, 3, 2)));
+   sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(2, 3, 0, 1)));
+
+   xy = yy = 0;
+
+   pulsesLeft = K;
+
+   /* Do a pre-search by projecting on the pyramid */
+   if (K > (N>>1))
+   {
+      __m128i pulses_sum;
+      __m128 yy4, xy4;
+      __m128 rcp4;
+      opus_val32 sum = _mm_cvtss_f32(sums);
+      /* If X is too small, just replace it with a pulse at 0 */
+      /* Prevents infinities and NaNs from causing too many pulses
+         to be allocated. 64 is an approximation of infinity here. */
+      if (!(sum > EPSILON && sum < 64))
+      {
+         X[0] = QCONST16(1.f,14);
+         j=1; do
+            X[j]=0;
+         while (++j<N);
+         sums = _mm_set_ps1(1.f);
+      }
+      /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
+      rcp4 = _mm_mul_ps(_mm_set_ps1((float)(K+.8)), _mm_rcp_ps(sums));
+      xy4 = yy4 = _mm_setzero_ps();
+      pulses_sum = _mm_setzero_si128();
+      for (j=0;j<N;j+=4)
+      {
+         __m128 rx4, x4, y4;
+         __m128i iy4;
+         x4 = _mm_loadu_ps(&X[j]);
+         rx4 = _mm_mul_ps(x4, rcp4);
+         iy4 = _mm_cvttps_epi32(rx4);
+         pulses_sum = _mm_add_epi32(pulses_sum, iy4);
+         _mm_storeu_si128((__m128i*)&iy[j], iy4);
+         y4 = _mm_cvtepi32_ps(iy4);
+         xy4 = _mm_add_ps(xy4, _mm_mul_ps(x4, y4));
+         yy4 = _mm_add_ps(yy4, _mm_mul_ps(y4, y4));
+         /* double the y[] vector so we don't have to do it in the search loop. */
+         _mm_storeu_ps(&y[j], _mm_add_ps(y4, y4));
+      }
+      pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(1, 0, 3, 2)));
+      pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(2, 3, 0, 1)));
+      pulsesLeft -= _mm_cvtsi128_si32(pulses_sum);
+      xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(1, 0, 3, 2)));
+      xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(2, 3, 0, 1)));
+      xy = _mm_cvtss_f32(xy4);
+      yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(1, 0, 3, 2)));
+      yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(2, 3, 0, 1)));
+      yy = _mm_cvtss_f32(yy4);
+   }
+   X[N] = X[N+1] = X[N+2] = -100;
+   y[N] = y[N+1] = y[N+2] = 100;
+   celt_assert2(pulsesLeft>=0, "Allocated too many pulses in the quick pass");
+
+   /* This should never happen, but just in case it does (e.g. on silence)
+      we fill the first bin with pulses. */
+   if (pulsesLeft > N+3)
+   {
+      opus_val16 tmp = (opus_val16)pulsesLeft;
+      yy = MAC16_16(yy, tmp, tmp);
+      yy = MAC16_16(yy, tmp, y[0]);
+      iy[0] += pulsesLeft;
+      pulsesLeft=0;
+   }
+
+   for (i=0;i<pulsesLeft;i++)
+   {
+      int best_id;
+      __m128 xy4, yy4;
+      __m128 max, max2;
+      __m128i count;
+      __m128i pos;
+      /* The squared magnitude term gets added anyway, so we might as well
+         add it outside the loop */
+      yy = ADD16(yy, 1);
+      xy4 = _mm_load1_ps(&xy);
+      yy4 = _mm_load1_ps(&yy);
+      max = _mm_setzero_ps();
+      pos = _mm_setzero_si128();
+      count = _mm_set_epi32(3, 2, 1, 0);
+      for (j=0;j<N;j+=4)
+      {
+         __m128 x4, y4, r4;
+         x4 = _mm_loadu_ps(&X[j]);
+         y4 = _mm_loadu_ps(&y[j]);
+         x4 = _mm_add_ps(x4, xy4);
+         y4 = _mm_add_ps(y4, yy4);
+         y4 = _mm_rsqrt_ps(y4);
+         r4 = _mm_mul_ps(x4, y4);
+         /* Update the index of the max. */
+         pos = _mm_max_epi16(pos, _mm_and_si128(count, _mm_castps_si128(_mm_cmpgt_ps(r4, max))));
+         /* Update the max. */
+         max = _mm_max_ps(max, r4);
+         /* Update the indices (+4) */
+         count = _mm_add_epi32(count, fours);
+      }
+      /* Horizontal max */
+      max2 = _mm_max_ps(max, _mm_shuffle_ps(max, max, _MM_SHUFFLE(1, 0, 3, 2)));
+      max2 = _mm_max_ps(max2, _mm_shuffle_ps(max2, max2, _MM_SHUFFLE(2, 3, 0, 1)));
+      /* Now that max2 contains the max at all positions, look at which value(s) of the
+         partial max is equal to the global max. */
+      pos = _mm_and_si128(pos, _mm_castps_si128(_mm_cmpeq_ps(max, max2)));
+      pos = _mm_max_epi16(pos, _mm_unpackhi_epi64(pos, pos));
+      pos = _mm_max_epi16(pos, _mm_shufflelo_epi16(pos, _MM_SHUFFLE(1, 0, 3, 2)));
+      best_id = _mm_cvtsi128_si32(pos);
+
+      /* Updating the sums of the new pulse(s) */
+      xy = ADD32(xy, EXTEND32(X[best_id]));
+      /* We're multiplying y[j] by two so we don't have to do it here */
+      yy = ADD16(yy, y[best_id]);
+
+      /* Only now that we've made the final choice, update y/iy */
+      /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
+      y[best_id] += 2;
+      iy[best_id]++;
+   }
+
+   /* Put the original sign back */
+   for (j=0;j<N;j+=4)
+   {
+      __m128i y4;
+      __m128i s4;
+      y4 = _mm_loadu_si128((__m128i*)&iy[j]);
+      s4 = _mm_castps_si128(_mm_loadu_ps(&signy[j]));
+      y4 = _mm_xor_si128(_mm_add_epi32(y4, s4), s4);
+      _mm_storeu_si128((__m128i*)&iy[j], y4);
+   }
+   RESTORE_STACK;
+   return yy;
+}
+
+#endif
--- a/media/libopus/celt/x86/x86_celt_map.c
+++ b/media/libopus/celt/x86/x86_celt_map.c
@@ -28,30 +28,30 @@
 #if defined(HAVE_CONFIG_H)
 #include "config.h"
 #endif
 
 #include "x86/x86cpu.h"
 #include "celt_lpc.h"
 #include "pitch.h"
 #include "pitch_sse.h"
+#include "vq.h"
 
 #if defined(OPUS_HAVE_RTCD)
 
 # if defined(FIXED_POINT)
 
 #if defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)
 
 void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
          const opus_val16 *x,
          const opus_val16 *num,
          opus_val16       *y,
          int              N,
          int              ord,
-         opus_val16       *mem,
          int              arch
 ) = {
   celt_fir_c,                /* non-sse */
   celt_fir_c,
   celt_fir_c,
   MAY_HAVE_SSE4_1(celt_fir), /* sse4.1  */
   MAY_HAVE_SSE4_1(celt_fir)  /* avx  */
 };
@@ -146,10 +146,22 @@ void (*const COMB_FILTER_CONST_IMPL[OPUS
   MAY_HAVE_SSE(comb_filter_const),
   MAY_HAVE_SSE(comb_filter_const),
   MAY_HAVE_SSE(comb_filter_const)
 };
 
 
 #endif
 
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)
+opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
+      celt_norm *_X, int *iy, int K, int N, int arch
+) = {
+  op_pvq_search_c,                /* non-sse */
+  op_pvq_search_c,
+  MAY_HAVE_SSE2(op_pvq_search),
+  MAY_HAVE_SSE2(op_pvq_search),
+  MAY_HAVE_SSE2(op_pvq_search)
+};
+#endif
+
 #endif
 #endif
--- a/media/libopus/include/opus_defines.h
+++ b/media/libopus/include/opus_defines.h
@@ -160,18 +160,19 @@ extern "C" {
 #define OPUS_GET_GAIN_REQUEST                4045 /* Should have been 4035 */
 #define OPUS_SET_LSB_DEPTH_REQUEST           4036
 #define OPUS_GET_LSB_DEPTH_REQUEST           4037
 #define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
 #define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
 #define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
 #define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
 #define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
-
 /* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
+#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
+#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
 
 /* Macros to trigger compilation errors when the wrong types are provided to a CTL */
 #define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
 #define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
 #define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
 #define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
 /** @endcond */
 
@@ -203,16 +204,19 @@ extern "C" {
 
 #define OPUS_FRAMESIZE_ARG                   5000 /**< Select frame size from the argument (default) */
 #define OPUS_FRAMESIZE_2_5_MS                5001 /**< Use 2.5 ms frames */
 #define OPUS_FRAMESIZE_5_MS                  5002 /**< Use 5 ms frames */
 #define OPUS_FRAMESIZE_10_MS                 5003 /**< Use 10 ms frames */
 #define OPUS_FRAMESIZE_20_MS                 5004 /**< Use 20 ms frames */
 #define OPUS_FRAMESIZE_40_MS                 5005 /**< Use 40 ms frames */
 #define OPUS_FRAMESIZE_60_MS                 5006 /**< Use 60 ms frames */
+#define OPUS_FRAMESIZE_80_MS                 5007 /**< Use 80 ms frames */
+#define OPUS_FRAMESIZE_100_MS                5008 /**< Use 100 ms frames */
+#define OPUS_FRAMESIZE_120_MS                5009 /**< Use 120 ms frames */
 
 /**@}*/
 
 
 /** @defgroup opus_encoderctls Encoder related CTLs
   *
   * These are convenience macros for use with the \c opus_encode_ctl
   * interface. They are used to generate the appropriate series of
@@ -561,32 +565,36 @@ extern "C" {
   * <dl>
   * <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
   * <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
-  * <dt>OPUS_FRAMESIZE_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
+  * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
   * </dl>
   * @hideinitializer */
 #define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
 /** Gets the encoder's configured use of variable duration frames.
   * @see OPUS_SET_EXPERT_FRAME_DURATION
   * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
   * <dl>
   * <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
   * <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
-  * <dt>OPUS_FRAMESIZE_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
+  * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
   * </dl>
   * @hideinitializer */
 #define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
 
 /** If set to 1, disables almost all use of prediction, making frames almost
   * completely independent. This reduces quality.
   * @see OPUS_GET_PREDICTION_DISABLED
   * @param[in] x <tt>opus_int32</tt>: Allowed values:
@@ -676,16 +684,40 @@ extern "C" {
 /** Gets the sampling rate the encoder or decoder was initialized with.
   * This simply returns the <code>Fs</code> value passed to opus_encoder_init()
   * or opus_decoder_init().
   * @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
   * @hideinitializer
   */
 #define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
 
+/** If set to 1, disables the use of phase inversion for intensity stereo,
+  * improving the quality of mono downmixes, but slightly reducing normal
+  * stereo quality. Disabling phase inversion in the decoder does not comply
+  * with RFC 6716, although it does not cause any interoperability issue and
+  * is expected to become part of the Opus standard once RFC 6716 is updated
+  * by draft-ietf-codec-opus-update.
+  * @see OPUS_GET_PHASE_INVERSION_DISABLED
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Enable phase inversion (default).</dd>
+  * <dt>1</dt><dd>Disable phase inversion.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured phase inversion status.
+  * @see OPUS_SET_PHASE_INVERSION_DISABLED
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd>
+  * <dt>1</dt><dd>Stereo phase inversion disabled.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
+
 /**@}*/
 
 /** @defgroup opus_decoderctls Decoder related CTLs
   * @see opus_genericctls, opus_encoderctls, opus_decoder
   * @{
   */
 
 /** Configures decoder gain adjustment.
--- a/media/libopus/include/opus_multistream.h
+++ b/media/libopus/include/opus_multistream.h
@@ -268,17 +268,17 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT Opus
       opus_int32 Fs,
       int channels,
       int mapping_family,
       int *streams,
       int *coupled_streams,
       unsigned char *mapping,
       int application,
       int *error
-) OPUS_ARG_NONNULL(5);
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
 
 /** Initialize a previously allocated multistream encoder state.
   * The memory pointed to by \a st must be at least the size returned by
   * opus_multistream_encoder_get_size().
   * This is intended for applications which use their own allocator instead of
   * malloc.
   * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
   * @see opus_multistream_encoder_create
@@ -337,17 +337,17 @@ OPUS_EXPORT int opus_multistream_surroun
       OpusMSEncoder *st,
       opus_int32 Fs,
       int channels,
       int mapping_family,
       int *streams,
       int *coupled_streams,
       unsigned char *mapping,
       int application
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
 
 /** Encodes a multistream Opus frame.
   * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
   * @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
   *                                            samples.
   *                                            This must contain
   *                                            <code>frame_size*channels</code>
   *                                            samples.
--- a/media/libopus/include/opus_types.h
+++ b/media/libopus/include/opus_types.h
@@ -29,17 +29,17 @@
 /**
    @file opus_types.h
    @brief Opus reference implementation types
 */
 #ifndef OPUS_TYPES_H
 #define OPUS_TYPES_H
 
 /* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
-#if (defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
+#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
 #include <stdint.h>
 
    typedef int16_t opus_int16;
    typedef uint16_t opus_uint16;
    typedef int32_t opus_int32;
    typedef uint32_t opus_uint32;
 #elif defined(_WIN32)
 
--- a/media/libopus/moz.build
+++ b/media/libopus/moz.build
@@ -15,17 +15,17 @@ EXPORTS.opus += [
 ]
 
 # We allow warnings for third-party code that can be updated from upstream.
 ALLOW_COMPILER_WARNINGS = True
 
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['OPUS_BUILD'] = True
-DEFINES['OPUS_VERSION'] = '"v1.1.5-mozilla"'
+DEFINES['OPUS_VERSION'] = '"v1.2-rc1-mozilla"'
 DEFINES['USE_ALLOCA'] = True
 
 # Don't export symbols
 DEFINES['OPUS_EXPORT'] = ''
 
 if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_AS']:
     DEFINES['OPUS_ARM_ASM'] = True
     DEFINES['OPUS_ARM_EXTERNAL_ASM'] = True
--- a/media/libopus/silk/A2NLSF.c
+++ b/media/libopus/silk/A2NLSF.c
@@ -35,17 +35,17 @@ POSSIBILITY OF SUCH DAMAGE.
 #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 MAX_ITERATIONS_A2NLSF_FIX    30
+#define MAX_ITERATIONS_A2NLSF_FIX    16
 
 /* Helper function for A2NLSF(..)                    */
 /* Transforms polynomials from cos(n*f) to cos(f)^n  */
 static OPUS_INLINE void silk_A2NLSF_trans_poly(
     opus_int32          *p,                     /* I/O    Polynomial                                */
     const opus_int      dd                      /* I      Polynomial order (= filter order / 2 )    */
 )
 {
@@ -125,17 +125,17 @@ static OPUS_INLINE void silk_A2NLSF_init
 /* 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 in 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_int   i, k, m, dd, root_ix, ffrac;
     opus_int32 xlo, xhi, xmid;
     opus_int32 ylo, yhi, ymid, thr;
     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;
 
@@ -234,23 +234,23 @@ void silk_A2NLSF(
             thr = 0;
 
             if( k > LSF_COS_TAB_SZ_FIX ) {
                 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 ] );
+                        NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ 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_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
 
                 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;
--- a/media/libopus/silk/CNG.c
+++ b/media/libopus/silk/CNG.c
@@ -133,21 +133,21 @@ void silk_CNG(
             gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
             gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 );
         } else {
             gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 );
             gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
             gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
         }
         gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
-        
+
         silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
 
         /* Convert CNG NLSF to filter representation */
-        silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
+        silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
 
         /* Generate CNG signal, by synthesis filtering */
         silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
         for( i = 0; i < length; i++ ) {
             silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
             /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
             LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
             LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i -  1 ], A_Q12[ 0 ] );
@@ -165,20 +165,20 @@ void silk_CNG(
                 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
                 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
                 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
                 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
                 LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
             }
 
             /* Update states */
-            CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q14[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
-            
+            CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
+
             /* Scale with Gain and add to input signal */
             frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
-            
+
         }
         silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
     } else {
         silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order *  sizeof( opus_int32 ) );
     }
     RESTORE_STACK;
 }
--- a/media/libopus/silk/LPC_analysis_filter.c
+++ b/media/libopus/silk/LPC_analysis_filter.c
@@ -34,48 +34,51 @@ POSSIBILITY OF SUCH DAMAGE.
 
 /*******************************************/
 /* LPC analysis filter                     */
 /* NB! State is kept internally and the    */
 /* filter always starts with zero state    */
 /* first d output samples are set to zero  */
 /*******************************************/
 
+/* OPT: Using celt_fir() for this function should be faster, but it may cause
+   integer overflows in intermediate values (not final results), which the
+   current implementation silences by casting to unsigned. Enabling
+   this should be safe in pretty much all cases, even though it is not technically
+   C89-compliant. */
+#define USE_CELT_FIR 0
+
 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                                                */
     int                         arch                /* I    Run-time architecture                                       */
 )
 {
     opus_int   j;
-#ifdef FIXED_POINT
-    opus_int16 mem[SILK_MAX_ORDER_LPC];
+#if defined(FIXED_POINT) && USE_CELT_FIR
     opus_int16 num[SILK_MAX_ORDER_LPC];
 #else
     int ix;
     opus_int32       out32_Q12, out32;
     const opus_int16 *in_ptr;
 #endif
 
     silk_assert( d >= 6 );
     silk_assert( (d & 1) == 0 );
     silk_assert( d <= len );
 
-#ifdef FIXED_POINT
+#if defined(FIXED_POINT) && USE_CELT_FIR
     silk_assert( d <= SILK_MAX_ORDER_LPC );
     for ( j = 0; j < d; j++ ) {
         num[ j ] = -B[ j ];
     }
-    for (j=0;j<d;j++) {
-        mem[ j ] = in[ d - j - 1 ];
-    }
-    celt_fir( in + d, num, out + d, len - d, d, mem, arch );
+    celt_fir( in + d, num, out + d, len - d, d, arch );
     for ( j = 0; j < d; j++ ) {
         out[ j ] = 0;
     }
 #else
     (void)arch;
     for( ix = d; ix < len; ix++ ) {
         in_ptr = &in[ ix - 1 ];
 
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/LPC_fit.c
@@ -0,0 +1,81 @@
+/***********************************************************************
+Copyright (c) 2013, Koen Vos. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
+void silk_LPC_fit(
+    opus_int16                  *a_QOUT,            /* O    Output signal                                               */
+    opus_int32                    *a_QIN,             /* I/O  Input signal                                                */
+    const opus_int              QOUT,               /* I    Input Q domain                                              */
+    const opus_int              QIN,                /* I    Input Q domain                                              */
+    const opus_int              d                   /* I    Filter order                                                */
+)
+{
+    opus_int    i, k, idx = 0;
+    opus_int32    maxabs, absval, chirp_Q16;
+
+    /* 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( a_QIN[k] );
+            if( absval > maxabs ) {
+                maxabs = absval;
+                idx    = k;
+            }
+        }
+        maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT );
+
+        if( maxabs > silk_int16_MAX ) {
+            /* Reduce magnitude of prediction coefficients */
+            maxabs = silk_min( maxabs, 163838 );  /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
+            chirp_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( a_QIN, d, chirp_Q16 );
+        } else {
+            break;
+        }
+    }
+
+    if( i == 10 ) {
+        /* Reached the last iteration, clip the coefficients */
+        for( k = 0; k < d; k++ ) {
+            a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) );
+            a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT );
+        }
+    } else {
+        for( k = 0; k < d; k++ ) {
+            a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT );
+        }
+    }
+}
--- a/media/libopus/silk/LPC_inv_pred_gain.c
+++ b/media/libopus/silk/LPC_inv_pred_gain.c
@@ -25,130 +25,117 @@ ARISING IN ANY WAY OUT OF THE USE OF THI
 POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "SigProc_FIX.h"
+#include "define.h"
 
 #define QA                          24
 #define A_LIMIT                     SILK_FIX_CONST( 0.99975, QA )
 
 #define MUL32_FRAC_Q(a32, b32, Q)   ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
 
 /* Compute inverse of LPC prediction gain, and                          */
 /* test if LPC coefficients are stable (all poles within unit circle)   */
-static opus_int32 LPC_inverse_pred_gain_QA(                 /* O   Returns inverse prediction gain in energy domain, Q30    */
-    opus_int32           A_QA[ 2 ][ SILK_MAX_ORDER_LPC ],   /* I   Prediction coefficients                                  */
+static opus_int32 LPC_inverse_pred_gain_QA_c(               /* O   Returns inverse prediction gain in energy domain, Q30    */
+    opus_int32           A_QA[ SILK_MAX_ORDER_LPC ],        /* I   Prediction coefficients                                  */
     const opus_int       order                              /* I   Prediction order                                         */
 )
 {
     opus_int   k, n, mult2Q;
-    opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA;
-    opus_int32 *Aold_QA, *Anew_QA;
+    opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
 
-    Anew_QA = A_QA[ order & 1 ];
-
-    invGain_Q30 = (opus_int32)1 << 30;
+    invGain_Q30 = SILK_FIX_CONST( 1, 30 );
     for( k = order - 1; k > 0; k-- ) {
         /* Check for stability */
-        if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
+        if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
             return 0;
         }
 
         /* Set RC equal to negated AR coef */
-        rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA );
+        rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
 
         /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
-        rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+        rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), 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 range: [ 2^30 : silk_int32_MAX ] */
-        mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
-        rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 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 ) );
+        if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+            return 0;
+        }
 
-        /* Swap pointers */
-        Aold_QA = Anew_QA;
-        Anew_QA = A_QA[ k & 1 ];
+        /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
+        mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
+        rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
 
         /* Update AR coefficient */
-        for( n = 0; n < k; n++ ) {
-            tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 );
-            Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q );
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            opus_int64 tmp64;
+            tmp1 = A_QA[ n ];
+            tmp2 = A_QA[ k - n - 1 ];
+            tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
+                  MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
+            if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+               return 0;
+            }
+            A_QA[ n ] = ( opus_int32 )tmp64;
+            tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
+                  MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
+            if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+               return 0;
+            }
+            A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
         }
     }
 
     /* Check for stability */
-    if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
+    if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
         return 0;
     }
 
     /* Set RC equal to negated AR coef */
-    rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA );
+    rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
 
     /* Range: [ 1 : 2^30 ] */
-    rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+    rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), 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 );
+    silk_assert( invGain_Q30 >= 0           );
+    silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+    if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+        return 0;
+    }
 
     return invGain_Q30;
 }
 
 /* For input in Q12 domain */
-opus_int32 silk_LPC_inverse_pred_gain(              /* O   Returns inverse prediction gain in energy domain, Q30        */
+opus_int32 silk_LPC_inverse_pred_gain_c(            /* O   Returns inverse prediction gain in energy domain, Q30        */
     const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
     const opus_int              order               /* I   Prediction order                                             */
 )
 {
     opus_int   k;
-    opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
-    opus_int32 *Anew_QA;
+    opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
     opus_int32 DC_resp = 0;
 
-    Anew_QA = Atmp_QA[ order & 1 ];
-
     /* Increase Q domain of the AR coefficients */
     for( k = 0; k < order; k++ ) {
         DC_resp += (opus_int32)A_Q12[ k ];
-        Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
+        Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
     }
     /* If the DC is unstable, we don't even need to do the full calculations */
     if( DC_resp >= 4096 ) {
         return 0;
     }
-    return LPC_inverse_pred_gain_QA( Atmp_QA, order );
+    return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
 }
-
-#ifdef FIXED_POINT
-
-/* For input in Q24 domain */
-opus_int32 silk_LPC_inverse_pred_gain_Q24(          /* O    Returns inverse prediction gain in energy domain, Q30       */
-    const opus_int32            *A_Q24,             /* I    Prediction coefficients [order]                             */
-    const opus_int              order               /* I    Prediction order                                            */
-)
-{
-    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_RSHIFT32( A_Q24[ k ], 24 - QA );
-    }
-
-    return LPC_inverse_pred_gain_QA( Atmp_QA, order );
-}
-#endif
--- a/media/libopus/silk/LP_variable_cutoff.c
+++ b/media/libopus/silk/LP_variable_cutoff.c
@@ -125,11 +125,11 @@ void silk_LP_variable_cutoff(
         /* 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);
+        silk_biquad_alt_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
     }
 }
--- a/media/libopus/silk/MacroCount.h
+++ b/media/libopus/silk/MacroCount.h
@@ -314,24 +314,16 @@ static OPUS_INLINE opus_int16 silk_ADD_P
 #undef silk_ADD_POS_SAT32
 static OPUS_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 OPUS_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 OPUS_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
@@ -694,17 +686,17 @@ static OPUS_INLINE opus_int16 silk_LIMIT
     ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
         : ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
 
 return(ret);
 }
 
 
 #undef silk_LIMIT_32
-static OPUS_INLINE opus_int silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
+static OPUS_INLINE opus_int32 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);
 }
--- a/media/libopus/silk/MacroDebug.h
+++ b/media/libopus/silk/MacroDebug.h
@@ -534,18 +534,17 @@ static OPUS_INLINE opus_int32 silk_DIV32
 }
 
 /* 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 */
+   no checking needed for silk_ADD_POS_SAT32 */
 
 #undef silk_LSHIFT8
 #define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
 static OPUS_INLINE opus_int8 silk_LSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
     opus_int8 ret;
     int       fail = 0;
     ret = a << shift;
     fail |= shift < 0;
--- a/media/libopus/silk/NLSF2A.c
+++ b/media/libopus/silk/NLSF2A.c
@@ -61,42 +61,42 @@ static OPUS_INLINE void silk_NLSF2A_find
         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)                               */
+    const opus_int              d,                  /* I    filter order (should be even)                               */
+    int                         arch                /* I    Run-time architecture                                       */
 )
 {
     /* This ordering was found to maximize quality. It improves numerical accuracy of
        silk_NLSF2A_find_poly() compared to "standard" ordering. */
     static const unsigned char ordering16[16] = {
       0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1
     };
     static const unsigned char ordering10[10] = {
       0, 9, 6, 3, 4, 5, 8, 1, 2, 7
     };
     const unsigned char *ordering;
     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;
 
     silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
-    silk_assert( d==10||d==16 );
+    silk_assert( d==10 || d==16 );
 
     /* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
     ordering = d == 16 ? ordering16 : ordering10;
     for( k = 0; k < d; k++ ) {
-        silk_assert(NLSF[k] >= 0 );
+        silk_assert( NLSF[k] >= 0 );
 
         /* 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);
@@ -121,58 +121,21 @@ void silk_NLSF2A(
         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 */
+    /* Convert int32 coefficients to Q12 int16 coefs */
+    silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d );
 
-        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( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
+        /* 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_LSHIFT( 2, i ) );
         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 = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
-        if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
-            /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion   */
-            /* on the unscaled coefficients, convert to Q12 and measure again                   */
-            silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
-            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;
+            a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );            /* QA+1 -> Q12 */
         }
     }
 }
 
--- a/media/libopus/silk/NLSF_VQ.c
+++ b/media/libopus/silk/NLSF_VQ.c
@@ -28,41 +28,49 @@ 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]                     */
+    opus_int32                  err_Q24[],                      /* 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_int16            pWght_Q9[],                     /* I    Codebook weights [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;
+    opus_int         i, m;
+    opus_int32       diff_Q15, diffw_Q24, sum_error_Q24, pred_Q24;
+    const opus_int16 *w_Q9_ptr;
+    const opus_uint8 *cb_Q8_ptr;
 
-    silk_assert( LPC_order <= 16 );
     silk_assert( ( LPC_order & 1 ) == 0 );
 
     /* Loop over codebook */
+    cb_Q8_ptr = pCB_Q8;
+    w_Q9_ptr = pWght_Q9;
     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 );
+        sum_error_Q24 = 0;
+        pred_Q24 = 0;
+        for( m = LPC_order-2; m >= 0; m -= 2 ) {
+            /* Compute weighted absolute predictive quantization error for index m + 1 */
+            diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m + 1 ], (opus_int32)cb_Q8_ptr[ m + 1 ], 7 ); /* range: [ -32767 : 32767 ]*/
+            diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m + 1 ] );
+            sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
+            pred_Q24 = diffw_Q24;
 
-            /* 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 );
+            /* Compute weighted absolute predictive quantization error for index m */
+            diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)cb_Q8_ptr[ m ], 7 ); /* range: [ -32767 : 32767 ]*/
+            diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m ] );
+            sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
+            pred_Q24 = diffw_Q24;
 
-            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 );
+            silk_assert( sum_error_Q24 >= 0 );
         }
-        err_Q26[ i ] = sum_error_Q26;
+        err_Q24[ i ] = sum_error_Q24;
+        cb_Q8_ptr += LPC_order;
+        w_Q9_ptr += LPC_order;
     }
 }
--- a/media/libopus/silk/NLSF_decode.c
+++ b/media/libopus/silk/NLSF_decode.c
@@ -27,17 +27,17 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "main.h"
 
 /* Predictive dequantizer for NLSF residuals */
-static OPUS_INLINE void silk_NLSF_residual_dequant(               /* O    Returns RD value in Q30                     */
+static OPUS_INLINE 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;
@@ -65,37 +65,29 @@ void silk_NLSF_decode(
           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;
+    opus_int32       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 );
-    }
+    const opus_int16 *pCB_Wght_Q9;
 
     /* Unpack entropy table indices and predictor for current CB1 index */
     silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
 
     /* Predictive residual 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 */
+    /* Apply inverse square-rooted weights to first stage and add to output */
+    pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
+    pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * 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 ) );
-        NLSF_Q15_tmp = silk_ADD32( pNLSF_Q15[ i ], silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), W_tmp_Q9 ) );
+        NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 );
         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 );
 }
--- a/media/libopus/silk/NLSF_del_dec_quant.c
+++ b/media/libopus/silk/NLSF_del_dec_quant.c
@@ -79,17 +79,17 @@ opus_int32 silk_NLSF_del_dec_quant(     
         out1_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_RSHIFT( silk_SMULBB( out1_Q10, quant_step_size_Q16 ), 16 );
     }
 
     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-- ) {
+    for( i = order - 1; i >= 0; i-- ) {
         rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ];
         in_Q10 = x_Q10[ i ];
         for( j = 0; j < nStates; j++ ) {
             pred_Q10 = silk_RSHIFT( silk_SMULBB( (opus_int16)pred_coef_Q8[ i ], prev_out_Q10[ j ] ), 8 );
             res_Q10  = silk_SUB16( in_Q10, pred_Q10 );
             ind_tmp  = silk_RSHIFT( silk_SMULBB( inv_quant_step_size_Q6, res_Q10 ), 16 );
             ind_tmp  = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 );
             ind[ j ][ i ] = (opus_int8)ind_tmp;
@@ -126,26 +126,26 @@ opus_int32 silk_NLSF_del_dec_quant(     
             }
             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 >> 1 ) ) {
+        if( nStates <= NLSF_QUANT_DEL_DEC_STATES/2 ) {
             /* 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 ) {
+        } else {
             /* 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 */
@@ -186,18 +186,16 @@ opus_int32 silk_NLSF_del_dec_quant(     
                 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 */
-            break;
         }
     }
 
     /* 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 ] ) {
--- a/media/libopus/silk/NLSF_encode.c
+++ b/media/libopus/silk/NLSF_encode.c
@@ -32,81 +32,68 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "main.h"
 #include "stack_alloc.h"
 
 /***********************/
 /* 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 ]         */
+          opus_int16            *pNLSF_Q15,                     /* I/O  (Un)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_int16            *pW_Q2,                         /* 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, ret;
-    VARDECL( opus_int32, err_Q26 );
+    VARDECL( opus_int32, err_Q24 );
     VARDECL( opus_int32, RD_Q25 );
     VARDECL( opus_int, tempIndices1 );
     VARDECL( opus_int8, tempIndices2 );
-    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;
+    const opus_int16 *pCB_Wght_Q9;
     SAVE_STACK;
 
-    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 */
-    ALLOC( err_Q26, psNLSF_CB->nVectors, opus_int32 );
-    silk_NLSF_VQ( err_Q26, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->nVectors, psNLSF_CB->order );
+    ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 );
+    silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order );
 
     /* Sort the quantization errors */
     ALLOC( tempIndices1, nSurvivors, opus_int );
-    silk_insertion_sort_increasing( err_Q26, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
+    silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
 
     ALLOC( RD_Q25, nSurvivors, opus_int32 );
     ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 );
 
     /* 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 ];
+        pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ 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 ] );
+            W_tmp_Q9 = pCB_Wght_Q9[ i ];
+            res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 );
+            W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 );
         }
 
         /* 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 );
--- a/media/libopus/silk/NSQ.c
+++ b/media/libopus/silk/NSQ.c
@@ -32,17 +32,17 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "main.h"
 #include "stack_alloc.h"
 #include "NSQ.h"
 
 
 static OPUS_INLINE void silk_nsq_scale_states(
     const silk_encoder_state *psEncC,           /* I    Encoder State                   */
     silk_nsq_state      *NSQ,                   /* I/O  NSQ state                       */
-    const opus_int32    x_Q3[],                 /* I    input in Q3                     */
+    const opus_int16    x16[],                  /* I    input                           */
     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_Q15[],             /* O    LTP state matching scaled input */
     opus_int            subfr,                  /* I    subframe number                 */
     const opus_int      LTP_scale_Q14,          /* I                                    */
     const opus_int32    Gains_Q16[ MAX_NB_SUBFR ], /* I                                 */
     const opus_int      pitchL[ MAX_NB_SUBFR ], /* I    Pitch lag                       */
     const opus_int      signal_type             /* I    Signal type                     */
@@ -70,24 +70,24 @@ static OPUS_INLINE void silk_noise_shape
     opus_int            shapingLPCOrder,        /* I    Noise shaping AR filter order   */
     opus_int            predictLPCOrder,        /* I    Prediction filter order         */
     int                 arch                    /* I    Architecture                    */
 );
 #endif
 
 void silk_NSQ_c
 (
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
-    const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
+    const opus_int16            x16[],                                        /* I    Input                           */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
-    const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs              */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
     const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                   /* I    Spectral tilt                   */
     const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                 /* I    Low frequency shaping coefs     */
     const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                  /* I    Quantization step sizes         */
     const opus_int              pitchL[ MAX_NB_SUBFR ],                     /* I    Pitch lags                      */
     const opus_int              Lambda_Q10,                                 /* I    Rate/distortion tradeoff        */
     const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
 )
@@ -112,28 +112,27 @@ void silk_NSQ_c
     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;
     }
 
-    ALLOC( sLTP_Q15,
-           psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+    ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
     ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
     ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
     /* Set up pointers to start of sub frame */
     NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
     NSQ->sLTP_buf_idx     = psEncC->ltp_mem_length;
     pxq                   = &NSQ->xq[ psEncC->ltp_mem_length ];
     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 ];
+        AR_shp_Q13 = &AR_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 ) {
@@ -149,32 +148,31 @@ void silk_NSQ_c
                 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, psEncC->arch );
 
                 NSQ->rewhite_flag = 1;
                 NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
             }
         }
 
-        silk_nsq_scale_states( psEncC, NSQ, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
+        silk_nsq_scale_states( psEncC, NSQ, x16, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
 
         silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
             AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
             offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
 
-        x_Q3   += psEncC->subfr_length;
+        x16    += 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 */
-    /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
     silk_memmove( NSQ->xq,           &NSQ->xq[           psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
     silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
     RESTORE_STACK;
 }
 
 /***********************************/
 /* silk_noise_shape_quantizer  */
 /***********************************/
@@ -245,17 +243,17 @@ void silk_noise_shape_quantizer(
             LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
             pred_lag_ptr++;
         } else {
             LTP_pred_Q13 = 0;
         }
 
         /* Noise shape feedback */
         silk_assert( ( shapingLPCOrder & 1 ) == 0 );   /* check that order is even */
-        n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(psLPC_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
+        n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
 
         n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
 
         n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
         n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 );
 
         silk_assert( lag > 0 || signalType != TYPE_VOICED );
 
@@ -274,24 +272,37 @@ void silk_noise_shape_quantizer(
             tmp1 = silk_RSHIFT_ROUND( tmp1, 3 );                                /* Q10 */
         } else {
             tmp1 = silk_RSHIFT_ROUND( tmp1, 2 );                                /* Q10 */
         }
 
         r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 );                              /* residual error Q10 */
 
         /* Flip sign depending on dither */
-        if ( NSQ->rand_seed < 0 ) {
-           r_Q10 = -r_Q10;
+        if( NSQ->rand_seed < 0 ) {
+            r_Q10 = -r_Q10;
         }
         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_Q0 = silk_RSHIFT( q1_Q10, 10 );
+        if (Lambda_Q10 > 2048) {
+            /* For aggressive RDO, the bias becomes more than one pulse. */
+            int rdo_offset = Lambda_Q10/2 - 512;
+            if (q1_Q10 > rdo_offset) {
+                q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+            } else if (q1_Q10 < -rdo_offset) {
+                q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+            } else if (q1_Q10 < 0) {
+                q1_Q0 = -1;
+            } else {
+                q1_Q0 = 0;
+            }
+        }
         if( q1_Q0 > 0 ) {
             q1_Q10  = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
             q1_Q10  = silk_ADD32( q1_Q10, offset_Q10 );
             q2_Q10  = silk_ADD32( q1_Q10, 1024 );
             rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 );
             rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
         } else if( q1_Q0 == 0 ) {
             q1_Q10  = offset_Q10;
@@ -332,17 +343,18 @@ void silk_noise_shape_quantizer(
         xq_Q14      = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 );
 
         /* Scale XQ back to normal level before saving */
         xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q14, Gain_Q10 ), 8 ) );
 
         /* Update states */
         psLPC_Q14++;
         *psLPC_Q14 = xq_Q14;
-        sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, n_AR_Q12, 2 );
+        NSQ->sDiff_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_sc_Q10[ i ], 4 );
+        sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( NSQ->sDiff_shp_Q14, n_AR_Q12, 2 );
         NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
 
         NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
         sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 );
         NSQ->sLTP_shp_buf_idx++;
         NSQ->sLTP_buf_idx++;
 
         /* Make dither dependent on quantized signal */
@@ -351,79 +363,75 @@ void silk_noise_shape_quantizer(
 
     /* Update LPC synth buffer */
     silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
 }
 
 static OPUS_INLINE void silk_nsq_scale_states(
     const silk_encoder_state *psEncC,           /* I    Encoder State                   */
     silk_nsq_state      *NSQ,                   /* I/O  NSQ state                       */
-    const opus_int32    x_Q3[],                 /* I    input in Q3                     */
+    const opus_int16    x16[],                  /* I    input                           */
     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_Q15[],             /* O    LTP state matching scaled input */
     opus_int            subfr,                  /* I    subframe number                 */
     const opus_int      LTP_scale_Q14,          /* I                                    */
     const opus_int32    Gains_Q16[ MAX_NB_SUBFR ], /* I                                 */
     const opus_int      pitchL[ MAX_NB_SUBFR ], /* I    Pitch lag                       */
     const opus_int      signal_type             /* I    Signal type                     */
 )
 {
     opus_int   i, lag;
-    opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
+    opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
 
     lag          = pitchL[ subfr ];
     inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
     silk_assert( inv_gain_Q31 != 0 );
 
-    /* Calculate gain adjustment factor */
-    if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
-        gain_adj_Q16 =  silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
-    } else {
-        gain_adj_Q16 = (opus_int32)1 << 16;
+    /* Scale input */
+    inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
+    for( i = 0; i < psEncC->subfr_length; i++ ) {
+        x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
     }
 
-    /* Scale input */
-    inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
-    for( i = 0; i < psEncC->subfr_length; i++ ) {
-        x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
-    }
-
-    /* Save inverse gain */
-    NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
-
     /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
     if( NSQ->rewhite_flag ) {
         if( subfr == 0 ) {
             /* Do LTP downscaling */
             inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
         }
         for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
             silk_assert( i < MAX_FRAME_LENGTH );
             sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
         }
     }
 
     /* Adjust for changing gain */
-    if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+    if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+        gain_adj_Q16 =  silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 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_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
         }
 
         /* Scale long-term prediction state */
         if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
             for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
                 sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
             }
         }
 
         NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
+        NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_shp_Q14 );
 
         /* 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 ] );
         }
+
+        /* Save inverse gain */
+        NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
     }
 }
--- a/media/libopus/silk/NSQ_del_dec.c
+++ b/media/libopus/silk/NSQ_del_dec.c
@@ -38,40 +38,42 @@ typedef struct {
     opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
     opus_int32 RandState[ DECISION_DELAY ];
     opus_int32 Q_Q10[     DECISION_DELAY ];
     opus_int32 Xq_Q14[    DECISION_DELAY ];
     opus_int32 Pred_Q15[  DECISION_DELAY ];
     opus_int32 Shape_Q14[ DECISION_DELAY ];
     opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
     opus_int32 LF_AR_Q14;
+    opus_int32 Diff_Q14;
     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_Q14;
+    opus_int32 Diff_Q14;
     opus_int32 sLTP_shp_Q14;
     opus_int32 LPC_exc_Q14;
 } NSQ_sample_struct;
 
 typedef NSQ_sample_struct  NSQ_sample_pair[ 2 ];
 
 #if defined(MIPSr1_ASM)
 #include "mips/NSQ_del_dec_mipsr1.h"
 #endif
 static OPUS_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_int32    x_Q3[],                     /* I    Input in Q3                         */
+    const opus_int16    x16[],                      /* I    Input                               */
     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_Q15[],                 /* O    LTP state matching scaled input     */
     opus_int            subfr,                      /* I    Subframe number                     */
     opus_int            nStatesDelayedDecision,     /* I    Number of del dec states            */
     const opus_int      LTP_scale_Q14,              /* I    LTP state scaling                   */
     const opus_int32    Gains_Q16[ MAX_NB_SUBFR ],  /* I                                        */
     const opus_int      pitchL[ MAX_NB_SUBFR ],     /* I    Pitch lag                           */
@@ -102,30 +104,30 @@ static OPUS_INLINE void silk_noise_shape
     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            *smpl_buf_idx,          /* I/O  Index to newest samples in buffers  */
     opus_int            decisionDelay,          /* I                                        */
     int                 arch                    /* I                                        */
 );
 
 void silk_NSQ_del_dec_c(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
-    const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
+    const opus_int16            x16[],                                        /* I    Input                           */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
-    const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs              */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
     const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                   /* I    Spectral tilt                   */
     const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                 /* I    Low frequency shaping coefs     */
     const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                  /* I    Quantization step sizes         */
     const opus_int              pitchL[ MAX_NB_SUBFR ],                     /* I    Pitch lags                      */
     const opus_int              Lambda_Q10,                                 /* I    Rate/distortion tradeoff        */
     const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
 )
@@ -154,16 +156,17 @@ void silk_NSQ_del_dec_c(
     ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct );
     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_Q14      = NSQ->sLF_AR_shp_Q14;
+        psDD->Diff_Q14       = NSQ->sDiff_shp_Q14;
         psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ 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 */
 
@@ -181,30 +184,29 @@ void silk_NSQ_del_dec_c(
     }
 
     if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
         LSF_interpolation_flag = 0;
     } else {
         LSF_interpolation_flag = 1;
     }
 
-    ALLOC( sLTP_Q15,
-           psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+    ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
     ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
     ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
     ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
     /* Set up pointers to start of sub frame */
     pxq                   = &NSQ->xq[ psEncC->ltp_mem_length ];
     NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
     NSQ->sLTP_buf_idx     = psEncC->ltp_mem_length;
     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 ];
+        AR_shp_Q13 = &AR_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 ) {
@@ -230,17 +232,18 @@ void silk_NSQ_del_dec_c(
                             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;
+                        last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
+                        if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
                         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_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
                         NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ];
                     }
 
                     subfr = 0;
                 }
@@ -252,25 +255,25 @@ void silk_NSQ_del_dec_c(
                 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, psEncC->arch );
 
                 NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
                 NSQ->rewhite_flag = 1;
             }
         }
 
-        silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x_Q3, x_sc_Q10, sLTP, sLTP_Q15, k,
+        silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
             psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
 
         silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
             delayedGain_Q10, 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, psEncC->arch );
 
-        x_Q3   += psEncC->subfr_length;
+        x16    += 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++ ) {
@@ -281,31 +284,33 @@ void silk_NSQ_del_dec_c(
     }
 
     /* 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;
     Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
     for( i = 0; i < decisionDelay; i++ ) {
-        last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
+        last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
+        if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
+
         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_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
         NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ 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_Q14 = psDD->LF_AR_Q14;
+    NSQ->sDiff_shp_Q14  = psDD->Diff_Q14;
     NSQ->lagPrev        = pitchL[ psEncC->nb_subfr - 1 ];
 
     /* Save quantized speech signal */
-    /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
     silk_memmove( NSQ->xq,           &NSQ->xq[           psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
     silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
     RESTORE_STACK;
 }
 
 /******************************************/
 /* Noise shape quantizer for one subframe */
 /******************************************/
@@ -330,17 +335,17 @@ static OPUS_INLINE void silk_noise_shape
     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            *smpl_buf_idx,          /* I/O  Index to newest samples in buffers  */
     opus_int            decisionDelay,          /* I                                        */
     int                 arch                    /* 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_Q14, n_AR_Q14, n_LTP_Q14;
     opus_int32   n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
@@ -411,17 +416,17 @@ static OPUS_INLINE void silk_noise_shape
             psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
             /* Short-term prediction */
             LPC_pred_Q14 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch);
             LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 );                              /* Q10 -> Q14 */
 
             /* 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 );
+            tmp2 = silk_SMLAWB( psDD->Diff_Q14, 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_Q14 = silk_RSHIFT( shapingLPCOrder, 1 );
             n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] );
             /* Loop over allpass sections */
             for( j = 2; j < shapingLPCOrder; j += 2 ) {
                 /* Output of allpass section */
@@ -457,16 +462,29 @@ static OPUS_INLINE void silk_noise_shape
             if ( psDD->Seed < 0 ) {
                 r_Q10 = -r_Q10;
             }
             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_Q0 = silk_RSHIFT( q1_Q10, 10 );
+            if (Lambda_Q10 > 2048) {
+                /* For aggressive RDO, the bias becomes more than one pulse. */
+                int rdo_offset = Lambda_Q10/2 - 512;
+                if (q1_Q10 > rdo_offset) {
+                    q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
+                } else if (q1_Q10 < -rdo_offset) {
+                    q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
+                } else if (q1_Q10 < 0) {
+                    q1_Q0 = -1;
+                } else {
+                    q1_Q0 = 0;
+                }
+            }
             if( q1_Q0 > 0 ) {
                 q1_Q10  = silk_SUB32( silk_LSHIFT( q1_Q0, 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_Q0 == 0 ) {
                 q1_Q10  = offset_Q10;
@@ -510,45 +528,47 @@ static OPUS_INLINE void silk_noise_shape
                 exc_Q14 = -exc_Q14;
             }
 
             /* Add predictions */
             LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
             xq_Q14      = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
 
             /* Update states */
-            sLF_AR_shp_Q14         = silk_SUB32( xq_Q14, n_AR_Q14 );
+            psSS[ 0 ].Diff_Q14     = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
+            sLF_AR_shp_Q14         = silk_SUB32( psSS[ 0 ].Diff_Q14, n_AR_Q14 );
             psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
             psSS[ 0 ].LF_AR_Q14    = sLF_AR_shp_Q14;
             psSS[ 0 ].LPC_exc_Q14  = LPC_exc_Q14;
             psSS[ 0 ].xq_Q14       = xq_Q14;
 
             /* Update states for second best quantization */
 
             /* Quantized excitation */
             exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 );
             if ( psDD->Seed < 0 ) {
                 exc_Q14 = -exc_Q14;
             }
 
-
             /* Add predictions */
             LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
             xq_Q14      = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
 
             /* Update states */
-            sLF_AR_shp_Q14         = silk_SUB32( xq_Q14, n_AR_Q14 );
+            psSS[ 1 ].Diff_Q14     = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
+            sLF_AR_shp_Q14         = silk_SUB32( psSS[ 1 ].Diff_Q14, n_AR_Q14 );
             psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
             psSS[ 1 ].LF_AR_Q14    = sLF_AR_shp_Q14;
             psSS[ 1 ].LPC_exc_Q14  = LPC_exc_Q14;
             psSS[ 1 ].xq_Q14       = xq_Q14;
         }
 
-        *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   */
+        *smpl_buf_idx  = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
+        if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
+        last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
 
         /* 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;
@@ -602,16 +622,17 @@ static OPUS_INLINE void silk_noise_shape
         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_Q14                          = psSS->LF_AR_Q14;
+            psDD->Diff_Q14                           = psSS->Diff_Q14;
             psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
             psDD->Xq_Q14[    *smpl_buf_idx ]         = psSS->xq_Q14;
             psDD->Q_Q10[     *smpl_buf_idx ]         = psSS->Q_Q10;
             psDD->Pred_Q15[  *smpl_buf_idx ]         = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 );
             psDD->Shape_Q14[ *smpl_buf_idx ]         = psSS->sLTP_shp_Q14;
             psDD->Seed                               = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) );
             psDD->RandState[ *smpl_buf_idx ]         = psDD->Seed;
             psDD->RD_Q10                             = psSS->RD_Q10;
@@ -626,67 +647,59 @@ static OPUS_INLINE void silk_noise_shape
     RESTORE_STACK;
 }
 #endif /* OVERRIDE_silk_noise_shape_quantizer_del_dec */
 
 static OPUS_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_int32    x_Q3[],                     /* I    Input in Q3                         */
+    const opus_int16    x16[],                      /* I    Input                               */
     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_Q15[],                 /* O    LTP state matching scaled input     */
     opus_int            subfr,                      /* I    Subframe number                     */
     opus_int            nStatesDelayedDecision,     /* I    Number of del dec states            */
     const opus_int      LTP_scale_Q14,              /* I    LTP state scaling                   */
     const opus_int32    Gains_Q16[ MAX_NB_SUBFR ],  /* I                                        */
     const opus_int      pitchL[ MAX_NB_SUBFR ],     /* I    Pitch lag                           */
     const opus_int      signal_type,                /* I    Signal type                         */
     const opus_int      decisionDelay               /* I    Decision delay                      */
 )
 {
     opus_int            i, k, lag;
-    opus_int32          gain_adj_Q16, inv_gain_Q31, inv_gain_Q23;
+    opus_int32          gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
     NSQ_del_dec_struct  *psDD;
 
     lag          = pitchL[ subfr ];
     inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
     silk_assert( inv_gain_Q31 != 0 );
 
-    /* Calculate gain adjustment factor */
-    if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
-        gain_adj_Q16 =  silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
-    } else {
-        gain_adj_Q16 = (opus_int32)1 << 16;
+    /* Scale input */
+    inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
+    for( i = 0; i < psEncC->subfr_length; i++ ) {
+        x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
     }
 
-    /* Scale input */
-    inv_gain_Q23 = silk_RSHIFT_ROUND( inv_gain_Q31, 8 );
-    for( i = 0; i < psEncC->subfr_length; i++ ) {
-        x_sc_Q10[ i ] = silk_SMULWW( x_Q3[ i ], inv_gain_Q23 );
-    }
-
-    /* Save inverse gain */
-    NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
-
     /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
     if( NSQ->rewhite_flag ) {
         if( subfr == 0 ) {
             /* Do LTP downscaling */
             inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
         }
         for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
             silk_assert( i < MAX_FRAME_LENGTH );
             sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
         }
     }
 
     /* Adjust for changing gain */
-    if( gain_adj_Q16 != (opus_int32)1 << 16 ) {
+    if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+        gain_adj_Q16 =  silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 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_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
         }
 
         /* Scale long-term prediction state */
         if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
             for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
@@ -694,23 +707,27 @@ static OPUS_INLINE void silk_nsq_del_dec
             }
         }
 
         for( k = 0; k < nStatesDelayedDecision; k++ ) {
             psDD = &psDelDec[ k ];
 
             /* Scale scalar states */
             psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 );
+            psDD->Diff_Q14 = silk_SMULWW( gain_adj_Q16, psDD->Diff_Q14 );
 
             /* 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_Q15[  i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[  i ] );
                 psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] );
             }
         }
+
+        /* Save inverse gain */
+        NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
     }
 }
--- a/media/libopus/silk/PLC.c
+++ b/media/libopus/silk/PLC.c
@@ -270,17 +270,17 @@ static OPUS_INLINE void silk_PLC_conceal
                 rand_scale_Q14 -= B_Q14[ i ];
             }
             rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
             rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
         } else {
             /* Reduce random noise for unvoiced frames with high LPC gain */
             opus_int32 invGain_Q30, down_scale_Q30;
 
-            invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order );
+            invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );
 
             down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
             down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)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 );
         }
     }
@@ -323,18 +323,20 @@ static OPUS_INLINE void silk_PLC_conceal
             sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 );
             sLTP_buf_idx++;
         }
 
         /* 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 );
+        if ( psDec->indices.signalType != TYPE_NO_VOICE_ACTIVITY ) {
+            /* 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_SMLAWB( psPLC->pitchL_Q8, 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 );
     }
 
     /***************************/
--- a/media/libopus/silk/SigProc_FIX.h
+++ b/media/libopus/silk/SigProc_FIX.h
@@ -30,28 +30,33 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #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() */
+#define SILK_MAX_ORDER_LPC            24            /* max order of the LPC analysis in schur() and k2a() */
 
 #include <string.h>                                 /* for memset(), memcpy(), memmove() */
 #include "typedef.h"
 #include "resampler_structs.h"
 #include "macros.h"
 #include "cpu_support.h"
 
 #if defined(OPUS_X86_MAY_HAVE_SSE4_1)
 #include "x86/SigProc_FIX_sse.h"
 #endif
 
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/biquad_alt_arm.h"
+#include "arm/LPC_inv_pred_gain_arm.h"
+#endif
+
 /********************************************************************/
 /*                    SIGNAL PROCESSING FUNCTIONS                   */
 /********************************************************************/
 
 /*!
  * Initialize/reset the resampler state for a given pair of input/output sampling rates
 */
 opus_int silk_resampler_init(
@@ -91,24 +96,32 @@ void silk_resampler_down2_3(
     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(
+void silk_biquad_alt_stride1(
     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)                               */
-    opus_int                    stride              /* I     Operate on interleaved signal if > 1                       */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+);
+
+void silk_biquad_alt_stride2_c(
+    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 [4]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
 );
 
 /* 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                                               */
@@ -127,36 +140,38 @@ void silk_bwexpander(
 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_int32 silk_LPC_inverse_pred_gain(              /* O   Returns inverse prediction gain in energy domain, Q30        */
+opus_int32 silk_LPC_inverse_pred_gain_c(            /* O   Returns inverse prediction gain in energy domain, Q30        */
     const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
     const opus_int              order               /* I   Prediction order                                             */
 );
 
-/* For input in Q24 domain */
-opus_int32 silk_LPC_inverse_pred_gain_Q24(          /* O    Returns inverse prediction gain in energy domain, Q30       */
-    const opus_int32            *A_Q24,             /* I    Prediction coefficients [order]                             */
-    const opus_int              order               /* I    Prediction order                                            */
-);
-
 /* 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                                     */
 );
 
+#if !defined(OVERRIDE_silk_biquad_alt_stride2)
+#define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_c(in, B_Q28, A_Q28, S, out, len))
+#endif
+
+#if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
+#define silk_LPC_inverse_pred_gain(A_Q12, order, arch)     ((void)(arch), silk_LPC_inverse_pred_gain_c(A_Q12, order))
+#endif
+
 /********************************************************************/
 /*                        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                                         */
@@ -266,17 +281,27 @@ void silk_A2NLSF(
     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)                               */
+    const opus_int              d,                  /* I    filter order (should be even)                               */
+    int                         arch                /* I    Run-time architecture                                       */
+);
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
+void silk_LPC_fit(
+    opus_int16                  *a_QOUT,            /* O    Output signal                                               */
+    opus_int32                  *a_QIN,             /* I/O  Input signal                                                */
+    const opus_int              QOUT,               /* I    Input Q domain                                              */
+    const opus_int              QIN,                /* I    Input Q domain                                              */
+    const opus_int              d                   /* I    Filter order                                                */
 );
 
 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                       */
 );
@@ -466,18 +491,17 @@ static OPUS_INLINE opus_int32 silk_ROR32
                                             ((((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_ADD_POS_SAT32(a, b)            ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
 
 #define silk_LSHIFT8(a, shift)              ((opus_int8)((opus_uint8)(a)<<(shift)))         /* shift >= 0, shift < 8  */
 #define silk_LSHIFT16(a, shift)             ((opus_int16)((opus_uint16)(a)<<(shift)))       /* shift >= 0, shift < 16 */
 #define silk_LSHIFT32(a, shift)             ((opus_int32)((opus_uint32)(a)<<(shift)))       /* shift >= 0, shift < 32 */
 #define silk_LSHIFT64(a, shift)             ((opus_int64)((opus_uint64)(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  */
@@ -567,17 +591,19 @@ static OPUS_INLINE opus_int64 silk_max_6
 #define silk_abs_int64(a)                   (((a) >  0)  ? (a) : -(a))
 
 #define silk_sign(a)                        ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ))
 
 /* 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))
+#define RAND_MULTIPLIER                     196314165
+#define RAND_INCREMENT                      907633515
+#define silk_RAND(seed)                     (silk_MLA_ovflw((RAND_INCREMENT), (seed), (RAND_MULTIPLIER)))
 
 /*  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 */
--- a/media/libopus/silk/VQ_WMat_EC.c
+++ b/media/libopus/silk/VQ_WMat_EC.c
@@ -29,92 +29,103 @@ POSSIBILITY OF SUCH DAMAGE.
 #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_c(
     opus_int8                   *ind,                           /* O    index of best codebook vector               */
-    opus_int32                  *rate_dist_Q14,                 /* O    best weighted quant error + mu * rate       */
+    opus_int32                  *res_nrg_Q15,                   /* O    best residual energy                        */
+    opus_int32                  *rate_dist_Q8,                  /* O    best total bitrate                          */
     opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
-    const opus_int16            *in_Q14,                        /* I    input vector to be quantized                */
-    const opus_int32            *W_Q18,                         /* I    weighting matrix                            */
+    const opus_int32            *XX_Q17,                        /* I    correlation matrix                          */
+    const opus_int32            *xX_Q17,                        /* I    correlation vector                          */
     const opus_int8             *cb_Q7,                         /* I    codebook                                    */
     const opus_uint8            *cb_gain_Q7,                    /* I    codebook effective gain                     */
     const opus_uint8            *cl_Q5,                         /* I    code length for each codebook vector        */
-    const opus_int              mu_Q9,                          /* I    tradeoff betw. weighted error and rate      */
+    const opus_int              subfr_len,                      /* I    number of samples per subframe              */
     const opus_int32            max_gain_Q7,                    /* I    maximum sum of absolute LTP coefficients    */
-    opus_int                    L                               /* I    number of vectors in codebook               */
+    const opus_int              L                               /* I    number of vectors in codebook               */
 )
 {
     opus_int   k, gain_tmp_Q7;
     const opus_int8 *cb_row_Q7;
-    opus_int16 diff_Q14[ 5 ];
-    opus_int32 sum1_Q14, sum2_Q16;
+    opus_int32 neg_xX_Q24[ 5 ];
+    opus_int32 sum1_Q15, sum2_Q24;
+    opus_int32 bits_res_Q8, bits_tot_Q8;
+
+    /* Negate and convert to new Q domain */
+    neg_xX_Q24[ 0 ] = -silk_LSHIFT32( xX_Q17[ 0 ], 7 );
+    neg_xX_Q24[ 1 ] = -silk_LSHIFT32( xX_Q17[ 1 ], 7 );
+    neg_xX_Q24[ 2 ] = -silk_LSHIFT32( xX_Q17[ 2 ], 7 );
+    neg_xX_Q24[ 3 ] = -silk_LSHIFT32( xX_Q17[ 3 ], 7 );
+    neg_xX_Q24[ 4 ] = -silk_LSHIFT32( xX_Q17[ 4 ], 7 );
 
     /* Loop over codebook */
-    *rate_dist_Q14 = silk_int32_MAX;
+    *rate_dist_Q8 = silk_int32_MAX;
+    *res_nrg_Q15 = silk_int32_MAX;
     cb_row_Q7 = cb_Q7;
+    /* In things go really bad, at least *ind is set to something safe. */
+    *ind = 0;
     for( k = 0; k < L; k++ ) {
+        opus_int32 penalty;
         gain_tmp_Q7 = cb_gain_Q7[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 ] );
+        /* Quantization error: 1 - 2 * xX * cb + cb' * XX * cb */
+        sum1_Q15 = SILK_FIX_CONST( 1.001, 15 );
 
         /* Penalty for too large gain */
-        sum1_Q14 = silk_ADD_LSHIFT32( sum1_Q14, silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 10 );
-
-        silk_assert( sum1_Q14 >= 0 );
+        penalty = silk_LSHIFT32( silk_max( silk_SUB32( gain_tmp_Q7, max_gain_Q7 ), 0 ), 11 );
 
-        /* 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 ] );
+        /* first row of XX_Q17 */
+        sum2_Q24 = silk_MLA( neg_xX_Q24[ 0 ], XX_Q17[  1 ], cb_row_Q7[ 1 ] );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[  2 ], cb_row_Q7[ 2 ] );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[  3 ], cb_row_Q7[ 3 ] );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[  4 ], cb_row_Q7[ 4 ] );
+        sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[  0 ], cb_row_Q7[ 0 ] );
+        sum1_Q15 = silk_SMLAWB( sum1_Q15,        sum2_Q24,  cb_row_Q7[ 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 ] );
+        /* second row of XX_Q17 */
+        sum2_Q24 = silk_MLA( neg_xX_Q24[ 1 ], XX_Q17[  7 ], cb_row_Q7[ 2 ] );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[  8 ], cb_row_Q7[ 3 ] );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[  9 ], cb_row_Q7[ 4 ] );
+        sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[  6 ], cb_row_Q7[ 1 ] );
+        sum1_Q15 = silk_SMLAWB( sum1_Q15,        sum2_Q24,  cb_row_Q7[ 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 ] );
+        /* third row of XX_Q17 */
+        sum2_Q24 = silk_MLA( neg_xX_Q24[ 2 ], XX_Q17[ 13 ], cb_row_Q7[ 3 ] );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[ 14 ], cb_row_Q7[ 4 ] );
+        sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[ 12 ], cb_row_Q7[ 2 ] );
+        sum1_Q15 = silk_SMLAWB( sum1_Q15,        sum2_Q24,  cb_row_Q7[ 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 ] );
+        /* fourth row of XX_Q17 */
+        sum2_Q24 = silk_MLA( neg_xX_Q24[ 3 ], XX_Q17[ 19 ], cb_row_Q7[ 4 ] );
+        sum2_Q24 = silk_LSHIFT32( sum2_Q24, 1 );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[ 18 ], cb_row_Q7[ 3 ] );
+        sum1_Q15 = silk_SMLAWB( sum1_Q15,        sum2_Q24,  cb_row_Q7[ 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 );
+        /* last row of XX_Q17 */
+        sum2_Q24 = silk_LSHIFT32( neg_xX_Q24[ 4 ], 1 );
+        sum2_Q24 = silk_MLA( sum2_Q24,        XX_Q17[ 24 ], cb_row_Q7[ 4 ] );
+        sum1_Q15 = silk_SMLAWB( sum1_Q15,        sum2_Q24,  cb_row_Q7[ 4 ] );
 
         /* find best */
-        if( sum1_Q14 < *rate_dist_Q14 ) {
-            *rate_dist_Q14 = sum1_Q14;
-            *ind = (opus_int8)k;
-            *gain_Q7 = gain_tmp_Q7;
+        if( sum1_Q15 >= 0 ) {
+            /* Translate residual energy to bits using high-rate assumption (6 dB ==> 1 bit/sample) */
+            bits_res_Q8 = silk_SMULBB( subfr_len, silk_lin2log( sum1_Q15 + penalty) - (15 << 7) );
+            /* In the following line we reduce the codelength component by half ("-1"); seems to slghtly improve quality */
+            bits_tot_Q8 = silk_ADD_LSHIFT32( bits_res_Q8, cl_Q5[ k ], 3-1 );
+            if( bits_tot_Q8 <= *rate_dist_Q8 ) {
+                *rate_dist_Q8 = bits_tot_Q8;
+                *res_nrg_Q15 = sum1_Q15 + penalty;
+                *ind = (opus_int8)k;
+                *gain_Q7 = gain_tmp_Q7;
+            }
         }
 
         /* Go to next cbk vector */
         cb_row_Q7 += LTP_ORDER;
     }
 }
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/arm/LPC_inv_pred_gain_arm.h
@@ -0,0 +1,57 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_LPC_INV_PRED_GAIN_ARM_H
+# define SILK_LPC_INV_PRED_GAIN_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+opus_int32 silk_LPC_inverse_pred_gain_neon(         /* O   Returns inverse prediction gain in energy domain, Q30        */
+    const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
+    const opus_int              order               /* I   Prediction order                                             */
+);
+
+#  if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+#   define OVERRIDE_silk_LPC_inverse_pred_gain            (1)
+#   define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), PRESUME_NEON(silk_LPC_inverse_pred_gain)(A_Q12, order))
+#  endif
+# endif
+
+# if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
+/*Is run-time CPU detection enabled on this platform?*/
+#  if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK+1])(const opus_int16 *A_Q12, const opus_int order);
+#   define OVERRIDE_silk_LPC_inverse_pred_gain            (1)
+#   define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((*SILK_LPC_INVERSE_PRED_GAIN_IMPL[(arch)&OPUS_ARCHMASK])(A_Q12, order))
+#  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#   define OVERRIDE_silk_LPC_inverse_pred_gain            (1)
+#   define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_neon(A_Q12, order))
+#  endif
+# endif
+
+#endif /* end SILK_LPC_INV_PRED_GAIN_ARM_H */
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/arm/LPC_inv_pred_gain_neon_intr.c
@@ -0,0 +1,280 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <arm_neon.h>
+#include "SigProc_FIX.h"
+#include "define.h"
+
+#define QA                          24
+#define A_LIMIT                     SILK_FIX_CONST( 0.99975, QA )
+
+#define MUL32_FRAC_Q(a32, b32, Q)   ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
+
+/* The difficulty is how to judge a 64-bit signed integer tmp64 is 32-bit overflowed,
+ * since NEON has no 64-bit min, max or comparison instructions.
+ * A failed idea is to compare the results of vmovn(tmp64) and vqmovn(tmp64) whether they are equal or not.
+ * However, this idea fails when the tmp64 is something like 0xFFFFFFF980000000.
+ * Here we know that mult2Q >= 1, so the highest bit (bit 63, sign bit) of tmp64 must equal to bit 62.
+ * tmp64 was shifted left by 1 and we got tmp64'. If high_half(tmp64') != 0 and high_half(tmp64') != -1,
+ * then we know that bit 31 to bit 63 of tmp64 can not all be the sign bit, and therefore tmp64 is 32-bit overflowed.
+ * That is, we judge if tmp64' > 0x00000000FFFFFFFF, or tmp64' <= 0xFFFFFFFF00000000.
+ * We use narrowing shift right 31 bits to tmp32' to save data bandwidth and instructions.
+ * That is, we judge if tmp32' > 0x00000000, or tmp32' <= 0xFFFFFFFF.
+ */
+
+/* Compute inverse of LPC prediction gain, and                          */
+/* test if LPC coefficients are stable (all poles within unit circle)   */
+static OPUS_INLINE opus_int32 LPC_inverse_pred_gain_QA_neon( /* O   Returns inverse prediction gain in energy domain, Q30    */
+    opus_int32           A_QA[ SILK_MAX_ORDER_LPC ],         /* I   Prediction coefficients                                  */
+    const opus_int       order                               /* I   Prediction order                                         */
+)
+{
+    opus_int   k, n, mult2Q;
+    opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
+    opus_int32 max, min;
+    int32x4_t  max_s32x4, min_s32x4;
+    int32x2_t  max_s32x2, min_s32x2;
+
+    max_s32x4 = vdupq_n_s32( silk_int32_MIN );
+    min_s32x4 = vdupq_n_s32( silk_int32_MAX );
+    invGain_Q30 = SILK_FIX_CONST( 1, 30 );
+    for( k = order - 1; k > 0; k-- ) {
+        int32x2_t rc_Q31_s32x2, rc_mult2_s32x2;
+        int64x2_t mult2Q_s64x2;
+
+        /* Check for stability */
+        if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+            return 0;
+        }
+
+        /* Set RC equal to negated AR coef */
+        rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
+
+        /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
+        rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), 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 ) );
+
+        /* 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 ) );
+        if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+            return 0;
+        }
+
+        /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
+        mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
+        rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
+
+        /* Update AR coefficient */
+        rc_Q31_s32x2   = vdup_n_s32( rc_Q31 );
+        mult2Q_s64x2   = vdupq_n_s64( -mult2Q );
+        rc_mult2_s32x2 = vdup_n_s32( rc_mult2 );
+
+        for( n = 0; n < ( ( k + 1 ) >> 1 ) - 3; n += 4 ) {
+            /* We always calculate extra elements of A_QA buffer when ( k % 4 ) != 0, to take the advantage of SIMD parallelization. */
+            int32x4_t tmp1_s32x4, tmp2_s32x4, t0_s32x4, t1_s32x4, s0_s32x4, s1_s32x4, t_QA0_s32x4, t_QA1_s32x4;
+            int64x2_t t0_s64x2, t1_s64x2, t2_s64x2, t3_s64x2;
+            tmp1_s32x4  = vld1q_s32( A_QA + n );
+            tmp2_s32x4  = vld1q_s32( A_QA + k - n - 4 );
+            tmp2_s32x4  = vrev64q_s32( tmp2_s32x4 );
+            tmp2_s32x4  = vcombine_s32( vget_high_s32( tmp2_s32x4 ), vget_low_s32( tmp2_s32x4 ) );
+            t0_s32x4    = vqrdmulhq_lane_s32( tmp2_s32x4, rc_Q31_s32x2, 0 );
+            t1_s32x4    = vqrdmulhq_lane_s32( tmp1_s32x4, rc_Q31_s32x2, 0 );
+            t_QA0_s32x4 = vqsubq_s32( tmp1_s32x4, t0_s32x4 );
+            t_QA1_s32x4 = vqsubq_s32( tmp2_s32x4, t1_s32x4 );
+            t0_s64x2    = vmull_s32( vget_low_s32 ( t_QA0_s32x4 ), rc_mult2_s32x2 );
+            t1_s64x2    = vmull_s32( vget_high_s32( t_QA0_s32x4 ), rc_mult2_s32x2 );
+            t2_s64x2    = vmull_s32( vget_low_s32 ( t_QA1_s32x4 ), rc_mult2_s32x2 );
+            t3_s64x2    = vmull_s32( vget_high_s32( t_QA1_s32x4 ), rc_mult2_s32x2 );
+            t0_s64x2    = vrshlq_s64( t0_s64x2, mult2Q_s64x2 );
+            t1_s64x2    = vrshlq_s64( t1_s64x2, mult2Q_s64x2 );
+            t2_s64x2    = vrshlq_s64( t2_s64x2, mult2Q_s64x2 );
+            t3_s64x2    = vrshlq_s64( t3_s64x2, mult2Q_s64x2 );
+            t0_s32x4    = vcombine_s32( vmovn_s64( t0_s64x2 ), vmovn_s64( t1_s64x2 ) );
+            t1_s32x4    = vcombine_s32( vmovn_s64( t2_s64x2 ), vmovn_s64( t3_s64x2 ) );
+            s0_s32x4    = vcombine_s32( vshrn_n_s64( t0_s64x2, 31 ), vshrn_n_s64( t1_s64x2, 31 ) );
+            s1_s32x4    = vcombine_s32( vshrn_n_s64( t2_s64x2, 31 ), vshrn_n_s64( t3_s64x2, 31 ) );
+            max_s32x4   = vmaxq_s32( max_s32x4, s0_s32x4 );
+            min_s32x4   = vminq_s32( min_s32x4, s0_s32x4 );
+            max_s32x4   = vmaxq_s32( max_s32x4, s1_s32x4 );
+            min_s32x4   = vminq_s32( min_s32x4, s1_s32x4 );
+            t1_s32x4    = vrev64q_s32( t1_s32x4 );
+            t1_s32x4    = vcombine_s32( vget_high_s32( t1_s32x4 ), vget_low_s32( t1_s32x4 ) );
+            vst1q_s32( A_QA + n,         t0_s32x4 );
+            vst1q_s32( A_QA + k - n - 4, t1_s32x4 );
+        }
+        for( ; n < (k + 1) >> 1; n++ ) {
+            opus_int64 tmp64;
+            tmp1 = A_QA[ n ];
+            tmp2 = A_QA[ k - n - 1 ];
+            tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
+                  MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
+            if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+               return 0;
+            }
+            A_QA[ n ] = ( opus_int32 )tmp64;
+            tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
+                  MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
+            if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+               return 0;
+            }
+            A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
+        }
+    }
+
+    /* Check for stability */
+    if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
+        return 0;
+    }
+
+    max_s32x2 = vmax_s32( vget_low_s32( max_s32x4 ), vget_high_s32( max_s32x4 ) );
+    min_s32x2 = vmin_s32( vget_low_s32( min_s32x4 ), vget_high_s32( min_s32x4 ) );
+    max_s32x2 = vmax_s32( max_s32x2, vreinterpret_s32_s64( vshr_n_s64( vreinterpret_s64_s32( max_s32x2 ), 32 ) ) );
+    min_s32x2 = vmin_s32( min_s32x2, vreinterpret_s32_s64( vshr_n_s64( vreinterpret_s64_s32( min_s32x2 ), 32 ) ) );
+    max = vget_lane_s32( max_s32x2, 0 );
+    min = vget_lane_s32( min_s32x2, 0 );
+    if( ( max > 0 ) || ( min < -1 ) ) {
+        return 0;
+    }
+
+    /* Set RC equal to negated AR coef */
+    rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
+
+    /* Range: [ 1 : 2^30 ] */
+    rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), 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 ) );
+    if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+        return 0;
+    }
+
+    return invGain_Q30;
+}
+
+/* For input in Q12 domain */
+opus_int32 silk_LPC_inverse_pred_gain_neon(         /* O   Returns inverse prediction gain in energy domain, Q30        */
+    const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
+    const opus_int              order               /* I   Prediction order                                             */
+)
+{
+#ifdef OPUS_CHECK_ASM
+    const opus_int32 invGain_Q30_c = silk_LPC_inverse_pred_gain_c( A_Q12, order );
+#endif
+
+    opus_int32 invGain_Q30;
+    if( ( SILK_MAX_ORDER_LPC != 24 ) || ( order & 1 )) {
+        invGain_Q30 = silk_LPC_inverse_pred_gain_c( A_Q12, order );
+    }
+    else {
+        opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
+        opus_int32 DC_resp;
+        int16x8_t  t0_s16x8, t1_s16x8, t2_s16x8;
+        int32x4_t  t0_s32x4;
+        const opus_int leftover = order & 7;
+
+        /* Increase Q domain of the AR coefficients */
+        t0_s16x8 = vld1q_s16( A_Q12 +  0 );
+        t1_s16x8 = vld1q_s16( A_Q12 +  8 );
+        t2_s16x8 = vld1q_s16( A_Q12 + 16 );
+        t0_s32x4 = vpaddlq_s16( t0_s16x8 );
+
+        switch( order - leftover )
+        {
+        case 24:
+            t0_s32x4 = vpadalq_s16( t0_s32x4, t2_s16x8 );
+            /* Intend to fall through */
+
+        case 16:
+            t0_s32x4 = vpadalq_s16( t0_s32x4, t1_s16x8 );
+            vst1q_s32( Atmp_QA + 16, vshll_n_s16( vget_low_s16 ( t2_s16x8 ), QA - 12 ) );
+            vst1q_s32( Atmp_QA + 20, vshll_n_s16( vget_high_s16( t2_s16x8 ), QA - 12 ) );
+            /* Intend to fall through */
+
+        case 8:
+        {
+            const int32x2_t t_s32x2 = vpadd_s32( vget_low_s32( t0_s32x4 ), vget_high_s32( t0_s32x4 ) );
+            const int64x1_t t_s64x1 = vpaddl_s32( t_s32x2 );
+            DC_resp = vget_lane_s32( vreinterpret_s32_s64( t_s64x1 ), 0 );
+            vst1q_s32( Atmp_QA +  8, vshll_n_s16( vget_low_s16 ( t1_s16x8 ), QA - 12 ) );
+            vst1q_s32( Atmp_QA + 12, vshll_n_s16( vget_high_s16( t1_s16x8 ), QA - 12 ) );
+        }
+        break;
+
+        default:
+            DC_resp = 0;
+            break;
+        }
+        A_Q12 += order - leftover;
+
+        switch( leftover )
+        {
+        case 6:
+            DC_resp += (opus_int32)A_Q12[ 5 ];
+            DC_resp += (opus_int32)A_Q12[ 4 ];
+            /* Intend to fall through */
+
+        case 4:
+            DC_resp += (opus_int32)A_Q12[ 3 ];
+            DC_resp += (opus_int32)A_Q12[ 2 ];
+            /* Intend to fall through */
+
+        case 2:
+            DC_resp += (opus_int32)A_Q12[ 1 ];
+            DC_resp += (opus_int32)A_Q12[ 0 ];
+            /* Intend to fall through */
+
+        default:
+            break;
+        }
+
+        /* If the DC is unstable, we don't even need to do the full calculations */
+        if( DC_resp >= 4096 ) {
+            invGain_Q30 = 0;
+        } else {
+            vst1q_s32( Atmp_QA + 0, vshll_n_s16( vget_low_s16 ( t0_s16x8 ), QA - 12 ) );
+            vst1q_s32( Atmp_QA + 4, vshll_n_s16( vget_high_s16( t0_s16x8 ), QA - 12 ) );
+            invGain_Q30 = LPC_inverse_pred_gain_QA_neon( Atmp_QA, order );
+        }
+    }
+
+#ifdef OPUS_CHECK_ASM
+    silk_assert( invGain_Q30_c == invGain_Q30 );
+#endif
+
+    return invGain_Q30;
+}
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/arm/NSQ_del_dec_arm.h
@@ -0,0 +1,100 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_NSQ_DEL_DEC_ARM_H
+#define SILK_NSQ_DEL_DEC_ARM_H
+
+#include "celt/arm/armcpu.h"
+
+#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_NSQ_del_dec_neon(
+    const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
+    SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
+    const opus_int16 PredCoef_Q12[2 * MAX_LPC_ORDER],
+    const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
+    const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
+    const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
+    const opus_int Tilt_Q14[MAX_NB_SUBFR],
+    const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
+    const opus_int32 Gains_Q16[MAX_NB_SUBFR],
+    const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
+    const opus_int LTP_scale_Q14);
+
+#if !defined(OPUS_HAVE_RTCD)
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12,  \
+                         LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14,   \
+                         LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10,          \
+                         LTP_scale_Q14, arch)                                \
+    ((void)(arch),                                                           \
+     PRESUME_NEON(silk_NSQ_del_dec)(                                         \
+         psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14,     \
+         AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
+         Lambda_Q10, LTP_scale_Q14))
+#endif
+#endif
+
+#if !defined(OVERRIDE_silk_NSQ_del_dec)
+/*Is run-time CPU detection enabled on this platform?*/
+#if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
+                                !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+    const silk_encoder_state *psEncC, silk_nsq_state *NSQ,
+    SideInfoIndices *psIndices, const opus_int16 x16[], opus_int8 pulses[],
+    const opus_int16 PredCoef_Q12[2 * MAX_LPC_ORDER],
+    const opus_int16 LTPCoef_Q14[LTP_ORDER * MAX_NB_SUBFR],
+    const opus_int16 AR_Q13[MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER],
+    const opus_int HarmShapeGain_Q14[MAX_NB_SUBFR],
+    const opus_int Tilt_Q14[MAX_NB_SUBFR],
+    const opus_int32 LF_shp_Q14[MAX_NB_SUBFR],
+    const opus_int32 Gains_Q16[MAX_NB_SUBFR],
+    const opus_int pitchL[MAX_NB_SUBFR], const opus_int Lambda_Q10,
+    const opus_int LTP_scale_Q14);
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+                         LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14,  \
+                         LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10,         \
+                         LTP_scale_Q14, arch)                               \
+    ((*SILK_NSQ_DEL_DEC_IMPL[(arch)&OPUS_ARCHMASK])(                        \
+        psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14,     \
+        AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, \
+        Lambda_Q10, LTP_scale_Q14))
+#elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#define OVERRIDE_silk_NSQ_del_dec (1)
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12,   \
+                         LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14,    \
+                         LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10,           \
+                         LTP_scale_Q14, arch)                                 \
+    ((void)(arch),                                                            \
+     silk_NSQ_del_dec_neon(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, \
+                           LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14,  \
+                           LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10,         \
+                           LTP_scale_Q14))
+#endif
+#endif
+
+#endif /* end SILK_NSQ_DEL_DEC_ARM_H */
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/arm/NSQ_del_dec_neon_intr.c
@@ -0,0 +1,1124 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <arm_neon.h>
+#ifdef OPUS_CHECK_ASM
+# include <string.h>
+#endif
+#include "main.h"
+#include "stack_alloc.h"
+
+/* NEON intrinsics optimization now can only parallelize up to 4 delay decision states.    */
+/* If there are more states, C function is called, and this optimization must be expanded. */
+#define NEON_MAX_DEL_DEC_STATES 4
+
+typedef struct {
+    opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ][ NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 RandState[ DECISION_DELAY ][     NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 Q_Q10[     DECISION_DELAY ][     NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 Xq_Q14[    DECISION_DELAY ][     NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 Pred_Q15[  DECISION_DELAY ][     NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 Shape_Q14[ DECISION_DELAY ][     NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ][ NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 LF_AR_Q14[ NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 Diff_Q14[  NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 Seed[      NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 SeedInit[  NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 RD_Q10[    NEON_MAX_DEL_DEC_STATES ];
+} NSQ_del_decs_struct;
+
+typedef struct {
+    opus_int32 Q_Q10[        NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 RD_Q10[       NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 xq_Q14[       NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 LF_AR_Q14[    NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 Diff_Q14[     NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 sLTP_shp_Q14[ NEON_MAX_DEL_DEC_STATES ];
+    opus_int32 LPC_exc_Q14[  NEON_MAX_DEL_DEC_STATES ];
+} NSQ_samples_struct;
+
+static OPUS_INLINE void silk_nsq_del_dec_scale_states_neon(
+    const silk_encoder_state *psEncC,               /* I    Encoder State                       */
+    silk_nsq_state      *NSQ,                       /* I/O  NSQ state                           */
+    NSQ_del_decs_struct psDelDec[],                 /* I/O  Delayed decision states             */
+    const opus_int16    x16[],                      /* I    Input                               */
+    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_Q15[],                 /* O    LTP state matching scaled input     */
+    opus_int            subfr,                      /* I    Subframe number                     */
+    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                           */
+    const opus_int      signal_type,                /* I    Signal type                         */
+    const opus_int      decisionDelay               /* I    Decision delay                      */
+);
+
+/******************************************/
+/* Noise shape quantizer for one subframe */
+/******************************************/
+static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_neon(
+    silk_nsq_state      *NSQ,                   /* I/O  NSQ state                           */
+    NSQ_del_decs_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_Q15[],             /* I/O  LTP filter state                    */
+    opus_int32          delayedGain_Q10[],      /* 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/O  Index to newest samples in buffers  */
+    opus_int            decisionDelay           /* I                                        */
+);
+
+static OPUS_INLINE void copy_winner_state_kernel(
+    const NSQ_del_decs_struct *psDelDec,
+    const opus_int            offset,
+    const opus_int            last_smple_idx,
+    const opus_int            Winner_ind,
+    const int32x2_t           gain_lo_s32x2,
+    const int32x2_t           gain_hi_s32x2,
+    const int32x4_t           shift_s32x4,
+    int32x4_t                 t0_s32x4,
+    int32x4_t                 t1_s32x4,
+    opus_int8 *const          pulses,
+    opus_int16                *pxq,
+    silk_nsq_state            *NSQ
+)
+{
+    int16x8_t t_s16x8;
+    int32x4_t o0_s32x4, o1_s32x4;
+
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Q_Q10[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
+    t_s16x8 = vcombine_s16( vrshrn_n_s32( t0_s32x4, 10 ), vrshrn_n_s32( t1_s32x4, 10 ) );
+    vst1_s8( &pulses[ offset ], vmovn_s16( t_s16x8 ) );
+
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Xq_Q14[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
+    o0_s32x4 = vqdmulhq_lane_s32( t0_s32x4, gain_lo_s32x2, 0 );
+    o1_s32x4 = vqdmulhq_lane_s32( t1_s32x4, gain_lo_s32x2, 0 );
+    o0_s32x4 = vmlaq_lane_s32( o0_s32x4, t0_s32x4, gain_hi_s32x2, 0 );
+    o1_s32x4 = vmlaq_lane_s32( o1_s32x4, t1_s32x4, gain_hi_s32x2, 0 );
+    o0_s32x4 = vrshlq_s32( o0_s32x4, shift_s32x4 );
+    o1_s32x4 = vrshlq_s32( o1_s32x4, shift_s32x4 );
+    vst1_s16( &pxq[ offset + 0 ], vqmovn_s32( o0_s32x4 ) );
+    vst1_s16( &pxq[ offset + 4 ], vqmovn_s32( o1_s32x4 ) );
+
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 0 ][ Winner_ind ], t0_s32x4, 0 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 1 ][ Winner_ind ], t0_s32x4, 1 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 2 ][ Winner_ind ], t0_s32x4, 2 );
+    t0_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 3 ][ Winner_ind ], t0_s32x4, 3 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 4 ][ Winner_ind ], t1_s32x4, 0 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 5 ][ Winner_ind ], t1_s32x4, 1 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 6 ][ Winner_ind ], t1_s32x4, 2 );
+    t1_s32x4 = vld1q_lane_s32( &psDelDec->Shape_Q14[ last_smple_idx - 7 ][ Winner_ind ], t1_s32x4, 3 );
+    vst1q_s32( &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx + offset + 0 ], t0_s32x4 );
+    vst1q_s32( &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx + offset + 4 ], t1_s32x4 );
+}
+
+static OPUS_INLINE void copy_winner_state(
+    const NSQ_del_decs_struct *psDelDec,
+    const opus_int            decisionDelay,
+    const opus_int            smpl_buf_idx,
+    const opus_int            Winner_ind,
+    const opus_int32          gain,
+    const opus_int32          shift,
+    opus_int8 *const          pulses,
+    opus_int16                *pxq,
+    silk_nsq_state            *NSQ
+)
+{
+    opus_int        i, last_smple_idx;
+    const int32x2_t gain_lo_s32x2 = vdup_n_s32( silk_LSHIFT32( gain & 0x0000FFFF, 15 ) );
+    const int32x2_t gain_hi_s32x2 = vdup_n_s32( gain >> 16 );
+    const int32x4_t shift_s32x4 = vdupq_n_s32( -shift );
+    int32x4_t       t0_s32x4, t1_s32x4;
+
+    t0_s32x4 = t1_s32x4 = vdupq_n_s32( 0 ); /* initialization */
+    last_smple_idx = smpl_buf_idx + decisionDelay - 1 + DECISION_DELAY;
+    if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
+    if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
+
+    for( i = 0; ( i < ( decisionDelay - 7 ) ) && ( last_smple_idx >= 7 ); i += 8, last_smple_idx -= 8 ) {
+        copy_winner_state_kernel( psDelDec, i - decisionDelay, last_smple_idx, Winner_ind, gain_lo_s32x2, gain_hi_s32x2, shift_s32x4, t0_s32x4, t1_s32x4, pulses, pxq, NSQ );
+    }
+    for( ; ( i < decisionDelay ) && ( last_smple_idx >= 0 ); i++, last_smple_idx-- ) {
+        pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
+        pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], gain ), shift ) );
+        NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
+    }
+
+    last_smple_idx += DECISION_DELAY;
+    for( ; i < ( decisionDelay - 7 ); i++, last_smple_idx-- ) {
+        copy_winner_state_kernel( psDelDec, i - decisionDelay, last_smple_idx, Winner_ind, gain_lo_s32x2, gain_hi_s32x2, shift_s32x4, t0_s32x4, t1_s32x4, pulses, pxq, NSQ );
+    }
+    for( ; i < decisionDelay; i++, last_smple_idx-- ) {
+        pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
+        pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], gain ), shift ) );
+        NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
+    }
+}
+
+void silk_NSQ_del_dec_neon(
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
+    silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
+    SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
+    const opus_int16            x16[],                                      /* I    Input                           */
+    opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
+    const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
+    const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs              */
+    const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
+    const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                   /* I    Spectral tilt                   */
+    const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                 /* I    Low frequency shaping coefs     */
+    const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                  /* I    Quantization step sizes         */
+    const opus_int              pitchL[ MAX_NB_SUBFR ],                     /* I    Pitch lags                      */
+    const opus_int              Lambda_Q10,                                 /* I    Rate/distortion tradeoff        */
+    const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
+)
+{
+#ifdef OPUS_CHECK_ASM
+    silk_nsq_state NSQ_c;
+    SideInfoIndices psIndices_c;
+    opus_int8 pulses_c[ MAX_FRAME_LENGTH ];
+    const opus_int8 *const pulses_a = pulses;
+
+    ( void )pulses_a;
+    silk_memcpy( &NSQ_c, NSQ, sizeof( NSQ_c ) );
+    silk_memcpy( &psIndices_c, psIndices, sizeof( psIndices_c ) );
+    silk_memcpy( pulses_c, pulses, sizeof( pulses_c ) );
+    silk_NSQ_del_dec_c( psEncC, &NSQ_c, &psIndices_c, x16, pulses_c, PredCoef_Q12, LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16,
+                       pitchL, Lambda_Q10, LTP_scale_Q14 );
+#endif
+
+    /* The optimization parallelizes the different delay decision states. */
+    if(( psEncC->nStatesDelayedDecision > NEON_MAX_DEL_DEC_STATES ) || ( psEncC->nStatesDelayedDecision <= 2 )) {
+        /* NEON intrinsics optimization now can only parallelize up to 4 delay decision states.    */
+        /* If there are more states, C function is called, and this optimization must be expanded. */
+        /* When the number of delay decision states is less than 3, there are penalties using this */
+        /* optimization, and C function is called.                                                 */
+        /* When the number of delay decision states is 2, it's better to specialize another        */
+        /* structure NSQ_del_dec2_struct and optimize with shorter NEON registers. (Low priority)  */
+        silk_NSQ_del_dec_c( psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, HarmShapeGain_Q14,
+            Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14 );
+    } else {
+        opus_int            i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
+        opus_int            smpl_buf_idx, decisionDelay;
+        const opus_int16    *A_Q12, *B_Q14, *AR_shp_Q13;
+        opus_int16          *pxq;
+        VARDECL( opus_int32, sLTP_Q15 );
+        VARDECL( opus_int16, sLTP );
+        opus_int32          HarmShapeFIRPacked_Q14;
+        opus_int            offset_Q10;
+        opus_int32          RDmin_Q10, Gain_Q10;
+        VARDECL( opus_int32, x_sc_Q10 );
+        VARDECL( opus_int32, delayedGain_Q10 );
+        VARDECL( NSQ_del_decs_struct, psDelDec );
+        int32x4_t           t_s32x4;
+        SAVE_STACK;
+
+        /* Set unvoiced lag to the previous one, overwrite later for voiced */
+        lag = NSQ->lagPrev;
+
+        silk_assert( NSQ->prev_gain_Q16 != 0 );
+
+        /* Initialize delayed decision states */
+        ALLOC( psDelDec, 1, NSQ_del_decs_struct );
+        /* Only RandState and RD_Q10 need to be initialized to 0. */
+        silk_memset( psDelDec->RandState, 0, sizeof( psDelDec->RandState ) );
+        vst1q_s32( psDelDec->RD_Q10, vdupq_n_s32( 0 ) );
+
+        for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
+            psDelDec->SeedInit[ k ] = psDelDec->Seed[ k ] = ( k + psIndices->Seed ) & 3;
+        }
+        vst1q_s32( psDelDec->LF_AR_Q14, vld1q_dup_s32( &NSQ->sLF_AR_shp_Q14 ) );
+        vst1q_s32( psDelDec->Diff_Q14, vld1q_dup_s32( &NSQ->sDiff_shp_Q14 ) );
+        vst1q_s32( psDelDec->Shape_Q14[ 0 ], vld1q_dup_s32( &NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ] ) );
+        for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+            vst1q_s32( psDelDec->sLPC_Q14[ i ], vld1q_dup_s32( &NSQ->sLPC_Q14[ i ] ) );
+        }
+        for( i = 0; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) ); i++ ) {
+            vst1q_s32( psDelDec->sAR2_Q14[ i ], vld1q_dup_s32( &NSQ->sAR2_Q14[ i ] ) );
+        }
+
+        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 ) {
+            opus_int pitch_min = pitchL[ 0 ];
+            for( k = 1; k < psEncC->nb_subfr; k++ ) {
+                pitch_min = silk_min_int( pitch_min, pitchL[ k ] );
+            }
+            decisionDelay = silk_min_int( decisionDelay, pitch_min - 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;
+        }
+
+        ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
+        ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
+        ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
+        ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
+        /* Set up pointers to start of sub frame */
+        pxq                   = &NSQ->xq[ psEncC->ltp_mem_length ];
+        NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
+        NSQ->sLTP_buf_idx     = psEncC->ltp_mem_length;
+        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 = &AR_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 */
+                        int32x4_t RD_Q10_s32x4;
+                        RDmin_Q10 = psDelDec->RD_Q10[ 0 ];
+                        Winner_ind = 0;
+                        for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) {
+                            if( psDelDec->RD_Q10[ i ] < RDmin_Q10 ) {
+                                RDmin_Q10 = psDelDec->RD_Q10[ i ];
+                                Winner_ind = i;
+                            }
+                        }
+                        psDelDec->RD_Q10[ Winner_ind ] -= ( silk_int32_MAX >> 4 );
+                        RD_Q10_s32x4 = vld1q_s32( psDelDec->RD_Q10 );
+                        RD_Q10_s32x4 = vaddq_s32( RD_Q10_s32x4, vdupq_n_s32( silk_int32_MAX >> 4 ) );
+                        vst1q_s32( psDelDec->RD_Q10, RD_Q10_s32x4 );
+
+                        /* Copy final part of signals from winner state to output and long-term filter states */
+                        copy_winner_state( psDelDec, decisionDelay, smpl_buf_idx, Winner_ind, Gains_Q16[ 1 ], 14, pulses, pxq, NSQ );
+
+                        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, psEncC->arch );
+
+                    NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
+                    NSQ->rewhite_flag = 1;
+                }
+            }
+
+            silk_nsq_del_dec_scale_states_neon( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
+                LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
+
+            silk_noise_shape_quantizer_del_dec_neon( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
+                delayedGain_Q10, 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 );
+
+            x16    += psEncC->subfr_length;
+            pulses += psEncC->subfr_length;
+            pxq    += psEncC->subfr_length;
+        }
+
+        /* Find winner */
+        RDmin_Q10 = psDelDec->RD_Q10[ 0 ];
+        Winner_ind = 0;
+        for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) {
+            if( psDelDec->RD_Q10[ k ] < RDmin_Q10 ) {
+                RDmin_Q10 = psDelDec->RD_Q10[ k ];
+                Winner_ind = k;
+            }
+        }
+
+        /* Copy final part of signals from winner state to output and long-term filter states */
+        psIndices->Seed = psDelDec->SeedInit[ Winner_ind ];
+        Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
+        copy_winner_state( psDelDec, decisionDelay, smpl_buf_idx, Winner_ind, Gain_Q10, 8, pulses, pxq, NSQ );
+
+        t_s32x4 = vdupq_n_s32( 0 ); /* initialization */
+        for( i = 0; i < ( NSQ_LPC_BUF_LENGTH - 3 ); i += 4 ) {
+            t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 0 ][ Winner_ind ], t_s32x4, 0 );
+            t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 1 ][ Winner_ind ], t_s32x4, 1 );
+            t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 2 ][ Winner_ind ], t_s32x4, 2 );
+            t_s32x4 = vld1q_lane_s32( &psDelDec->sLPC_Q14[ i + 3 ][ Winner_ind ], t_s32x4, 3 );
+            vst1q_s32( &NSQ->sLPC_Q14[ i ], t_s32x4 );
+        }
+
+        for( ; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+          NSQ->sLPC_Q14[ i ] = psDelDec->sLPC_Q14[ i ][ Winner_ind ];
+        }
+
+        for( i = 0; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) - 3 ); i += 4 ) {
+            t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 0 ][ Winner_ind ], t_s32x4, 0 );
+            t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 1 ][ Winner_ind ], t_s32x4, 1 );
+            t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 2 ][ Winner_ind ], t_s32x4, 2 );
+            t_s32x4 = vld1q_lane_s32( &psDelDec->sAR2_Q14[ i + 3 ][ Winner_ind ], t_s32x4, 3 );
+            vst1q_s32( &NSQ->sAR2_Q14[ i ], t_s32x4 );
+        }
+
+        for( ; i < (opus_int)( sizeof( NSQ->sAR2_Q14 ) / sizeof( NSQ->sAR2_Q14[ 0 ] ) ); i++ ) {
+          NSQ->sAR2_Q14[ i ] = psDelDec->sAR2_Q14[ i ][ Winner_ind ];
+        }
+
+        /* Update states */
+        NSQ->sLF_AR_shp_Q14 = psDelDec->LF_AR_Q14[ Winner_ind ];
+        NSQ->sDiff_shp_Q14  = psDelDec->Diff_Q14[ Winner_ind ];
+        NSQ->lagPrev        = pitchL[ psEncC->nb_subfr - 1 ];
+
+        /* Save quantized speech signal */
+        silk_memmove( NSQ->xq,           &NSQ->xq[           psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
+        silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
+        RESTORE_STACK;
+    }
+
+#ifdef OPUS_CHECK_ASM
+    silk_assert( !memcmp( &NSQ_c, NSQ, sizeof( NSQ_c ) ) );
+    silk_assert( !memcmp( &psIndices_c, psIndices, sizeof( psIndices_c ) ) );
+    silk_assert( !memcmp( pulses_c, pulses_a, sizeof( pulses_c ) ) );
+#endif
+}
+
+/******************************************/
+/* Noise shape quantizer for one subframe */
+/******************************************/
+/* Note: Function silk_short_prediction_create_arch_coef_neon() defined in NSQ_neon.h is actually a hacking C function. */
+/*       Therefore here we append "_local" to the NEON function name to avoid confusion.                                */
+static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon_local(opus_int32 *out, const opus_int16 *in, opus_int order)
+{
+  int16x8_t t_s16x8;
+  int32x4_t t0_s32x4, t1_s32x4, t2_s32x4, t3_s32x4;
+  silk_assert( order == 10 || order == 16 );
+
+  t_s16x8 = vld1q_s16( in + 0 );                                                   /* 7 6 5 4  3 2 1 0    */
+  t_s16x8 = vrev64q_s16( t_s16x8 );                                                /* 4 5 6 7  0 1 2 3    */
+  t2_s32x4 = vshll_n_s16( vget_high_s16( t_s16x8 ), 15 );                          /* 4 5 6 7             */
+  t3_s32x4 = vshll_n_s16( vget_low_s16(  t_s16x8 ), 15 );                          /* 0 1 2 3             */
+
+  if( order == 16 ) {
+      t_s16x8 = vld1q_s16( in + 8 );                                               /* F E D C  B A 9 8    */
+      t_s16x8 = vrev64q_s16( t_s16x8 );                                            /* C D E F  8 9 A B    */
+      t0_s32x4 = vshll_n_s16( vget_high_s16( t_s16x8 ), 15 );                      /* C D E F             */
+      t1_s32x4 = vshll_n_s16( vget_low_s16(  t_s16x8 ), 15 );                      /* 8 9 A B             */
+  } else {
+      int16x4_t t_s16x4;
+
+      t0_s32x4 = vdupq_n_s32( 0 );                                                 /* zero zero zero zero */
+      t_s16x4 = vld1_s16( in + 6 );                                                /* 9    8    7    6    */
+      t_s16x4 = vrev64_s16( t_s16x4 );                                             /* 6    7    8    9    */
+      t1_s32x4 = vshll_n_s16( t_s16x4, 15 );
+      t1_s32x4 = vcombine_s32( vget_low_s32(t0_s32x4), vget_low_s32( t1_s32x4 ) ); /* 8    9    zero zero */
+  }
+  vst1q_s32( out +  0, t0_s32x4 );
+  vst1q_s32( out +  4, t1_s32x4 );
+  vst1q_s32( out +  8, t2_s32x4 );
+  vst1q_s32( out + 12, t3_s32x4 );
+}
+
+static OPUS_INLINE int32x4_t silk_SMLAWB_lane0_neon(
+    const int32x4_t out_s32x4,
+    const int32x4_t in_s32x4,
+    const int32x2_t coef_s32x2
+)
+{
+    return vaddq_s32( out_s32x4, vqdmulhq_lane_s32( in_s32x4, coef_s32x2, 0 ) );
+}
+
+static OPUS_INLINE int32x4_t silk_SMLAWB_lane1_neon(
+    const int32x4_t out_s32x4,
+    const int32x4_t in_s32x4,
+    const int32x2_t coef_s32x2
+)
+{
+    return vaddq_s32( out_s32x4, vqdmulhq_lane_s32( in_s32x4, coef_s32x2, 1 ) );
+}
+
+/* Note: This function has different return value than silk_noise_shape_quantizer_short_prediction_neon(). */
+/*       Therefore here we append "_local" to the function name to avoid confusion.                        */
+static OPUS_INLINE int32x4_t silk_noise_shape_quantizer_short_prediction_neon_local(const opus_int32 *buf32, const opus_int32 *a_Q12_arch, opus_int order)
+{
+    const int32x4_t a_Q12_arch0_s32x4 = vld1q_s32( a_Q12_arch + 0 );
+    const int32x4_t a_Q12_arch1_s32x4 = vld1q_s32( a_Q12_arch + 4 );
+    const int32x4_t a_Q12_arch2_s32x4 = vld1q_s32( a_Q12_arch + 8 );
+    const int32x4_t a_Q12_arch3_s32x4 = vld1q_s32( a_Q12_arch + 12 );
+    int32x4_t LPC_pred_Q14_s32x4;
+
+    silk_assert( order == 10 || order == 16 );
+    /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+    LPC_pred_Q14_s32x4 = vdupq_n_s32( silk_RSHIFT( order, 1 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  0 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32(  a_Q12_arch0_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  1 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32(  a_Q12_arch0_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  2 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch0_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  3 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch0_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  4 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32(  a_Q12_arch1_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  5 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32(  a_Q12_arch1_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  6 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch1_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  7 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch1_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  8 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32(  a_Q12_arch2_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 +  9 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32(  a_Q12_arch2_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 10 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch2_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 11 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch2_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 12 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32(  a_Q12_arch3_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 13 * NEON_MAX_DEL_DEC_STATES ), vget_low_s32(  a_Q12_arch3_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane0_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 14 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch3_s32x4 ) );
+    LPC_pred_Q14_s32x4 = silk_SMLAWB_lane1_neon( LPC_pred_Q14_s32x4, vld1q_s32( buf32 + 15 * NEON_MAX_DEL_DEC_STATES ), vget_high_s32( a_Q12_arch3_s32x4 ) );
+
+    return LPC_pred_Q14_s32x4;
+}
+
+static OPUS_INLINE void silk_noise_shape_quantizer_del_dec_neon(
+    silk_nsq_state      *NSQ,                   /* I/O  NSQ state                           */
+    NSQ_del_decs_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_Q15[],             /* I/O  LTP filter state                    */
+    opus_int32          delayedGain_Q10[],      /* 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/O  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, n_LTP_Q14;
+    opus_int32   RDmin_Q10, RDmax_Q10;
+    opus_int32   Gain_Q10;
+    opus_int32   *pred_lag_ptr, *shp_lag_ptr;
+    opus_int32   a_Q12_arch[MAX_LPC_ORDER];
+    const int32x2_t warping_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( warping_Q16, 16 ) >> 1 );
+    const opus_int32 LF_shp_Q29 = silk_LSHIFT32( LF_shp_Q14, 16 ) >> 1;
+    opus_int32 AR_shp_Q28[ MAX_SHAPE_LPC_ORDER ];
+    const uint32x4_t rand_multiplier_u32x4 = vdupq_n_u32( RAND_MULTIPLIER );
+    const uint32x4_t rand_increment_u32x4 = vdupq_n_u32( RAND_INCREMENT );
+
+    VARDECL( NSQ_samples_struct, psSampleState );
+    SAVE_STACK;
+
+    silk_assert( nStatesDelayedDecision > 0 );
+    silk_assert( ( shapingLPCOrder & 1 ) == 0 );   /* check that order is even */
+    ALLOC( psSampleState, 2, NSQ_samples_struct );
+
+    shp_lag_ptr  = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
+    pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
+    Gain_Q10     = silk_RSHIFT( Gain_Q16, 6 );
+
+    for( i = 0; i < ( MAX_SHAPE_LPC_ORDER - 7 ); i += 8 ) {
+      const int16x8_t t_s16x8 = vld1q_s16( AR_shp_Q13 +  i );
+      vst1q_s32( AR_shp_Q28 + i + 0, vshll_n_s16( vget_low_s16(  t_s16x8 ), 15 ) );
+      vst1q_s32( AR_shp_Q28 + i + 4, vshll_n_s16( vget_high_s16( t_s16x8 ), 15 ) );
+    }
+
+    for( ; i < MAX_SHAPE_LPC_ORDER; i++ ) {
+      AR_shp_Q28[i] = silk_LSHIFT32( AR_shp_Q13[i], 15 );
+    }
+
+    silk_short_prediction_create_arch_coef_neon_local( a_Q12_arch, a_Q12, predictLPCOrder );
+
+    for( i = 0; i < length; i++ ) {
+        int32x4_t Seed_s32x4, LPC_pred_Q14_s32x4;
+        int32x4_t sign_s32x4, tmp1_s32x4, tmp2_s32x4;
+        int32x4_t n_AR_Q14_s32x4, n_LF_Q14_s32x4;
+        int32x2_t AR_shp_Q28_s32x2;
+        int16x4_t r_Q10_s16x4, rr_Q10_s16x4;
+
+        /* Perform common calculations used in all states */
+
+        /* Long-term prediction */
+        if( signalType == TYPE_VOICED ) {
+            /* Unrolled loop */
+            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
+            LTP_pred_Q14 = 2;
+            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[  0 ], b_Q14[ 0 ] );
+            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
+            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
+            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
+            LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
+            LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 );                          /* Q13 -> Q14 */
+            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_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 );            /* Q12 -> Q14 */
+            shp_lag_ptr++;
+        } else {
+            n_LTP_Q14 = 0;
+        }
+
+        /* Generate dither */
+        Seed_s32x4 = vld1q_s32( psDelDec->Seed );
+        Seed_s32x4 = vreinterpretq_s32_u32( vmlaq_u32( rand_increment_u32x4, vreinterpretq_u32_s32( Seed_s32x4 ), rand_multiplier_u32x4 ) );
+        vst1q_s32( psDelDec->Seed, Seed_s32x4 );
+
+        /* Short-term prediction */
+        LPC_pred_Q14_s32x4 = silk_noise_shape_quantizer_short_prediction_neon_local(psDelDec->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 16 + i ], a_Q12_arch, predictLPCOrder);
+        LPC_pred_Q14_s32x4 = vshlq_n_s32( LPC_pred_Q14_s32x4, 4 ); /* Q10 -> Q14 */
+
+        /* Noise shape feedback */
+        /* Output of lowpass section */
+        tmp2_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->Diff_Q14 ), vld1q_s32( psDelDec->sAR2_Q14[ 0 ] ), warping_Q16_s32x2 );
+        /* Output of allpass section */
+        tmp1_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ 1 ] ), tmp2_s32x4 );
+        tmp1_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ 0 ] ), tmp1_s32x4, warping_Q16_s32x2 );
+        vst1q_s32( psDelDec->sAR2_Q14[ 0 ], tmp2_s32x4 );
+        AR_shp_Q28_s32x2 = vld1_s32( AR_shp_Q28 );
+        n_AR_Q14_s32x4 = vaddq_s32( vdupq_n_s32( silk_RSHIFT( shapingLPCOrder, 1 ) ), vqdmulhq_lane_s32( tmp2_s32x4, AR_shp_Q28_s32x2, 0 ) );
+
+        /* Loop over allpass sections */
+        for( j = 2; j < shapingLPCOrder; j += 2 ) {
+            /* Output of allpass section */
+            tmp2_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ j + 0 ] ), tmp1_s32x4 );
+            tmp2_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ j - 1 ] ), tmp2_s32x4, warping_Q16_s32x2 );
+            vst1q_s32( psDelDec->sAR2_Q14[ j - 1 ], tmp1_s32x4 );
+            n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp1_s32x4, AR_shp_Q28_s32x2, 1 ) );
+            /* Output of allpass section */
+            tmp1_s32x4 = vsubq_s32( vld1q_s32( psDelDec->sAR2_Q14[ j + 1 ] ), tmp2_s32x4 );
+            tmp1_s32x4 = silk_SMLAWB_lane0_neon( vld1q_s32( psDelDec->sAR2_Q14[ j + 0 ] ), tmp1_s32x4, warping_Q16_s32x2 );
+            vst1q_s32( psDelDec->sAR2_Q14[ j + 0 ], tmp2_s32x4 );
+            AR_shp_Q28_s32x2 = vld1_s32( &AR_shp_Q28[ j ] );
+            n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp2_s32x4, AR_shp_Q28_s32x2, 0 ) );
+        }
+        vst1q_s32( psDelDec->sAR2_Q14[ shapingLPCOrder - 1 ], tmp1_s32x4 );
+        n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_lane_s32( tmp1_s32x4, AR_shp_Q28_s32x2, 1 ) );
+        n_AR_Q14_s32x4 = vshlq_n_s32( n_AR_Q14_s32x4, 1 );                                                                                        /* Q11 -> Q12 */
+        n_AR_Q14_s32x4 = vaddq_s32( n_AR_Q14_s32x4, vqdmulhq_n_s32( vld1q_s32( psDelDec->LF_AR_Q14 ), silk_LSHIFT32( Tilt_Q14, 16 ) >> 1 ) );     /* Q12 */
+        n_AR_Q14_s32x4 = vshlq_n_s32( n_AR_Q14_s32x4, 2 );                                                                                        /* Q12 -> Q14 */
+        n_LF_Q14_s32x4 = vqdmulhq_n_s32( vld1q_s32( psDelDec->Shape_Q14[ *smpl_buf_idx ] ), LF_shp_Q29 );                                         /* Q12 */
+        n_LF_Q14_s32x4 = vaddq_s32( n_LF_Q14_s32x4, vqdmulhq_n_s32( vld1q_s32( psDelDec->LF_AR_Q14 ), silk_LSHIFT32( LF_shp_Q14 >> 16 , 15 ) ) ); /* Q12 */
+        n_LF_Q14_s32x4 = vshlq_n_s32( n_LF_Q14_s32x4, 2 );                                                                                        /* Q12 -> Q14 */
+
+        /* Input minus prediction plus noise feedback                       */
+        /* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP  */
+        tmp1_s32x4 = vaddq_s32( n_AR_Q14_s32x4, n_LF_Q14_s32x4 );               /* Q14 */
+        tmp2_s32x4 = vaddq_s32( vdupq_n_s32( n_LTP_Q14 ), LPC_pred_Q14_s32x4 ); /* Q13 */
+        tmp1_s32x4 = vsubq_s32( tmp2_s32x4, tmp1_s32x4 );                       /* Q13 */
+        tmp1_s32x4 = vrshrq_n_s32( tmp1_s32x4, 4 );                             /* Q10 */
+        tmp1_s32x4 = vsubq_s32( vdupq_n_s32( x_Q10[ i ] ), tmp1_s32x4 );        /* residual error Q10 */
+
+        /* Flip sign depending on dither */
+        sign_s32x4 = vreinterpretq_s32_u32( vcltq_s32( Seed_s32x4, vdupq_n_s32( 0 ) ) );
+        tmp1_s32x4 = veorq_s32( tmp1_s32x4, sign_s32x4 );
+        tmp1_s32x4 = vsubq_s32( tmp1_s32x4, sign_s32x4 );
+        tmp1_s32x4 = vmaxq_s32( tmp1_s32x4, vdupq_n_s32( -( 31 << 10 ) ) );
+        tmp1_s32x4 = vminq_s32( tmp1_s32x4, vdupq_n_s32( 30 << 10 ) );
+        r_Q10_s16x4 = vmovn_s32( tmp1_s32x4 );
+
+        /* Find two quantization level candidates and measure their rate-distortion */
+        {
+            int16x4_t q1_Q10_s16x4 = vsub_s16( r_Q10_s16x4, vdup_n_s16( offset_Q10 ) );
+            int16x4_t q1_Q0_s16x4 = vshr_n_s16( q1_Q10_s16x4, 10 );
+            int16x4_t q2_Q10_s16x4;
+            int32x4_t rd1_Q10_s32x4, rd2_Q10_s32x4;
+            uint32x4_t t_u32x4;
+
+            if( Lambda_Q10 > 2048 ) {
+                /* For aggressive RDO, the bias becomes more than one pulse. */
+                const int rdo_offset = Lambda_Q10/2 - 512;
+                const uint16x4_t greaterThanRdo = vcgt_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) );
+                const uint16x4_t lessThanMinusRdo = vclt_s16( q1_Q10_s16x4, vdup_n_s16( -rdo_offset ) );
+                /* If Lambda_Q10 > 32767, then q1_Q0, q1_Q10 and q2_Q10 must change to 32-bit. */
+                silk_assert( Lambda_Q10 <= 32767 );
+
+                q1_Q0_s16x4 = vreinterpret_s16_u16( vclt_s16( q1_Q10_s16x4, vdup_n_s16( 0 ) ) );
+                q1_Q0_s16x4 = vbsl_s16( greaterThanRdo, vsub_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) ), q1_Q0_s16x4 );
+                q1_Q0_s16x4 = vbsl_s16( lessThanMinusRdo, vadd_s16( q1_Q10_s16x4, vdup_n_s16( rdo_offset ) ), q1_Q0_s16x4 );
+                q1_Q0_s16x4 = vshr_n_s16( q1_Q0_s16x4, 10 );
+            }
+            {
+                const uint16x4_t equal0_u16x4 = vceq_s16( q1_Q0_s16x4, vdup_n_s16( 0 ) );
+                const uint16x4_t equalMinus1_u16x4 = vceq_s16( q1_Q0_s16x4, vdup_n_s16( -1 ) );
+                const uint16x4_t lessThanMinus1_u16x4 = vclt_s16( q1_Q0_s16x4, vdup_n_s16( -1 ) );
+                int16x4_t tmp1_s16x4, tmp2_s16x4;
+
+                q1_Q10_s16x4 = vshl_n_s16( q1_Q0_s16x4, 10 );
+                tmp1_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( offset_Q10 - QUANT_LEVEL_ADJUST_Q10 ) );
+                q1_Q10_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( offset_Q10 + QUANT_LEVEL_ADJUST_Q10 ) );
+                q1_Q10_s16x4 = vbsl_s16( lessThanMinus1_u16x4, q1_Q10_s16x4, tmp1_s16x4 );
+                q1_Q10_s16x4 = vbsl_s16( equal0_u16x4, vdup_n_s16( offset_Q10 ), q1_Q10_s16x4 );
+                q1_Q10_s16x4 = vbsl_s16( equalMinus1_u16x4, vdup_n_s16( offset_Q10 - ( 1024 - QUANT_LEVEL_ADJUST_Q10 ) ), q1_Q10_s16x4 );
+                q2_Q10_s16x4 = vadd_s16( q1_Q10_s16x4, vdup_n_s16( 1024 ) );
+                q2_Q10_s16x4 = vbsl_s16( equal0_u16x4, vdup_n_s16( offset_Q10 + 1024 - QUANT_LEVEL_ADJUST_Q10 ), q2_Q10_s16x4 );
+                q2_Q10_s16x4 = vbsl_s16( equalMinus1_u16x4, vdup_n_s16( offset_Q10 ), q2_Q10_s16x4 );
+                tmp1_s16x4 = q1_Q10_s16x4;
+                tmp2_s16x4 = q2_Q10_s16x4;
+                tmp1_s16x4 = vbsl_s16( vorr_u16( equalMinus1_u16x4, lessThanMinus1_u16x4 ), vneg_s16( tmp1_s16x4 ), tmp1_s16x4 );
+                tmp2_s16x4 = vbsl_s16( lessThanMinus1_u16x4, vneg_s16( tmp2_s16x4 ), tmp2_s16x4 );
+                rd1_Q10_s32x4 = vmull_s16( tmp1_s16x4, vdup_n_s16( Lambda_Q10 ) );
+                rd2_Q10_s32x4 = vmull_s16( tmp2_s16x4, vdup_n_s16( Lambda_Q10 ) );
+            }
+
+            rr_Q10_s16x4 = vsub_s16( r_Q10_s16x4, q1_Q10_s16x4 );
+            rd1_Q10_s32x4 = vmlal_s16( rd1_Q10_s32x4, rr_Q10_s16x4, rr_Q10_s16x4 );
+            rd1_Q10_s32x4 = vshrq_n_s32( rd1_Q10_s32x4, 10 );
+
+            rr_Q10_s16x4 = vsub_s16( r_Q10_s16x4, q2_Q10_s16x4 );
+            rd2_Q10_s32x4 = vmlal_s16( rd2_Q10_s32x4, rr_Q10_s16x4, rr_Q10_s16x4 );
+            rd2_Q10_s32x4 = vshrq_n_s32( rd2_Q10_s32x4, 10 );
+
+            tmp2_s32x4 = vld1q_s32( psDelDec->RD_Q10 );
+            tmp1_s32x4 = vaddq_s32( tmp2_s32x4, vminq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 ) );
+            tmp2_s32x4 = vaddq_s32( tmp2_s32x4, vmaxq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 ) );
+            vst1q_s32( psSampleState[ 0 ].RD_Q10, tmp1_s32x4 );
+            vst1q_s32( psSampleState[ 1 ].RD_Q10, tmp2_s32x4 );
+            t_u32x4 = vcltq_s32( rd1_Q10_s32x4, rd2_Q10_s32x4 );
+            tmp1_s32x4 = vbslq_s32( t_u32x4, vmovl_s16( q1_Q10_s16x4 ), vmovl_s16( q2_Q10_s16x4 ) );
+            tmp2_s32x4 = vbslq_s32( t_u32x4, vmovl_s16( q2_Q10_s16x4 ), vmovl_s16( q1_Q10_s16x4 ) );
+            vst1q_s32( psSampleState[ 0 ].Q_Q10, tmp1_s32x4 );
+            vst1q_s32( psSampleState[ 1 ].Q_Q10, tmp2_s32x4 );
+        }
+
+        {
+            /* Update states for best quantization */
+            int32x4_t exc_Q14_s32x4, LPC_exc_Q14_s32x4, xq_Q14_s32x4, sLF_AR_shp_Q14_s32x4;
+
+            /* Quantized excitation */
+            exc_Q14_s32x4 = vshlq_n_s32( tmp1_s32x4, 4 );
+            exc_Q14_s32x4 = veorq_s32( exc_Q14_s32x4, sign_s32x4 );
+            exc_Q14_s32x4 = vsubq_s32( exc_Q14_s32x4, sign_s32x4 );
+
+            /* Add predictions */
+            LPC_exc_Q14_s32x4 = vaddq_s32( exc_Q14_s32x4, vdupq_n_s32( LTP_pred_Q14 ) );
+            xq_Q14_s32x4      = vaddq_s32( LPC_exc_Q14_s32x4, LPC_pred_Q14_s32x4 );
+
+            /* Update states */
+            tmp1_s32x4 = vsubq_s32( xq_Q14_s32x4, vshlq_n_s32( vdupq_n_s32( x_Q10[ i ] ), 4 ) );
+            vst1q_s32( psSampleState[ 0 ].Diff_Q14, tmp1_s32x4 );
+            sLF_AR_shp_Q14_s32x4 = vsubq_s32( tmp1_s32x4, n_AR_Q14_s32x4 );
+            vst1q_s32( psSampleState[ 0 ].sLTP_shp_Q14, vsubq_s32( sLF_AR_shp_Q14_s32x4, n_LF_Q14_s32x4 ) );
+            vst1q_s32( psSampleState[ 0 ].LF_AR_Q14, sLF_AR_shp_Q14_s32x4 );
+            vst1q_s32( psSampleState[ 0 ].LPC_exc_Q14, LPC_exc_Q14_s32x4 );
+            vst1q_s32( psSampleState[ 0 ].xq_Q14, xq_Q14_s32x4 );
+
+            /* Quantized excitation */
+            exc_Q14_s32x4 = vshlq_n_s32( tmp2_s32x4, 4 );
+            exc_Q14_s32x4 = veorq_s32( exc_Q14_s32x4, sign_s32x4 );
+            exc_Q14_s32x4 = vsubq_s32( exc_Q14_s32x4, sign_s32x4 );
+
+            /* Add predictions */
+            LPC_exc_Q14_s32x4 = vaddq_s32( exc_Q14_s32x4, vdupq_n_s32( LTP_pred_Q14 ) );
+            xq_Q14_s32x4      = vaddq_s32( LPC_exc_Q14_s32x4, LPC_pred_Q14_s32x4 );
+
+            /* Update states */
+            tmp1_s32x4 = vsubq_s32( xq_Q14_s32x4, vshlq_n_s32( vdupq_n_s32( x_Q10[ i ] ), 4 ) );
+            vst1q_s32( psSampleState[ 1 ].Diff_Q14, tmp1_s32x4 );
+            sLF_AR_shp_Q14_s32x4 = vsubq_s32( tmp1_s32x4, n_AR_Q14_s32x4 );
+            vst1q_s32( psSampleState[ 1 ].sLTP_shp_Q14, vsubq_s32( sLF_AR_shp_Q14_s32x4, n_LF_Q14_s32x4 ) );
+            vst1q_s32( psSampleState[ 1 ].LF_AR_Q14, sLF_AR_shp_Q14_s32x4 );
+            vst1q_s32( psSampleState[ 1 ].LPC_exc_Q14, LPC_exc_Q14_s32x4 );
+            vst1q_s32( psSampleState[ 1 ].xq_Q14, xq_Q14_s32x4 );
+        }
+
+        *smpl_buf_idx = *smpl_buf_idx ? ( *smpl_buf_idx - 1 ) : ( DECISION_DELAY - 1);
+        last_smple_idx = *smpl_buf_idx + decisionDelay + DECISION_DELAY;
+        if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
+        if( last_smple_idx >= DECISION_DELAY ) last_smple_idx -= DECISION_DELAY;
+
+        /* Find winner */
+        RDmin_Q10 = psSampleState[ 0 ].RD_Q10[ 0 ];
+        Winner_ind = 0;
+        for( k = 1; k < nStatesDelayedDecision; k++ ) {
+            if( psSampleState[ 0 ].RD_Q10[ k ] < RDmin_Q10 ) {
+                RDmin_Q10 = psSampleState[ 0 ].RD_Q10[ k ];
+                Winner_ind = k;
+            }
+        }
+
+        /* Increase RD values of expired states */
+        {
+            uint32x4_t t_u32x4;
+            Winner_rand_state = psDelDec->RandState[ last_smple_idx ][ Winner_ind ];
+            t_u32x4 = vceqq_s32( vld1q_s32( psDelDec->RandState[ last_smple_idx ] ), vdupq_n_s32( Winner_rand_state ) );
+            t_u32x4 = vmvnq_u32( t_u32x4 );
+            t_u32x4 = vshrq_n_u32( t_u32x4, 5 );
+            tmp1_s32x4 = vld1q_s32( psSampleState[ 0 ].RD_Q10 );
+            tmp2_s32x4 = vld1q_s32( psSampleState[ 1 ].RD_Q10 );
+            tmp1_s32x4 = vaddq_s32( tmp1_s32x4, vreinterpretq_s32_u32( t_u32x4 ) );
+            tmp2_s32x4 = vaddq_s32( tmp2_s32x4, vreinterpretq_s32_u32( t_u32x4 ) );
+            vst1q_s32( psSampleState[ 0 ].RD_Q10, tmp1_s32x4 );
+            vst1q_s32( psSampleState[ 1 ].RD_Q10, tmp2_s32x4 );
+
+            /* Find worst in first set and best in second set */
+            RDmax_Q10 = psSampleState[ 0 ].RD_Q10[ 0 ];
+            RDmin_Q10 = psSampleState[ 1 ].RD_Q10[ 0 ];
+            RDmax_ind = 0;
+            RDmin_ind = 0;
+            for( k = 1; k < nStatesDelayedDecision; k++ ) {
+                /* find worst in first set */
+                if( psSampleState[ 0 ].RD_Q10[ k ] > RDmax_Q10 ) {
+                    RDmax_Q10 = psSampleState[ 0 ].RD_Q10[ k ];
+                    RDmax_ind = k;
+                }
+                /* find best in second set */
+                if( psSampleState[ 1 ].RD_Q10[ k ] < RDmin_Q10 ) {
+                    RDmin_Q10 = psSampleState[ 1 ].RD_Q10[ k ];
+                    RDmin_ind = k;
+                }
+            }
+        }
+
+        /* Replace a state if best from second set outperforms worst in first set */
+        if( RDmin_Q10 < RDmax_Q10 ) {
+            opus_int32 (*ptr)[NEON_MAX_DEL_DEC_STATES] = psDelDec->RandState;
+            const int numOthers = (int)( ( sizeof( NSQ_del_decs_struct ) - sizeof( ( (NSQ_del_decs_struct *)0 )->sLPC_Q14 ) )
+                / ( NEON_MAX_DEL_DEC_STATES * sizeof( opus_int32 ) ) );
+            /* Only ( predictLPCOrder - 1 ) of sLPC_Q14 buffer need to be updated, though the first several     */
+            /* useless sLPC_Q14[] will be different comparing with C when predictLPCOrder < NSQ_LPC_BUF_LENGTH. */
+            /* Here just update constant ( NSQ_LPC_BUF_LENGTH - 1 ) for simplicity.                             */
+            for( j = i + 1; j < i + NSQ_LPC_BUF_LENGTH; j++ ) {
+                psDelDec->sLPC_Q14[ j ][ RDmax_ind ] = psDelDec->sLPC_Q14[ j ][ RDmin_ind ];
+            }
+            for( j = 0; j < numOthers; j++ ) {
+                ptr[ j ][ RDmax_ind ] = ptr[ j ][ RDmin_ind ];
+            }
+
+            psSampleState[ 0 ].Q_Q10[ RDmax_ind ] = psSampleState[ 1 ].Q_Q10[ RDmin_ind ];
+            psSampleState[ 0 ].RD_Q10[ RDmax_ind ] = psSampleState[ 1 ].RD_Q10[ RDmin_ind ];
+            psSampleState[ 0 ].xq_Q14[ RDmax_ind ] = psSampleState[ 1 ].xq_Q14[ RDmin_ind ];
+            psSampleState[ 0 ].LF_AR_Q14[ RDmax_ind ] = psSampleState[ 1 ].LF_AR_Q14[ RDmin_ind ];
+            psSampleState[ 0 ].Diff_Q14[ RDmax_ind ] = psSampleState[ 1 ].Diff_Q14[ RDmin_ind ];
+            psSampleState[ 0 ].sLTP_shp_Q14[ RDmax_ind ] = psSampleState[ 1 ].sLTP_shp_Q14[ RDmin_ind ];
+            psSampleState[ 0 ].LPC_exc_Q14[ RDmax_ind ] = psSampleState[ 1 ].LPC_exc_Q14[ RDmin_ind ];
+        }
+
+        /* Write samples from winner to output and long-term filter states */
+        if( subfr > 0 || i >= decisionDelay ) {
+            pulses[  i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDelDec->Q_Q10[ last_smple_idx ][ Winner_ind ], 10 );
+            xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
+                silk_SMULWW( psDelDec->Xq_Q14[ last_smple_idx ][ Winner_ind ], delayedGain_Q10[ last_smple_idx ] ), 8 ) );
+            NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDelDec->Shape_Q14[ last_smple_idx ][ Winner_ind ];
+            sLTP_Q15[          NSQ->sLTP_buf_idx     - decisionDelay ] = psDelDec->Pred_Q15[  last_smple_idx ][ Winner_ind ];
+        }
+        NSQ->sLTP_shp_buf_idx++;
+        NSQ->sLTP_buf_idx++;
+
+        /* Update states */
+        vst1q_s32( psDelDec->LF_AR_Q14, vld1q_s32( psSampleState[ 0 ].LF_AR_Q14 ) );
+        vst1q_s32( psDelDec->Diff_Q14, vld1q_s32( psSampleState[ 0 ].Diff_Q14 ) );
+        vst1q_s32( psDelDec->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ], vld1q_s32( psSampleState[ 0 ].xq_Q14 ) );
+        vst1q_s32( psDelDec->Xq_Q14[ *smpl_buf_idx ], vld1q_s32( psSampleState[ 0 ].xq_Q14 ) );
+        tmp1_s32x4 = vld1q_s32( psSampleState[ 0 ].Q_Q10 );
+        vst1q_s32( psDelDec->Q_Q10[ *smpl_buf_idx ], tmp1_s32x4 );
+        vst1q_s32( psDelDec->Pred_Q15[ *smpl_buf_idx ], vshlq_n_s32( vld1q_s32( psSampleState[ 0 ].LPC_exc_Q14 ), 1 ) );
+        vst1q_s32( psDelDec->Shape_Q14[ *smpl_buf_idx ], vld1q_s32( psSampleState[ 0 ].sLTP_shp_Q14 ) );
+        tmp1_s32x4 = vrshrq_n_s32( tmp1_s32x4, 10 );
+        tmp1_s32x4 = vaddq_s32( vld1q_s32( psDelDec->Seed ), tmp1_s32x4 );
+        vst1q_s32( psDelDec->Seed, tmp1_s32x4 );
+        vst1q_s32( psDelDec->RandState[ *smpl_buf_idx ], tmp1_s32x4 );
+        vst1q_s32( psDelDec->RD_Q10, vld1q_s32( psSampleState[ 0 ].RD_Q10 ) );
+        delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10;
+    }
+    /* Update LPC states */
+    silk_memcpy( psDelDec->sLPC_Q14[ 0 ], psDelDec->sLPC_Q14[ length ], NEON_MAX_DEL_DEC_STATES * NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
+
+    RESTORE_STACK;
+}
+
+static OPUS_INLINE void silk_SMULWB_8_neon(
+    const opus_int16 *a,
+    const int32x2_t  b,
+    opus_int32       *o
+)
+{
+    const int16x8_t a_s16x8 = vld1q_s16( a );
+    int32x4_t o0_s32x4, o1_s32x4;
+
+    o0_s32x4 = vshll_n_s16( vget_low_s16( a_s16x8 ), 15 );
+    o1_s32x4 = vshll_n_s16( vget_high_s16( a_s16x8 ), 15 );
+    o0_s32x4 = vqdmulhq_lane_s32( o0_s32x4, b, 0 );
+    o1_s32x4 = vqdmulhq_lane_s32( o1_s32x4, b, 0 );
+    vst1q_s32( o, o0_s32x4 );
+    vst1q_s32( o + 4, o1_s32x4 );
+}
+
+/* Only works when ( b >= -65536 ) && ( b < 65536 ). */
+static OPUS_INLINE void silk_SMULWW_small_b_4_neon(
+    opus_int32       *a,
+    const int32x2_t  b_s32x2)
+{
+    int32x4_t o_s32x4;
+
+    o_s32x4 = vld1q_s32( a );
+    o_s32x4 = vqdmulhq_lane_s32( o_s32x4, b_s32x2, 0 );
+    vst1q_s32( a, o_s32x4 );
+}
+
+/* Only works when ( b >= -65536 ) && ( b < 65536 ). */
+static OPUS_INLINE void silk_SMULWW_small_b_8_neon(
+    opus_int32       *a,
+    const int32x2_t  b_s32x2
+)
+{
+    int32x4_t o0_s32x4, o1_s32x4;
+
+    o0_s32x4 = vld1q_s32( a );
+    o1_s32x4 = vld1q_s32( a + 4 );
+    o0_s32x4 = vqdmulhq_lane_s32( o0_s32x4, b_s32x2, 0 );
+    o1_s32x4 = vqdmulhq_lane_s32( o1_s32x4, b_s32x2, 0 );
+    vst1q_s32( a, o0_s32x4 );
+    vst1q_s32( a + 4, o1_s32x4 );
+}
+
+static OPUS_INLINE void silk_SMULWW_4_neon(
+    opus_int32       *a,
+    const int32x2_t  b_s32x2)
+{
+    int32x4_t a_s32x4, o_s32x4;
+
+    a_s32x4 = vld1q_s32( a );
+    o_s32x4 = vqdmulhq_lane_s32( a_s32x4, b_s32x2, 0 );
+    o_s32x4 = vmlaq_lane_s32( o_s32x4, a_s32x4, b_s32x2, 1 );
+    vst1q_s32( a, o_s32x4 );
+}
+
+static OPUS_INLINE void silk_SMULWW_8_neon(
+    opus_int32       *a,
+    const int32x2_t  b_s32x2
+)
+{
+    int32x4_t a0_s32x4, a1_s32x4, o0_s32x4, o1_s32x4;
+
+    a0_s32x4 = vld1q_s32( a );
+    a1_s32x4 = vld1q_s32( a + 4 );
+    o0_s32x4 = vqdmulhq_lane_s32( a0_s32x4, b_s32x2, 0 );
+    o1_s32x4 = vqdmulhq_lane_s32( a1_s32x4, b_s32x2, 0 );
+    o0_s32x4 = vmlaq_lane_s32( o0_s32x4, a0_s32x4, b_s32x2, 1 );
+    o1_s32x4 = vmlaq_lane_s32( o1_s32x4, a1_s32x4, b_s32x2, 1 );
+    vst1q_s32( a, o0_s32x4 );
+    vst1q_s32( a + 4, o1_s32x4 );
+}
+
+static OPUS_INLINE void silk_SMULWW_loop_neon(
+    const opus_int16 *a,
+    const opus_int32 b,
+    opus_int32       *o,
+    const opus_int   loop_num
+)
+{
+    opus_int i;
+    int32x2_t b_s32x2;
+
+    b_s32x2 = vdup_n_s32( b );
+    for( i = 0; i < loop_num - 7; i += 8 ) {
+        silk_SMULWB_8_neon( a + i, b_s32x2, o + i );
+    }
+    for( ; i < loop_num; i++ ) {
+        o[ i ] = silk_SMULWW( a[ i ], b );
+    }
+}
+
+static OPUS_INLINE void silk_nsq_del_dec_scale_states_neon(
+    const silk_encoder_state *psEncC,               /* I    Encoder State                       */
+    silk_nsq_state      *NSQ,                       /* I/O  NSQ state                           */
+    NSQ_del_decs_struct psDelDec[],                 /* I/O  Delayed decision states             */
+    const opus_int16    x16[],                      /* I    Input                               */
+    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_Q15[],                 /* O    LTP state matching scaled input     */
+    opus_int            subfr,                      /* I    Subframe number                     */
+    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                           */
+    const opus_int      signal_type,                /* I    Signal type                         */
+    const opus_int      decisionDelay               /* I    Decision delay                      */
+)
+{
+    opus_int            i, lag;
+    opus_int32          gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
+
+    lag          = pitchL[ subfr ];
+    inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
+    silk_assert( inv_gain_Q31 != 0 );
+
+    /* Scale input */
+    inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
+    silk_SMULWW_loop_neon( x16, inv_gain_Q26, x_sc_Q10, psEncC->subfr_length );
+
+    /* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
+    if( NSQ->rewhite_flag ) {
+        if( subfr == 0 ) {
+            /* Do LTP downscaling */
+            inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
+        }
+        silk_SMULWW_loop_neon( sLTP + NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2, inv_gain_Q31, sLTP_Q15 + NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2, lag + LTP_ORDER / 2 );
+    }
+
+    /* Adjust for changing gain */
+    if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
+        int32x2_t gain_adj_Q16_s32x2;
+        gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
+
+        /* Scale long-term shaping state */
+        if( ( gain_adj_Q16 >= -65536 ) && ( gain_adj_Q16 < 65536 ) ) {
+            gain_adj_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( gain_adj_Q16, 15 ) );
+            for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 7; i += 8 ) {
+                silk_SMULWW_small_b_8_neon( NSQ->sLTP_shp_Q14 + i, gain_adj_Q16_s32x2 );
+            }
+            for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) {
+                NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
+            }
+
+            /* Scale long-term prediction state */
+            if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
+                for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay - 7; i += 8 ) {
+                    silk_SMULWW_small_b_8_neon( sLTP_Q15 + i, gain_adj_Q16_s32x2 );
+                }
+                for( ; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
+                    sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
+                }
+            }
+
+            /* Scale scalar states */
+            silk_SMULWW_small_b_4_neon( psDelDec->LF_AR_Q14, gain_adj_Q16_s32x2 );
+            silk_SMULWW_small_b_4_neon( psDelDec->Diff_Q14,  gain_adj_Q16_s32x2 );
+
+            /* Scale short-term prediction and shaping states */
+            for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+                silk_SMULWW_small_b_4_neon( psDelDec->sLPC_Q14[ i ], gain_adj_Q16_s32x2 );
+            }
+
+            for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
+                silk_SMULWW_small_b_4_neon( psDelDec->sAR2_Q14[ i ], gain_adj_Q16_s32x2 );
+            }
+
+            for( i = 0; i < DECISION_DELAY; i++ ) {
+                silk_SMULWW_small_b_4_neon( psDelDec->Pred_Q15[  i ], gain_adj_Q16_s32x2 );
+                silk_SMULWW_small_b_4_neon( psDelDec->Shape_Q14[ i ], gain_adj_Q16_s32x2 );
+            }
+        } else {
+            gain_adj_Q16_s32x2 = vdup_n_s32( silk_LSHIFT32( gain_adj_Q16 & 0x0000FFFF, 15 ) );
+            gain_adj_Q16_s32x2 = vset_lane_s32( gain_adj_Q16 >> 16, gain_adj_Q16_s32x2, 1 );
+            for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx - 7; i += 8 ) {
+                silk_SMULWW_8_neon( NSQ->sLTP_shp_Q14 + i, gain_adj_Q16_s32x2 );
+            }
+            for( ; i < NSQ->sLTP_shp_buf_idx; i++ ) {
+                NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
+            }
+
+            /* Scale long-term prediction state */
+            if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
+                for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay - 7; i += 8 ) {
+                    silk_SMULWW_8_neon( sLTP_Q15 + i, gain_adj_Q16_s32x2 );
+                }
+                for( ; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
+                    sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
+                }
+            }
+
+            /* Scale scalar states */
+            silk_SMULWW_4_neon( psDelDec->LF_AR_Q14, gain_adj_Q16_s32x2 );
+            silk_SMULWW_4_neon( psDelDec->Diff_Q14,  gain_adj_Q16_s32x2 );
+
+            /* Scale short-term prediction and shaping states */
+            for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
+                silk_SMULWW_4_neon( psDelDec->sLPC_Q14[ i ], gain_adj_Q16_s32x2 );
+            }
+
+            for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
+                silk_SMULWW_4_neon( psDelDec->sAR2_Q14[ i ], gain_adj_Q16_s32x2 );
+            }
+
+            for( i = 0; i < DECISION_DELAY; i++ ) {
+                silk_SMULWW_4_neon( psDelDec->Pred_Q15[  i ], gain_adj_Q16_s32x2 );
+                silk_SMULWW_4_neon( psDelDec->Shape_Q14[ i ], gain_adj_Q16_s32x2 );
+            }
+        }
+
+        /* Save inverse gain */
+        NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
+    }
+}
--- a/media/libopus/silk/arm/NSQ_neon.h
+++ b/media/libopus/silk/arm/NSQ_neon.h
@@ -23,40 +23,41 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 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_NSQ_NEON_H
 #define SILK_NSQ_NEON_H
 
 #include "cpu_support.h"
+#include "SigProc_FIX.h"
 
 #undef silk_short_prediction_create_arch_coef
 /* For vectorized calc, reverse a_Q12 coefs, convert to 32-bit, and shift for vqdmulhq_s32. */
 static OPUS_INLINE void silk_short_prediction_create_arch_coef_neon(opus_int32 *out, const opus_int16 *in, opus_int order)
 {
-    out[15] = in[0] << 15;
-    out[14] = in[1] << 15;
-    out[13] = in[2] << 15;
-    out[12] = in[3] << 15;
-    out[11] = in[4] << 15;
-    out[10] = in[5] << 15;
-    out[9]  = in[6] << 15;
-    out[8]  = in[7] << 15;
-    out[7]  = in[8] << 15;
-    out[6]  = in[9] << 15;
+    out[15] = silk_LSHIFT32(in[0], 15);
+    out[14] = silk_LSHIFT32(in[1], 15);
+    out[13] = silk_LSHIFT32(in[2], 15);
+    out[12] = silk_LSHIFT32(in[3], 15);
+    out[11] = silk_LSHIFT32(in[4], 15);
+    out[10] = silk_LSHIFT32(in[5], 15);
+    out[9]  = silk_LSHIFT32(in[6], 15);
+    out[8]  = silk_LSHIFT32(in[7], 15);
+    out[7]  = silk_LSHIFT32(in[8], 15);
+    out[6]  = silk_LSHIFT32(in[9], 15);
 
     if (order == 16)
     {
-        out[5] = in[10] << 15;
-        out[4] = in[11] << 15;
-        out[3] = in[12] << 15;
-        out[2] = in[13] << 15;
-        out[1] = in[14] << 15;
-        out[0] = in[15] << 15;
+        out[5] = silk_LSHIFT32(in[10], 15);
+        out[4] = silk_LSHIFT32(in[11], 15);
+        out[3] = silk_LSHIFT32(in[12], 15);
+        out[2] = silk_LSHIFT32(in[13], 15);
+        out[1] = silk_LSHIFT32(in[14], 15);
+        out[0] = silk_LSHIFT32(in[15], 15);
     }
     else
     {
         out[5] = 0;
         out[4] = 0;
         out[3] = 0;
         out[2] = 0;
         out[1] = 0;
--- a/media/libopus/silk/arm/arm_silk_map.c
+++ b/media/libopus/silk/arm/arm_silk_map.c
@@ -23,23 +23,72 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 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_FIX.h"
 #include "NSQ.h"
+#include "SigProc_FIX.h"
 
 #if defined(OPUS_HAVE_RTCD)
 
 # if (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && \
  !defined(OPUS_ARM_PRESUME_NEON_INTR))
 
+void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK + 1])(
+        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 [4]                                           */
+        opus_int16                  *out,               /* O     output signal                                              */
+        const opus_int32            len                 /* I     signal length (must be even)                               */
+) = {
+      silk_biquad_alt_stride2_c,    /* ARMv4 */
+      silk_biquad_alt_stride2_c,    /* EDSP */
+      silk_biquad_alt_stride2_c,    /* Media */
+      silk_biquad_alt_stride2_neon, /* Neon */
+};
+
+opus_int32 (*const SILK_LPC_INVERSE_PRED_GAIN_IMPL[OPUS_ARCHMASK + 1])( /* O   Returns inverse prediction gain in energy domain, Q30        */
+        const opus_int16            *A_Q12,                             /* I   Prediction coefficients, Q12 [order]                         */
+        const opus_int              order                               /* I   Prediction order                                             */
+) = {
+      silk_LPC_inverse_pred_gain_c,    /* ARMv4 */
+      silk_LPC_inverse_pred_gain_c,    /* EDSP */
+      silk_LPC_inverse_pred_gain_c,    /* Media */
+      silk_LPC_inverse_pred_gain_neon, /* Neon */
+};
+
+void  (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
+        const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
+        silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
+        SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
+        const opus_int16            x16[],                                      /* I    Input                           */
+        opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
+        const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
+        const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
+        const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs              */
+        const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
+        const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                   /* I    Spectral tilt                   */
+        const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                 /* I    Low frequency shaping coefs     */
+        const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                  /* I    Quantization step sizes         */
+        const opus_int              pitchL[ MAX_NB_SUBFR ],                     /* I    Pitch lags                      */
+        const opus_int              Lambda_Q10,                                 /* I    Rate/distortion tradeoff        */
+        const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
+) = {
+      silk_NSQ_del_dec_c,    /* ARMv4 */
+      silk_NSQ_del_dec_c,    /* EDSP */
+      silk_NSQ_del_dec_c,    /* Media */
+      silk_NSQ_del_dec_neon, /* Neon */
+};
+
 /*There is no table for silk_noise_shape_quantizer_short_prediction because the
    NEON version takes different parameters than the C version.
   Instead RTCD is done via if statements at the call sites.
   See NSQ_neon.h for details.*/
 
 opus_int32
  (*const SILK_NSQ_NOISE_SHAPE_FEEDBACK_LOOP_IMPL[OPUS_ARCHMASK+1])(
  const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef,
@@ -47,9 +96,28 @@ opus_int32
   silk_NSQ_noise_shape_feedback_loop_c,    /* ARMv4 */
   silk_NSQ_noise_shape_feedback_loop_c,    /* EDSP */
   silk_NSQ_noise_shape_feedback_loop_c,    /* Media */
   silk_NSQ_noise_shape_feedback_loop_neon, /* NEON */
 };
 
 # endif
 
+# if defined(FIXED_POINT) && \
+ defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
+
+void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK + 1])(
+          opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
+          opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
+    const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
+    const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
+    const opus_int                  length,                                 /* I    Length of input                                                             */
+    const opus_int                  order                                   /* I    Correlation order (even)                                                    */
+) = {
+      silk_warped_autocorrelation_FIX_c,    /* ARMv4 */
+      silk_warped_autocorrelation_FIX_c,    /* EDSP */
+      silk_warped_autocorrelation_FIX_c,    /* Media */
+      silk_warped_autocorrelation_FIX_neon, /* Neon */
+};
+
+# endif
+
 #endif /* OPUS_HAVE_RTCD */
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/arm/biquad_alt_arm.h
@@ -0,0 +1,68 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_BIQUAD_ALT_ARM_H
+# define SILK_BIQUAD_ALT_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_biquad_alt_stride2_neon(
+    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 [4]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+);
+
+#  if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+#   define OVERRIDE_silk_biquad_alt_stride2                   (1)
+#   define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), PRESUME_NEON(silk_biquad_alt_stride2)(in, B_Q28, A_Q28, S, out, len))
+#  endif
+# endif
+
+# if !defined(OVERRIDE_silk_biquad_alt_stride2)
+/*Is run-time CPU detection enabled on this platform?*/
+#  if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_BIQUAD_ALT_STRIDE2_IMPL[OPUS_ARCHMASK+1])(
+        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 [4]                                           */
+        opus_int16                  *out,               /* O     output signal                                              */
+        const opus_int32            len                 /* I     signal length (must be even)                               */
+    );
+#   define OVERRIDE_silk_biquad_alt_stride2                  (1)
+#   define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((*SILK_BIQUAD_ALT_STRIDE2_IMPL[(arch)&OPUS_ARCHMASK])(in, B_Q28, A_Q28, S, out, len))
+#  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#   define OVERRIDE_silk_biquad_alt_stride2                  (1)
+#   define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_neon(in, B_Q28, A_Q28, S, out, len))
+#  endif
+# endif
+
+#endif /* end SILK_BIQUAD_ALT_ARM_H */
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/arm/biquad_alt_neon_intr.c
@@ -0,0 +1,156 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <arm_neon.h>
+#ifdef OPUS_CHECK_ASM
+# include <string.h>
+# include "stack_alloc.h"
+#endif
+#include "SigProc_FIX.h"
+
+static inline void silk_biquad_alt_stride2_kernel( const int32x4_t A_L_s32x4, const int32x4_t A_U_s32x4, const int32x4_t B_Q28_s32x4, const int32x2_t t_s32x2, const int32x4_t in_s32x4, int32x4_t *S_s32x4, int32x2_t *out32_Q14_s32x2 )
+{
+    int32x4_t t_s32x4, out32_Q14_s32x4;
+
+    *out32_Q14_s32x2 = vadd_s32( vget_low_s32( *S_s32x4 ), t_s32x2 );              /* silk_SMLAWB( S{0,1}, B_Q28[ 0 ], in{0,1} )                                      */
+    *S_s32x4         = vcombine_s32( vget_high_s32( *S_s32x4 ), vdup_n_s32( 0 ) ); /* S{0,1} = S{2,3}; S{2,3} = 0;                                                    */
+    *out32_Q14_s32x2 = vshl_n_s32( *out32_Q14_s32x2, 2 );                          /* out32_Q14_{0,1} = silk_LSHIFT( silk_SMLAWB( S{0,1}, B_Q28[ 0 ], in{0,1} ), 2 ); */
+    out32_Q14_s32x4  = vcombine_s32( *out32_Q14_s32x2, *out32_Q14_s32x2 );         /* out32_Q14_{0,1,0,1}                                                             */
+    t_s32x4          = vqdmulhq_s32( out32_Q14_s32x4, A_L_s32x4 );                 /* silk_SMULWB( out32_Q14_{0,1,0,1}, A{0,0,1,1}_L_Q28 )                            */
+    *S_s32x4         = vrsraq_n_s32( *S_s32x4, t_s32x4, 14 );                      /* S{0,1} = S{2,3} + silk_RSHIFT_ROUND();  S{2,3} = silk_RSHIFT_ROUND();           */
+    t_s32x4          = vqdmulhq_s32( out32_Q14_s32x4, A_U_s32x4 );                 /* silk_SMULWB( out32_Q14_{0,1,0,1}, A{0,0,1,1}_U_Q28 )                            */
+    *S_s32x4         = vaddq_s32( *S_s32x4, t_s32x4 );                             /* S0 = silk_SMLAWB( S{0,1,2,3}, out32_Q14_{0,1,0,1}, A{0,0,1,1}_U_Q28 );          */
+    t_s32x4          = vqdmulhq_s32( in_s32x4, B_Q28_s32x4 );                      /* silk_SMULWB( B_Q28[ {1,1,2,2} ], in{0,1,0,1} )                                  */
+    *S_s32x4         = vaddq_s32( *S_s32x4, t_s32x4 );                             /* S0 = silk_SMLAWB( S0, B_Q28[ {1,1,2,2} ], in{0,1,0,1} );                        */
+}
+
+void silk_biquad_alt_stride2_neon(
+    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 [4]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+)
+{
+    /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+    opus_int        k            = 0;
+    const int32x2_t offset_s32x2 = vdup_n_s32( (1<<14) - 1 );
+    const int32x4_t offset_s32x4 = vcombine_s32( offset_s32x2, offset_s32x2 );
+    int16x4_t       in_s16x4  = vdup_n_s16( 0 );
+    int16x4_t       out_s16x4;
+    int32x2_t       A_Q28_s32x2, A_L_s32x2, A_U_s32x2, B_Q28_s32x2, t_s32x2;
+    int32x4_t       A_L_s32x4, A_U_s32x4, B_Q28_s32x4, S_s32x4, out32_Q14_s32x4;
+    int32x2x2_t     t0_s32x2x2, t1_s32x2x2, t2_s32x2x2, S_s32x2x2;
+
+#ifdef OPUS_CHECK_ASM
+    opus_int32 S_c[ 4 ];
+    VARDECL( opus_int16, out_c );
+    SAVE_STACK;
+    ALLOC( out_c, 2 * len, opus_int16 );
+
+    silk_memcpy( &S_c, S, sizeof( S_c ) );
+    silk_biquad_alt_stride2_c( in, B_Q28, A_Q28, S_c, out_c, len );
+#endif
+
+    /* Negate A_Q28 values and split in two parts */
+    A_Q28_s32x2 = vld1_s32( A_Q28 );
+    A_Q28_s32x2 = vneg_s32( A_Q28_s32x2 );
+    A_L_s32x2   = vshl_n_s32( A_Q28_s32x2, 18 );                                                        /* ( -A_Q28[] & 0x00003FFF ) << 18                                                     */
+    A_L_s32x2   = vreinterpret_s32_u32( vshr_n_u32( vreinterpret_u32_s32( A_L_s32x2 ), 3 ) );           /* ( -A_Q28[] & 0x00003FFF ) << 15                                                     */
+    A_U_s32x2   = vshr_n_s32( A_Q28_s32x2, 14 );                                                        /* silk_RSHIFT( -A_Q28[], 14 )                                                         */
+    A_U_s32x2   = vshl_n_s32( A_U_s32x2, 16 );                                                          /* silk_RSHIFT( -A_Q28[], 14 ) << 16 (Clip two leading bits to conform to C function.) */
+    A_U_s32x2   = vshr_n_s32( A_U_s32x2, 1 );                                                           /* silk_RSHIFT( -A_Q28[], 14 ) << 15                                                   */
+
+    B_Q28_s32x2  = vld1_s32( B_Q28 );
+    t_s32x2      = vld1_s32( B_Q28 + 1 );
+    t0_s32x2x2   = vzip_s32( A_L_s32x2, A_L_s32x2 );
+    t1_s32x2x2   = vzip_s32( A_U_s32x2, A_U_s32x2 );
+    t2_s32x2x2   = vzip_s32( t_s32x2, t_s32x2 );
+    A_L_s32x4    = vcombine_s32( t0_s32x2x2.val[ 0 ], t0_s32x2x2.val[ 1 ] );                            /* A{0,0,1,1}_L_Q28          */
+    A_U_s32x4    = vcombine_s32( t1_s32x2x2.val[ 0 ], t1_s32x2x2.val[ 1 ] );                            /* A{0,0,1,1}_U_Q28          */
+    B_Q28_s32x4  = vcombine_s32( t2_s32x2x2.val[ 0 ], t2_s32x2x2.val[ 1 ] );                            /* B_Q28[ {1,1,2,2} ]        */
+    S_s32x4      = vld1q_s32( S );                                                                      /* S0 = S[ 0 ]; S3 = S[ 3 ]; */
+    S_s32x2x2    = vtrn_s32( vget_low_s32( S_s32x4 ), vget_high_s32( S_s32x4 ) );                       /* S2 = S[ 1 ]; S1 = S[ 2 ]; */
+    S_s32x4      = vcombine_s32( S_s32x2x2.val[ 0 ], S_s32x2x2.val[ 1 ] );
+
+    for( ; k < len - 1; k += 2 ) {
+        int32x4_t in_s32x4[ 2 ], t_s32x4;
+        int32x2_t out32_Q14_s32x2[ 2 ];
+
+        /* S[ 2 * i + 0 ], S[ 2 * i + 1 ], S[ 2 * i + 2 ], S[ 2 * i + 3 ]: Q12 */
+        in_s16x4      = vld1_s16( &in[ 2 * k ] );                                                       /* in{0,1,2,3} = in[ 2 * k + {0,1,2,3} ]; */
+        in_s32x4[ 0 ] = vshll_n_s16( in_s16x4, 15 );                                                    /* in{0,1,2,3} << 15                      */
+        t_s32x4       = vqdmulhq_lane_s32( in_s32x4[ 0 ], B_Q28_s32x2, 0 );                             /* silk_SMULWB( B_Q28[ 0 ], in{0,1,2,3} ) */
+        in_s32x4[ 1 ] = vcombine_s32( vget_high_s32( in_s32x4[ 0 ] ), vget_high_s32( in_s32x4[ 0 ] ) ); /* in{2,3,2,3} << 15                      */
+        in_s32x4[ 0 ] = vcombine_s32( vget_low_s32 ( in_s32x4[ 0 ] ), vget_low_s32 ( in_s32x4[ 0 ] ) ); /* in{0,1,0,1} << 15                      */
+        silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, vget_low_s32 ( t_s32x4 ), in_s32x4[ 0 ], &S_s32x4, &out32_Q14_s32x2[ 0 ] );
+        silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, vget_high_s32( t_s32x4 ), in_s32x4[ 1 ], &S_s32x4, &out32_Q14_s32x2[ 1 ] );
+
+        /* Scale back to Q0 and saturate */
+        out32_Q14_s32x4 = vcombine_s32( out32_Q14_s32x2[ 0 ], out32_Q14_s32x2[ 1 ] );                   /* out32_Q14_{0,1,2,3}                                                                                        */
+        out32_Q14_s32x4 = vaddq_s32( out32_Q14_s32x4, offset_s32x4 );                                   /* out32_Q14_{0,1,2,3} + (1<<14) - 1                                                                          */
+        out_s16x4       = vqshrn_n_s32( out32_Q14_s32x4, 14 );                                          /* (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,2,3} + (1<<14) - 1, 14 ) )                             */
+        vst1_s16( &out[ 2 * k ], out_s16x4 );                                                           /* out[ 2 * k + {0,1,2,3} ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,2,3} + (1<<14) - 1, 14 ) ); */
+    }
+
+    /* Process leftover. */
+    if( k < len ) {
+        int32x4_t in_s32x4;
+        int32x2_t out32_Q14_s32x2;
+
+        /* S[ 2 * i + 0 ], S[ 2 * i + 1 ]: Q12 */
+        in_s16x4     = vld1_lane_s16( &in[ 2 * k + 0 ], in_s16x4, 0 );                                  /* in{0,1} = in[ 2 * k + {0,1} ];     */
+        in_s16x4     = vld1_lane_s16( &in[ 2 * k + 1 ], in_s16x4, 1 );                                  /* in{0,1} = in[ 2 * k + {0,1} ];     */
+        in_s32x4     = vshll_n_s16( in_s16x4, 15 );                                                     /* in{0,1} << 15                      */
+        t_s32x2      = vqdmulh_lane_s32( vget_low_s32( in_s32x4 ), B_Q28_s32x2, 0 );                    /* silk_SMULWB( B_Q28[ 0 ], in{0,1} ) */
+        in_s32x4     = vcombine_s32( vget_low_s32( in_s32x4 ), vget_low_s32( in_s32x4 ) );              /* in{0,1,0,1} << 15                  */
+        silk_biquad_alt_stride2_kernel( A_L_s32x4, A_U_s32x4, B_Q28_s32x4, t_s32x2, in_s32x4, &S_s32x4, &out32_Q14_s32x2 );
+
+        /* Scale back to Q0 and saturate */
+        out32_Q14_s32x2 = vadd_s32( out32_Q14_s32x2, offset_s32x2 );                                    /* out32_Q14_{0,1} + (1<<14) - 1                                                              */
+        out32_Q14_s32x4 = vcombine_s32( out32_Q14_s32x2, out32_Q14_s32x2 );                             /* out32_Q14_{0,1,0,1} + (1<<14) - 1                                                          */
+        out_s16x4       = vqshrn_n_s32( out32_Q14_s32x4, 14 );                                          /* (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_{0,1,0,1} + (1<<14) - 1, 14 ) )             */
+        vst1_lane_s16( &out[ 2 * k + 0 ], out_s16x4, 0 );                                               /* out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_0 + (1<<14) - 1, 14 ) ); */
+        vst1_lane_s16( &out[ 2 * k + 1 ], out_s16x4, 1 );                                               /* out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14_1 + (1<<14) - 1, 14 ) ); */
+    }
+
+    vst1q_lane_s32( &S[ 0 ], S_s32x4, 0 );                                                              /* S[ 0 ] = S0; */
+    vst1q_lane_s32( &S[ 1 ], S_s32x4, 2 );                                                              /* S[ 1 ] = S2; */
+    vst1q_lane_s32( &S[ 2 ], S_s32x4, 1 );                                                              /* S[ 2 ] = S1; */
+    vst1q_lane_s32( &S[ 3 ], S_s32x4, 3 );                                                              /* S[ 3 ] = S3; */
+
+#ifdef OPUS_CHECK_ASM
+    silk_assert( !memcmp( S_c, S, sizeof( S_c ) ) );
+    silk_assert( !memcmp( out_c, out, 2 * len * sizeof( opus_int16 ) ) );
+    RESTORE_STACK;
+#endif
+}
--- a/media/libopus/silk/arm/macros_armv4.h
+++ b/media/libopus/silk/arm/macros_armv4.h
@@ -23,27 +23,32 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 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_MACROS_ARMv4_H
 #define SILK_MACROS_ARMv4_H
 
+/* This macro only avoids the undefined behaviour from a left shift of
+   a negative value. It should only be used in macros that can't include
+   SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
+#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
+
 /* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
 #undef silk_SMULWB
 static OPUS_INLINE opus_int32 silk_SMULWB_armv4(opus_int32 a, opus_int16 b)
 {
   unsigned rd_lo;
   int rd_hi;
   __asm__(
       "#silk_SMULWB\n\t"
       "smull %0, %1, %2, %3\n\t"
       : "=&r"(rd_lo), "=&r"(rd_hi)
-      : "%r"(a), "r"(b<<16)
+      : "%r"(a), "r"(SAFE_SHL(b,16))
   );
   return rd_hi;
 }
 #define silk_SMULWB(a, b) (silk_SMULWB_armv4(a, b))
 
 /* a32 + (b32 * (opus_int32)((opus_int16)(c32))) >> 16 output have to be 32bit int */
 #undef silk_SMLAWB
 #define silk_SMLAWB(a, b, c) ((a) + silk_SMULWB(b, c))
@@ -75,29 +80,31 @@ static OPUS_INLINE opus_int32 silk_SMULW
   unsigned rd_lo;
   int rd_hi;
   __asm__(
     "#silk_SMULWW\n\t"
     "smull %0, %1, %2, %3\n\t"
     : "=&r"(rd_lo), "=&r"(rd_hi)
     : "%r"(a), "r"(b)
   );
-  return (rd_hi<<16)+(rd_lo>>16);
+  return SAFE_SHL(rd_hi,16)+(rd_lo>>16);
 }
 #define silk_SMULWW(a, b) (silk_SMULWW_armv4(a, b))
 
 #undef silk_SMLAWW
 static OPUS_INLINE opus_int32 silk_SMLAWW_armv4(opus_int32 a, opus_int32 b,
  opus_int32 c)
 {
   unsigned rd_lo;
   int rd_hi;
   __asm__(
     "#silk_SMLAWW\n\t"
     "smull %0, %1, %2, %3\n\t"
     : "=&r"(rd_lo), "=&r"(rd_hi)
     : "%r"(b), "r"(c)
   );
-  return a+(rd_hi<<16)+(rd_lo>>16);
+  return a+SAFE_SHL(rd_hi,16)+(rd_lo>>16);
 }
 #define silk_SMLAWW(a, b, c) (silk_SMLAWW_armv4(a, b, c))
 
+#undef SAFE_SHL
+
 #endif /* SILK_MACROS_ARMv4_H */
--- a/media/libopus/silk/arm/macros_armv5e.h
+++ b/media/libopus/silk/arm/macros_armv5e.h
@@ -24,16 +24,21 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 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_MACROS_ARMv5E_H
 #define SILK_MACROS_ARMv5E_H
 
+/* This macro only avoids the undefined behaviour from a left shift of
+   a negative value. It should only be used in macros that can't include
+   SigProc_FIX.h. In other cases, use silk_LSHIFT32(). */
+#define SAFE_SHL(a,b) ((opus_int32)((opus_uint32)(a) << (b)))
+
 /* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
 #undef silk_SMULWB
 static OPUS_INLINE opus_int32 silk_SMULWB_armv5e(opus_int32 a, opus_int16 b)
 {
   int res;
   __asm__(
       "#silk_SMULWB\n\t"
       "smulwb %0, %1, %2\n\t"
@@ -185,17 +190,17 @@ static OPUS_INLINE opus_int32 silk_SUB_S
 #undef silk_CLZ16
 static OPUS_INLINE opus_int32 silk_CLZ16_armv5(opus_int16 in16)
 {
   int res;
   __asm__(
       "#silk_CLZ16\n\t"
       "clz %0, %1;\n"
       : "=r"(res)
-      : "r"(in16<<16|0x8000)
+      : "r"(SAFE_SHL(in16,16)|0x8000)
   );
   return res;
 }
 #define silk_CLZ16(in16) (silk_CLZ16_armv5(in16))
 
 #undef silk_CLZ32
 static OPUS_INLINE opus_int32 silk_CLZ32_armv5(opus_int32 in32)
 {
@@ -205,9 +210,11 @@ static OPUS_INLINE opus_int32 silk_CLZ32
       "clz %0, %1\n\t"
       : "=r"(res)
       : "r"(in32)
   );
   return res;
 }
 #define silk_CLZ32(in32) (silk_CLZ32_armv5(in32))
 
+#undef SAFE_SHL
+
 #endif /* SILK_MACROS_ARMv5E_H */
--- a/media/libopus/silk/biquad_alt.c
+++ b/media/libopus/silk/biquad_alt.c
@@ -34,45 +34,88 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "SigProc_FIX.h"
 
 /* Second order ARMA filter, alternative implementation */
-void silk_biquad_alt(
+void silk_biquad_alt_stride1(
     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)                               */
-    opus_int                    stride              /* I     Operate on interleaved signal if > 1                       */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
 )
 {
     /* 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 ];
+        inval = in[ k ];
         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 ) );
+        out[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14 + (1<<14) - 1, 14 ) );
     }
 }
+
+void silk_biquad_alt_stride2_c(
+    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 [4]                                           */
+    opus_int16                  *out,               /* O     output signal                                              */
+    const opus_int32            len                 /* I     signal length (must be even)                               */
+)
+{
+    /* DIRECT FORM II TRANSPOSED (uses 2 element state vector) */
+    opus_int   k;
+    opus_int32 A0_U_Q28, A0_L_Q28, A1_U_Q28, A1_L_Q28, out32_Q14[ 2 ];
+
+    /* 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 ], S[ 2 ], S[ 3 ]: Q12 */
+        out32_Q14[ 0 ] = silk_LSHIFT( silk_SMLAWB( S[ 0 ], B_Q28[ 0 ], in[ 2 * k + 0 ] ), 2 );
+        out32_Q14[ 1 ] = silk_LSHIFT( silk_SMLAWB( S[ 2 ], B_Q28[ 0 ], in[ 2 * k + 1 ] ), 2 );
+
+        S[ 0 ] = S[ 1 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A0_L_Q28 ), 14 );
+        S[ 2 ] = S[ 3 ] + silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A0_L_Q28 ), 14 );
+        S[ 0 ] = silk_SMLAWB( S[ 0 ], out32_Q14[ 0 ], A0_U_Q28 );
+        S[ 2 ] = silk_SMLAWB( S[ 2 ], out32_Q14[ 1 ], A0_U_Q28 );
+        S[ 0 ] = silk_SMLAWB( S[ 0 ], B_Q28[ 1 ], in[ 2 * k + 0 ] );
+        S[ 2 ] = silk_SMLAWB( S[ 2 ], B_Q28[ 1 ], in[ 2 * k + 1 ] );
+
+        S[ 1 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 0 ], A1_L_Q28 ), 14 );
+        S[ 3 ] = silk_RSHIFT_ROUND( silk_SMULWB( out32_Q14[ 1 ], A1_L_Q28 ), 14 );
+        S[ 1 ] = silk_SMLAWB( S[ 1 ], out32_Q14[ 0 ], A1_U_Q28 );
+        S[ 3 ] = silk_SMLAWB( S[ 3 ], out32_Q14[ 1 ], A1_U_Q28 );
+        S[ 1 ] = silk_SMLAWB( S[ 1 ], B_Q28[ 2 ], in[ 2 * k + 0 ] );
+        S[ 3 ] = silk_SMLAWB( S[ 3 ], B_Q28[ 2 ], in[ 2 * k + 1 ] );
+
+        /* Scale back to Q0 and saturate */
+        out[ 2 * k + 0 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 0 ] + (1<<14) - 1, 14 ) );
+        out[ 2 * k + 1 ] = (opus_int16)silk_SAT16( silk_RSHIFT( out32_Q14[ 1 ] + (1<<14) - 1, 14 ) );
+    }
+}
--- a/media/libopus/silk/bwexpander.c
+++ b/media/libopus/silk/bwexpander.c
@@ -40,12 +40,12 @@ void silk_bwexpander(
 {
     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 );
+        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 );
 }
--- a/media/libopus/silk/control.h
+++ b/media/libopus/silk/control.h
@@ -72,16 +72,19 @@ typedef struct {
     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 actually code in-band Forward Error Correction (FEC) in the current packet; 0/1 */
+    opus_int LBRR_coded;
+
     /* I:   Flag to enable discontinuous transmission (DTX); 0/1                            */
     opus_int useDTX;
 
     /* I:   Flag to use constant bitrate                                                    */
     opus_int useCBR;
 
     /* I:   Maximum number of bits allowed for the frame                                    */
     opus_int maxBits;
@@ -105,16 +108,21 @@ typedef struct {
     opus_int inWBmodeWithoutVariableLP;
 
     /* O:   Stereo width */
     opus_int stereoWidth_Q14;
 
     /* O:   Tells the Opus encoder we're ready to switch                                    */
     opus_int switchReady;
 
+    /* O: SILK Signal type */
+    opus_int signalType;
+
+    /* O: SILK offset (dithering) */
+    opus_int offset;
 } silk_EncControlStruct;
 
 /**************************************************************************/
 /* Structure for controlling decoder operation and reading decoder status */
 /**************************************************************************/
 typedef struct {
     /* I:   Number of channels; 1/2                                                         */
     opus_int32 nChannelsAPI;
--- a/media/libopus/silk/control_SNR.c
+++ b/media/libopus/silk/control_SNR.c
@@ -59,18 +59,17 @@ opus_int silk_control_SNR(
         /* 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 ] );
+                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;
             }
         }
     }
 
     return ret;
 }
--- a/media/libopus/silk/control_codec.c
+++ b/media/libopus/silk/control_codec.c
@@ -52,25 +52,24 @@ static opus_int silk_setup_fs(
 
 static opus_int silk_setup_complexity(
     silk_encoder_state              *psEncC,            /* I/O                      */
     opus_int                        Complexity          /* I                        */
 );
 
 static OPUS_INLINE opus_int silk_setup_LBRR(
     silk_encoder_state              *psEncC,            /* I/O                      */
-    const opus_int32                TargetRate_bps      /* I                        */
+    const silk_EncControlStruct     *encControl         /* 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;
@@ -120,17 +119,17 @@ opus_int silk_control_encoder(
     /********************************************/
     /* Set packet loss rate measured by farend  */
     /********************************************/
     psEnc->sCmn.PacketLoss_perc = encControl->packetLossPercentage;
 
     /********************************************/
     /* Set LBRR usage                           */
     /********************************************/
-    ret += silk_setup_LBRR( &psEnc->sCmn, TargetRate_bps );
+    ret += silk_setup_LBRR( &psEnc->sCmn, encControl );
 
     psEnc->sCmn.controlled_since_last_payload = 1;
 
     return ret;
 }
 
 static opus_int silk_setup_resamplers(
     silk_encoder_state_Fxx          *psEnc,             /* I/O                      */
@@ -239,28 +238,26 @@ static opus_int silk_setup_fs(
     }
 
     /* 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 */
         silk_memset( &psEnc->sShape,               0, sizeof( psEnc->sShape ) );
-        silk_memset( &psEnc->sPrefilt,             0, sizeof( psEnc->sPrefilt ) );
         silk_memset( &psEnc->sCmn.sNSQ,            0, sizeof( psEnc->sCmn.sNSQ ) );
         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_gain_Q16          = 65536;
         psEnc->sCmn.prevSignalType              = TYPE_NO_VOICE_ACTIVITY;
 
         psEnc->sCmn.fs_kHz = fs_kHz;
         if( psEnc->sCmn.fs_kHz == 8 ) {
             if( psEnc->sCmn.nb_subfr == MAX_NB_SUBFR ) {
@@ -288,23 +285,20 @@ static opus_int silk_setup_fs(
         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;
@@ -314,115 +308,116 @@ static 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 ) {
+    if( Complexity < 1 ) {
         psEncC->pitchEstimationComplexity       = SILK_PE_MIN_COMPLEX;
         psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.8, 16 );
         psEncC->pitchEstimationLPCOrder         = 6;
-        psEncC->shapingLPCOrder                 = 8;
+        psEncC->shapingLPCOrder                 = 12;
         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 < 2 ) {
+        psEncC->pitchEstimationComplexity       = SILK_PE_MID_COMPLEX;
+        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.76, 16 );
+        psEncC->pitchEstimationLPCOrder         = 8;
+        psEncC->shapingLPCOrder                 = 14;
+        psEncC->la_shape                        = 5 * psEncC->fs_kHz;
+        psEncC->nStatesDelayedDecision          = 1;
+        psEncC->useInterpolatedNLSFs            = 0;
+        psEncC->NLSF_MSVQ_Survivors             = 3;
+        psEncC->warping_Q16                     = 0;
+    } else if( Complexity < 3 ) {
+        psEncC->pitchEstimationComplexity       = SILK_PE_MIN_COMPLEX;
+        psEncC->pitchEstimationThreshold_Q16    = SILK_FIX_CONST( 0.8, 16 );
+        psEncC->pitchEstimationLPCOrder         = 6;
+        psEncC->shapingLPCOrder                 = 12;
+        psEncC->la_shape                        = 3 * psEncC->fs_kHz;
+        psEncC->nStatesDelayedDecision          = 2;
+        psEncC->useInterpolatedNLSFs            = 0;
         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->shapingLPCOrder                 = 14;
         psEncC->la_shape                        = 5 * psEncC->fs_kHz;
-        psEncC->nStatesDelayedDecision          = 1;
+        psEncC->nStatesDelayedDecision          = 2;
         psEncC->useInterpolatedNLSFs            = 0;
-        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->shapingLPCOrder                 = 16;
         psEncC->la_shape                        = 5 * psEncC->fs_kHz;
         psEncC->nStatesDelayedDecision          = 2;
         psEncC->useInterpolatedNLSFs            = 1;
-        psEncC->LTPQuantLowComplexity           = 0;
-        psEncC->NLSF_MSVQ_Survivors             = 8;
+        psEncC->NLSF_MSVQ_Survivors             = 6;
         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->shapingLPCOrder                 = 20;
         psEncC->la_shape                        = 5 * psEncC->fs_kHz;
         psEncC->nStatesDelayedDecision          = 3;
         psEncC->useInterpolatedNLSFs            = 1;
-        psEncC->LTPQuantLowComplexity           = 0;
-        psEncC->NLSF_MSVQ_Survivors             = 16;
+        psEncC->NLSF_MSVQ_Survivors             = 8;
         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->shapingLPCOrder                 = 24;
         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->NLSF_MSVQ_Survivors             = 16;
         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 OPUS_INLINE opus_int silk_setup_LBRR(
     silk_encoder_state          *psEncC,            /* I/O                      */
-    const opus_int32            TargetRate_bps      /* I                        */
+    const silk_EncControlStruct *encControl         /* I                        */
 )
 {
     opus_int   LBRR_in_previous_packet, ret = SILK_NO_ERROR;
-    opus_int32 LBRR_rate_thres_bps;
 
     LBRR_in_previous_packet = psEncC->LBRR_enabled;
-    psEncC->LBRR_enabled = 0;
-    if( psEncC->useInBandFEC && psEncC->PacketLoss_perc > 0 ) {
-        if( psEncC->fs_kHz == 8 ) {
-            LBRR_rate_thres_bps = LBRR_NB_MIN_RATE_BPS;
-        } else if( psEncC->fs_kHz == 12 ) {
-            LBRR_rate_thres_bps = LBRR_MB_MIN_RATE_BPS;
+    psEncC->LBRR_enabled = encControl->LBRR_coded;
+    if( psEncC->LBRR_enabled ) {
+        /* Set gain increase for coding LBRR excitation */
+        if( LBRR_in_previous_packet == 0 ) {
+            /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
+            psEncC->LBRR_GainIncreases = 7;
         } else {
-            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 */
-            if( LBRR_in_previous_packet == 0 ) {
-                /* Previous packet did not have LBRR, and was therefore coded at a higher bitrate */
-                psEncC->LBRR_GainIncreases = 7;
-            } else {
-                psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
-            }
-            psEncC->LBRR_enabled = 1;
+            psEncC->LBRR_GainIncreases = silk_max_int( 7 - silk_SMULWB( (opus_int32)psEncC->PacketLoss_perc, SILK_FIX_CONST( 0.4, 16 ) ), 2 );
         }
     }
 
     return ret;
 }
--- a/media/libopus/silk/debug.h
+++ b/media/libopus/silk/debug.h
@@ -34,33 +34,20 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #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
+/* Set to 1 to enable DEBUG_STORE_DATA() macros for dumping
+ * intermediate signals from the codec.
+ */
+#define SILK_DEBUG 0
 
 /* Flag for using timers */
 #define SILK_TIC_TOC    0
 
 
 #if SILK_TIC_TOC
 
 #if (defined(_WIN32) || defined(_WINCE))
--- a/media/libopus/silk/decode_core.c
+++ b/media/libopus/silk/decode_core.c
@@ -220,18 +220,16 @@ void silk_decode_core(
 
             /* Add prediction to LPC excitation */
             sLPC_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( pres_Q14[ i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
 
             /* Scale with gain */
             pxq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14[ MAX_LPC_ORDER + i ], Gain_Q10 ), 8 ) );
         }
 
-        /* DEBUG_STORE_DATA( dec.pcm, pxq, psDec->subfr_length * sizeof( opus_int16 ) ) */
-
         /* Update LPC filter state */
         silk_memcpy( sLPC_Q14, &sLPC_Q14[ psDec->subfr_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
         pexc_Q14 += psDec->subfr_length;
         pxq      += psDec->subfr_length;
     }
 
     /* Save LPC state */
     silk_memcpy( psDec->sLPC_Q14_buf, sLPC_Q14, MAX_LPC_ORDER * sizeof( opus_int32 ) );
--- a/media/libopus/silk/decode_frame.c
+++ b/media/libopus/silk/decode_frame.c
@@ -92,16 +92,17 @@ opus_int silk_decode_frame(
         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 */
+        psDec->indices.signalType = psDec->prevSignalType;
         silk_PLC( psDec, psDecCtrl, pOut, 1, arch );
     }
 
     /*************************/
     /* Update output buffer. */
     /*************************/
     silk_assert( psDec->ltp_mem_length >= psDec->frame_length );
     mv_len = psDec->ltp_mem_length - psDec->frame_length;
--- a/media/libopus/silk/decode_parameters.c
+++ b/media/libopus/silk/decode_parameters.c
@@ -47,34 +47,34 @@ void silk_decode_parameters(
         &psDec->LastGainIndex, condCoding == CODE_CONDITIONALLY, 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 );
+    silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 1 ], pNLSF_Q15, psDec->LPC_order, psDec->arch );
 
     /* 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 );
+        silk_NLSF2A( psDecCtrl->PredCoef_Q12[ 0 ], pNLSF0_Q15, psDec->LPC_order, psDec->arch );
     } 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 */
--- a/media/libopus/silk/define.h
+++ b/media/libopus/silk/define.h
@@ -51,16 +51,17 @@ extern "C"
 /* 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 */
+#define DTX_ACTIVITY_THRESHOLD                  0.1f
 
 /* Maximum sampling frequency */
 #define MAX_FS_KHZ                              16
 #define MAX_API_FS_KHZ                          48
 
 /* Signal types */
 #define TYPE_NO_VOICE_ACTIVITY                  0
 #define TYPE_UNVOICED                           1
@@ -142,47 +143,42 @@ extern "C"
 
 /* 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 MAX_SHAPE_LPC_ORDER                     24
 
 #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 )
+#define DECISION_DELAY                          40
 
 /* 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 SILK_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
 
 /***************************/
 /* Voice activity detector */
 /***************************/
 #define VAD_N_BANDS                             4
 
 #define VAD_INTERNAL_SUBFRAMES_LOG2             2
 #define VAD_INTERNAL_SUBFRAMES                  ( 1 << VAD_INTERNAL_SUBFRAMES_LOG2 )
@@ -200,17 +196,16 @@ extern "C"
 /* 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)*/
--- a/media/libopus/silk/enc_API.c
+++ b/media/libopus/silk/enc_API.c
@@ -228,21 +228,20 @@ opus_int silk_Encode(                   
         /* Make sure no more than one packet can be produced */
         if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) {
             silk_assert( 0 );
             RESTORE_STACK;
             return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
         }
     }
 
-    TargetRate_bps = silk_RSHIFT32( encControl->bitRate, encControl->nChannelsInternal - 1 );
     for( n = 0; n < encControl->nChannelsInternal; n++ ) {
         /* Force the side channel to the same rate as the mid */
         opus_int force_fs_kHz = (n==1) ? psEnc->state_Fxx[0].sCmn.fs_kHz : 0;
-        if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, TargetRate_bps, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
+        if( ( ret = silk_control_encoder( &psEnc->state_Fxx[ n ], encControl, psEnc->allowBandwidthSwitch, n, force_fs_kHz ) ) != 0 ) {
             silk_assert( 0 );
             RESTORE_STACK;
             return ret;
         }
         if( psEnc->state_Fxx[n].sCmn.first_frame_after_reset || transition ) {
             for( i = 0; i < psEnc->state_Fxx[ 0 ].sCmn.nFramesPerPacket; i++ ) {
                 psEnc->state_Fxx[ n ].sCmn.LBRR_flags[ i ] = 0;
             }
@@ -411,17 +410,16 @@ opus_int silk_Encode(                   
                 silk_stereo_LR_to_MS( &psEnc->sStereo, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ 2 ], &psEnc->state_Fxx[ 1 ].sCmn.inputBuf[ 2 ],
                     psEnc->sStereo.predIx[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ], &psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ],
                     MStargetRates_bps, TargetRate_bps, psEnc->state_Fxx[ 0 ].sCmn.speech_activity_Q8, encControl->toMono,
                     psEnc->state_Fxx[ 0 ].sCmn.fs_kHz, psEnc->state_Fxx[ 0 ].sCmn.frame_length );
                 if( psEnc->sStereo.mid_only_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] == 0 ) {
                     /* Reset side channel encoder memory for first frame with side coding */
                     if( psEnc->prev_decode_only_middle == 1 ) {
                         silk_memset( &psEnc->state_Fxx[ 1 ].sShape,               0, sizeof( psEnc->state_Fxx[ 1 ].sShape ) );
-                        silk_memset( &psEnc->state_Fxx[ 1 ].sPrefilt,             0, sizeof( psEnc->state_Fxx[ 1 ].sPrefilt ) );
                         silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sNSQ,            0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sNSQ ) );
                         silk_memset( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15,   0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.prev_NLSFq_Q15 ) );
                         silk_memset( &psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State, 0, sizeof( psEnc->state_Fxx[ 1 ].sCmn.sLP.In_LP_State ) );
                         psEnc->state_Fxx[ 1 ].sCmn.prevLag                 = 100;
                         psEnc->state_Fxx[ 1 ].sCmn.sNSQ.lagPrev            = 100;
                         psEnc->state_Fxx[ 1 ].sShape.LastGainIndex         = 10;
                         psEnc->state_Fxx[ 1 ].sCmn.prevSignalType          = TYPE_NO_VOICE_ACTIVITY;
                         psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16      = 65536;
@@ -552,12 +550,16 @@ opus_int silk_Encode(                   
         encControl->payloadSize_ms = tmp_payloadSize_ms;
         encControl->complexity = tmp_complexity;
         for( n = 0; n < encControl->nChannelsInternal; n++ ) {
             psEnc->state_Fxx[ n ].sCmn.controlled_since_last_payload = 0;
             psEnc->state_Fxx[ n ].sCmn.prefillFlag = 0;
         }
     }
 
+    encControl->signalType = psEnc->state_Fxx[0].sCmn.indices.signalType;
+    encControl->offset = silk_Quantization_Offsets_Q10
+                         [ psEnc->state_Fxx[0].sCmn.indices.signalType >> 1 ]
+                         [ psEnc->state_Fxx[0].sCmn.indices.quantOffsetType ];
     RESTORE_STACK;
     return ret;
 }
 
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/fixed/arm/warped_autocorrelation_FIX_arm.h
@@ -0,0 +1,68 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifndef SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
+# define SILK_WARPED_AUTOCORRELATION_FIX_ARM_H
+
+# include "celt/arm/armcpu.h"
+
+# if defined(FIXED_POINT)
+
+#  if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+void silk_warped_autocorrelation_FIX_neon(
+          opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
+          opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
+    const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
+    const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
+    const opus_int                  length,                                 /* I    Length of input                                                             */
+    const opus_int                  order                                   /* I    Correlation order (even)                                                    */
+);
+
+#  if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+#   define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+#   define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+    ((void)(arch), PRESUME_NEON(silk_warped_autocorrelation_FIX)(corr, scale, input, warping_Q16, length, order))
+#  endif
+#  endif
+
+#  if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
+/*Is run-time CPU detection enabled on this platform?*/
+#   if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const SILK_WARPED_AUTOCORRELATION_FIX_IMPL[OPUS_ARCHMASK+1])(opus_int32*, opus_int*, const opus_int16*, const opus_int, const opus_int, const opus_int);
+#    define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+#    define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+    ((*SILK_WARPED_AUTOCORRELATION_FIX_IMPL[(arch)&OPUS_ARCHMASK])(corr, scale, input, warping_Q16, length, order))
+#   elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#    define OVERRIDE_silk_warped_autocorrelation_FIX (1)
+#    define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+    ((void)(arch), silk_warped_autocorrelation_FIX_neon(corr, scale, input, warping_Q16, length, order))
+#   endif
+#  endif
+
+# endif /* end FIXED_POINT */
+
+#endif /* end SILK_WARPED_AUTOCORRELATION_FIX_ARM_H */
new file mode 100644
--- /dev/null
+++ b/media/libopus/silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c
@@ -0,0 +1,260 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc., Jean-Marc Valin
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <arm_neon.h>
+#ifdef OPUS_CHECK_ASM
+# include <string.h>
+#endif
+#include "stack_alloc.h"
+#include "main_FIX.h"
+
+static OPUS_INLINE void calc_corr( const opus_int32 *const input_QS, opus_int64 *const corr_QC, const opus_int offset, const int32x4_t state_QS_s32x4 )
+{
+    int64x2_t corr_QC_s64x2[ 2 ], t_s64x2[ 2 ];
+    const int32x4_t input_QS_s32x4 = vld1q_s32( input_QS + offset );
+    corr_QC_s64x2[ 0 ] = vld1q_s64( corr_QC + offset + 0 );
+    corr_QC_s64x2[ 1 ] = vld1q_s64( corr_QC + offset + 2 );
+    t_s64x2[ 0 ] = vmull_s32( vget_low_s32( state_QS_s32x4 ), vget_low_s32( input_QS_s32x4 ) );
+    t_s64x2[ 1 ] = vmull_s32( vget_high_s32( state_QS_s32x4 ), vget_high_s32( input_QS_s32x4 ) );
+    corr_QC_s64x2[ 0 ] = vsraq_n_s64( corr_QC_s64x2[ 0 ], t_s64x2[ 0 ], 2 * QS - QC );
+    corr_QC_s64x2[ 1 ] = vsraq_n_s64( corr_QC_s64x2[ 1 ], t_s64x2[ 1 ], 2 * QS - QC );
+    vst1q_s64( corr_QC + offset + 0, corr_QC_s64x2[ 0 ] );
+    vst1q_s64( corr_QC + offset + 2, corr_QC_s64x2[ 1 ] );
+}
+
+static OPUS_INLINE int32x4_t calc_state( const int32x4_t state_QS0_s32x4, const int32x4_t state_QS0_1_s32x4, const int32x4_t state_QS1_1_s32x4, const int32x4_t warping_Q16_s32x4 )
+{
+    int32x4_t t_s32x4 = vsubq_s32( state_QS0_s32x4, state_QS0_1_s32x4 );
+    t_s32x4 = vqdmulhq_s32( t_s32x4, warping_Q16_s32x4 );
+    return vaddq_s32( state_QS1_1_s32x4, t_s32x4 );
+}
+
+void silk_warped_autocorrelation_FIX_neon(
+          opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
+          opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
+    const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
+    const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
+    const opus_int                  length,                                 /* I    Length of input                                                             */
+    const opus_int                  order                                   /* I    Correlation order (even)                                                    */
+)
+{
+    if( ( MAX_SHAPE_LPC_ORDER > 24 ) || ( order < 6 ) ) {
+        silk_warped_autocorrelation_FIX_c( corr, scale, input, warping_Q16, length, order );
+    } else {
+        opus_int       n, i, lsh;
+        opus_int64     corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 }; /* In reverse order */
+        opus_int64     corr_QC_orderT;
+        int64x2_t      lsh_s64x2;
+        const opus_int orderT = ( order + 3 ) & ~3;
+        opus_int64     *corr_QCT;
+        opus_int32     *input_QS;
+        VARDECL( opus_int32, input_QST );
+        VARDECL( opus_int32, state );
+        SAVE_STACK;
+
+        /* Order must be even */
+        silk_assert( ( order & 1 ) == 0 );
+        silk_assert( 2 * QS - QC >= 0 );
+
+        ALLOC( input_QST, length + 2 * MAX_SHAPE_LPC_ORDER, opus_int32 );
+
+        input_QS = input_QST;
+        /* input_QS has zero paddings in the beginning and end. */
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+
+        /* Loop over samples */
+        for( n = 0; n < length - 7; n += 8, input_QS += 8 ) {
+            const int16x8_t t0_s16x4 = vld1q_s16( input + n );
+            vst1q_s32( input_QS + 0, vshll_n_s16( vget_low_s16( t0_s16x4 ), QS ) );
+            vst1q_s32( input_QS + 4, vshll_n_s16( vget_high_s16( t0_s16x4 ), QS ) );
+        }
+        for( ; n < length; n++, input_QS++ ) {
+            input_QS[ 0 ] = silk_LSHIFT32( (opus_int32)input[ n ], QS );
+        }
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS += 4;
+        vst1q_s32( input_QS, vdupq_n_s32( 0 ) );
+        input_QS = input_QST + MAX_SHAPE_LPC_ORDER - orderT;
+
+        /* The following loop runs ( length + order ) times, with ( order ) extra epilogues.                  */
+        /* The zero paddings in input_QS guarantee corr_QC's correctness even with the extra epilogues.       */
+        /* The values of state_QS will be polluted by the extra epilogues, however they are temporary values. */
+
+        /* Keep the C code here to help understand the intrinsics optimization. */
+        /*
+        {
+            opus_int32 state_QS[ 2 ][ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
+            opus_int32 *state_QST[ 3 ];
+            state_QST[ 0 ] = state_QS[ 0 ];
+            state_QST[ 1 ] = state_QS[ 1 ];
+            for( n = 0; n < length + order; n++, input_QS++ ) {
+                state_QST[ 0 ][ orderT ] = input_QS[ orderT ];
+                for( i = 0; i < orderT; i++ ) {
+                    corr_QC[ i ] += silk_RSHIFT64( silk_SMULL( state_QST[ 0 ][ i ], input_QS[ i ] ), 2 * QS - QC );
+                    state_QST[ 1 ][ i ] = silk_SMLAWB( state_QST[ 1 ][ i + 1 ], state_QST[ 0 ][ i ] - state_QST[ 0 ][ i + 1 ], warping_Q16 );
+                }
+                state_QST[ 2 ] = state_QST[ 0 ];
+                state_QST[ 0 ] = state_QST[ 1 ];
+                state_QST[ 1 ] = state_QST[ 2 ];
+            }
+        }
+        */
+
+        {
+            const int32x4_t warping_Q16_s32x4 = vdupq_n_s32( warping_Q16 << 15 );
+            const opus_int32 *in = input_QS + orderT;
+            opus_int o = orderT;
+            int32x4_t state_QS_s32x4[ 3 ][ 2 ];
+
+            ALLOC( state, length + orderT, opus_int32 );
+            state_QS_s32x4[ 2 ][ 1 ] = vdupq_n_s32( 0 );
+
+            /* Calculate 8 taps of all inputs in each loop. */
+            do {
+                state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 0 ][ 1 ] =
+                state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 1 ][ 1 ] = vdupq_n_s32( 0 );
+                n = 0;
+                do {
+                    calc_corr( input_QS + n, corr_QC, o - 8, state_QS_s32x4[ 0 ][ 0 ] );
+                    calc_corr( input_QS + n, corr_QC, o - 4, state_QS_s32x4[ 0 ][ 1 ] );
+                    state_QS_s32x4[ 2 ][ 1 ] = vld1q_s32( in + n );
+                    vst1q_lane_s32( state + n, state_QS_s32x4[ 0 ][ 0 ], 0 );
+                    state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 0 ][ 1 ], 1 );
+                    state_QS_s32x4[ 2 ][ 1 ] = vextq_s32( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], 1 );
+                    state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 );
+                    state_QS_s32x4[ 0 ][ 1 ] = calc_state( state_QS_s32x4[ 0 ][ 1 ], state_QS_s32x4[ 2 ][ 1 ], state_QS_s32x4[ 1 ][ 1 ], warping_Q16_s32x4 );
+                    state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ];
+                    state_QS_s32x4[ 1 ][ 1 ] = state_QS_s32x4[ 2 ][ 1 ];
+                } while( ++n < ( length + order ) );
+                in = state;
+                o -= 8;
+            } while( o > 4 );
+
+            if( o ) {
+                /* Calculate the last 4 taps of all inputs. */
+                opus_int32 *stateT = state;
+                silk_assert( o == 4 );
+                state_QS_s32x4[ 0 ][ 0 ] = state_QS_s32x4[ 1 ][ 0 ] = vdupq_n_s32( 0 );
+                n = length + order;
+                do {
+                    calc_corr( input_QS, corr_QC, 0, state_QS_s32x4[ 0 ][ 0 ] );
+                    state_QS_s32x4[ 2 ][ 0 ] = vld1q_s32( stateT );
+                    vst1q_lane_s32( stateT, state_QS_s32x4[ 0 ][ 0 ], 0 );
+                    state_QS_s32x4[ 2 ][ 0 ] = vextq_s32( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], 1 );
+                    state_QS_s32x4[ 0 ][ 0 ] = calc_state( state_QS_s32x4[ 0 ][ 0 ], state_QS_s32x4[ 2 ][ 0 ], state_QS_s32x4[ 1 ][ 0 ], warping_Q16_s32x4 );
+                    state_QS_s32x4[ 1 ][ 0 ] = state_QS_s32x4[ 2 ][ 0 ];
+                    input_QS++;
+                    stateT++;
+                } while( --n );
+            }
+        }
+
+        {
+            const opus_int16 *inputT = input;
+            int32x4_t t_s32x4;
+            int64x1_t t_s64x1;
+            int64x2_t t_s64x2 = vdupq_n_s64( 0 );
+            for( n = 0; n <= length - 8; n += 8 ) {
+                int16x8_t input_s16x8 = vld1q_s16( inputT );
+                t_s32x4 = vmull_s16( vget_low_s16( input_s16x8 ), vget_low_s16( input_s16x8 ) );
+                t_s32x4 = vmlal_s16( t_s32x4, vget_high_s16( input_s16x8 ), vget_high_s16( input_s16x8 ) );
+                t_s64x2 = vaddw_s32( t_s64x2, vget_low_s32( t_s32x4 ) );
+                t_s64x2 = vaddw_s32( t_s64x2, vget_high_s32( t_s32x4 ) );
+                inputT += 8;
+            }
+            t_s64x1 = vadd_s64( vget_low_s64( t_s64x2 ), vget_high_s64( t_s64x2 ) );
+            corr_QC_orderT = vget_lane_s64( t_s64x1, 0 );
+            for( ; n < length; n++ ) {
+                corr_QC_orderT += silk_SMULL( input[ n ], input[ n ] );
+            }
+            corr_QC_orderT = silk_LSHIFT64( corr_QC_orderT, QC );
+            corr_QC[ orderT ] = corr_QC_orderT;
+        }
+
+        corr_QCT = corr_QC + orderT - order;
+        lsh = silk_CLZ64( corr_QC_orderT ) - 35;
+        lsh = silk_LIMIT( lsh, -12 - QC, 30 - QC );
+        *scale = -( QC + lsh );
+        silk_assert( *scale >= -30 && *scale <= 12 );
+        lsh_s64x2 = vdupq_n_s64( lsh );
+        for( i = 0; i <= order - 3; i += 4 ) {
+            int32x4_t corr_s32x4;
+            int64x2_t corr_QC0_s64x2, corr_QC1_s64x2;
+            corr_QC0_s64x2 = vld1q_s64( corr_QCT + i );
+            corr_QC1_s64x2 = vld1q_s64( corr_QCT + i + 2 );
+            corr_QC0_s64x2 = vshlq_s64( corr_QC0_s64x2, lsh_s64x2 );
+            corr_QC1_s64x2 = vshlq_s64( corr_QC1_s64x2, lsh_s64x2 );
+            corr_s32x4     = vcombine_s32( vmovn_s64( corr_QC1_s64x2 ), vmovn_s64( corr_QC0_s64x2 ) );
+            corr_s32x4     = vrev64q_s32( corr_s32x4 );
+            vst1q_s32( corr + order - i - 3, corr_s32x4 );
+        }
+        if( lsh >= 0 ) {
+            for( ; i < order + 1; i++ ) {
+                corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_LSHIFT64( corr_QCT[ i ], lsh ) );
+            }
+        } else {
+            for( ; i < order + 1; i++ ) {
+                corr[ order - i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QCT[ i ], -lsh ) );
+            }
+        }
+        silk_assert( corr_QCT[ order ] >= 0 ); /* If breaking, decrease QC*/
+        RESTORE_STACK;
+    }
+
+#ifdef OPUS_CHECK_ASM
+    {
+        opus_int32 corr_c[ MAX_SHAPE_LPC_ORDER + 1 ];
+        opus_int   scale_c;
+        silk_warped_autocorrelation_FIX_c( corr_c, &scale_c, input, warping_Q16, length, order );
+        silk_assert( !memcmp( corr_c, corr, sizeof( corr_c[ 0 ] ) * ( order + 1 ) ) );
+        silk_assert( scale_c == *scale );
+    }
+#endif
+}
--- a/media/libopus/silk/fixed/burg_modified_FIX.c
+++ b/media/libopus/silk/fixed/burg_modified_FIX.c
@@ -32,17 +32,17 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "SigProc_FIX.h"
 #include "define.h"
 #include "tuning_parameters.h"
 #include "pitch.h"
 
 #define MAX_FRAME_SIZE              384             /* subfr_length * nb_subfr = ( 0.005 * 16000 + 16 ) * 4 = 384 */
 
 #define QA                          25
-#define N_BITS_HEAD_ROOM            2
+#define N_BITS_HEAD_ROOM            3
 #define MIN_RSHIFTS                 -16
 #define MAX_RSHIFTS                 (32 - QA)
 
 /* Compute reflection coefficients from input signal */
 void silk_burg_modified_c(
     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)                      */
--- a/media/libopus/silk/fixed/corrMatrix_FIX.c
+++ b/media/libopus/silk/fixed/corrMatrix_FIX.c
@@ -53,17 +53,17 @@ void silk_corrVector_FIX(
     ptr1 = &x[ order - 1 ]; /* Points to first sample of column 0 of X: X[:,0] */
     ptr2 = t;
     /* Calculate X'*t */
     if( rshifts > 0 ) {
         /* Right shifting used */
         for( lag = 0; lag < order; lag++ ) {
             inner_prod = 0;
             for( i = 0; i < L; i++ ) {
-                inner_prod += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
+                inner_prod = silk_ADD_RSHIFT32( inner_prod, silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts );
             }
             Xt[ lag ] = inner_prod; /* X[:,lag]'*t */
             ptr1--; /* Go to next column of X */
         }
     } else {
         silk_assert( rshifts == 0 );
         for( lag = 0; lag < order; lag++ ) {
             Xt[ lag ] = silk_inner_prod_aligned( ptr1, ptr2, L, arch ); /* X[:,lag]'*t */
@@ -72,71 +72,64 @@ void silk_corrVector_FIX(
     }
 }
 
 /* Calculates correlation matrix X'*X */
 void silk_corrMatrix_FIX(
     const opus_int16                *x,                                     /* I    x vector [L + order - 1] used to form data matrix X                         */
     const opus_int                  L,                                      /* I    Length of vectors                                                           */
     const opus_int                  order,                                  /* I    Max lag for correlation                                                     */
-    const opus_int                  head_room,                              /* I    Desired headroom                                                            */
     opus_int32                      *XX,                                    /* O    Pointer to X'*X correlation matrix [ order x order ]                        */
-    opus_int                        *rshifts,                               /* I/O  Right shifts of correlations                                                */
+    opus_int32                      *nrg,                                    /* O    Energy of x vector                                                            */
+    opus_int                        *rshifts,                               /* O    Right shifts of correlations and energy                                     */
     int                             arch                                    /* I    Run-time architecture                                                       */
 )
 {
-    opus_int         i, j, lag, rshifts_local, head_room_rshifts;
+    opus_int         i, j, lag;
     opus_int32       energy;
     const opus_int16 *ptr1, *ptr2;
 
     /* Calculate energy to find shift used to fit in 32 bits */
-    silk_sum_sqr_shift( &energy, &rshifts_local, x, L + order - 1 );
-    /* Add shifts to get the desired head room */
-    head_room_rshifts = silk_max( head_room - silk_CLZ32( energy ), 0 );
-
-    energy = silk_RSHIFT32( energy, head_room_rshifts );
-    rshifts_local += head_room_rshifts;
+    silk_sum_sqr_shift( nrg, rshifts, x, L + order - 1 );
+    energy = *nrg;
 
     /* Calculate energy of first column (0) of X: X[:,0]'*X[:,0] */
     /* Remove contribution of first order - 1 samples */
     for( i = 0; i < order - 1; i++ ) {
-        energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), rshifts_local );
-    }
-    if( rshifts_local < *rshifts ) {
-        /* Adjust energy */
-        energy = silk_RSHIFT32( energy, *rshifts - rshifts_local );
-        rshifts_local = *rshifts;
+        energy -= silk_RSHIFT32( silk_SMULBB( x[ i ], x[ i ] ), *rshifts );
     }
 
     /* Calculate energy of remaining columns of X: X[:,j]'*X[:,j] */
     /* Fill out the diagonal of the correlation matrix */
     matrix_ptr( XX, 0, 0, order ) = energy;
+    silk_assert( energy >= 0 );
     ptr1 = &x[ order - 1 ]; /* First sample of column 0 of X */
     for( j = 1; j < order; j++ ) {
-        energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), rshifts_local ) );
-        energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), rshifts_local ) );
+        energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr1[ L - j ] ), *rshifts ) );
+        energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr1[ -j ] ), *rshifts ) );
         matrix_ptr( XX, j, j, order ) = energy;
+        silk_assert( energy >= 0 );
     }
 
     ptr2 = &x[ order - 2 ]; /* First sample of column 1 of X */
     /* Calculate the remaining elements of the correlation matrix */
-    if( rshifts_local > 0 ) {
+    if( *rshifts > 0 ) {
         /* Right shifting used */
         for( lag = 1; lag < order; lag++ ) {
             /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
             energy = 0;
             for( i = 0; i < L; i++ ) {
-                energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), rshifts_local );
+                energy += silk_RSHIFT32( silk_SMULBB( ptr1[ i ], ptr2[i] ), *rshifts );
             }
             /* Calculate remaining off diagonal: X[:,j]'*X[:,j + lag] */
             matrix_ptr( XX, lag, 0, order ) = energy;
             matrix_ptr( XX, 0, lag, order ) = energy;
             for( j = 1; j < ( order - lag ); j++ ) {
-                energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), rshifts_local ) );
-                energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), rshifts_local ) );
+                energy = silk_SUB32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ), *rshifts ) );
+                energy = silk_ADD32( energy, silk_RSHIFT32( silk_SMULBB( ptr1[ -j ], ptr2[ -j ] ), *rshifts ) );
                 matrix_ptr( XX, lag + j, j, order ) = energy;
                 matrix_ptr( XX, j, lag + j, order ) = energy;
             }
             ptr2--; /* Update pointer to first sample of next column (lag) in X */
         }
     } else {
         for( lag = 1; lag < order; lag++ ) {
             /* Inner product of column 0 and column lag: X[:,0]'*X[:,lag] */
@@ -148,11 +141,10 @@ void silk_corrMatrix_FIX(
                 energy = silk_SUB32( energy, silk_SMULBB( ptr1[ L - j ], ptr2[ L - j ] ) );
                 energy = silk_SMLABB( energy, ptr1[ -j ], ptr2[ -j ] );
                 matrix_ptr( XX, lag + j, j, order ) = energy;
                 matrix_ptr( XX, j, lag + j, order ) = energy;
             }
             ptr2--;/* Update pointer to first sample of next column (lag) in X */
         }
     }
-    *rshifts = rshifts_local;
 }
 
--- a/media/libopus/silk/fixed/encode_frame_FIX.c
+++ b/media/libopus/silk/fixed/encode_frame_FIX.c
@@ -24,25 +24,26 @@ CONTRACT, STRICT LIABILITY, OR TORT (INC
 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_FIX.h"
 #include "stack_alloc.h"
 #include "tuning_parameters.h"
 
 /* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate           */
 static OPUS_INLINE void silk_LBRR_encode_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
-    const opus_int32                xfw_Q3[],                               /* I    Input signal                                                                */
+    const opus_int16                x16[],                                  /* I    Input signal                                                                */
     opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
 );
 
 void silk_encode_do_VAD_FIX(
     silk_encoder_state_FIX          *psEnc                                  /* I/O  Pointer to Silk FIX encoder state                                           */
 )
 {
     /****************************/
@@ -89,16 +90,19 @@ opus_int silk_encode_frame_FIX(
     ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
     silk_nsq_state sNSQ_copy, sNSQ_copy2;
     opus_int32   seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
     opus_int32   gainsID, gainsID_lower, gainsID_upper;
     opus_int16   gainMult_Q8;
     opus_int16   ec_prevLagIndex_copy;
     opus_int     ec_prevSignalType_copy;
     opus_int8    LastGainIndex_copy2;
+    opus_int     gain_lock[ MAX_NB_SUBFR ] = {0};
+    opus_int16   best_gain_mult[ MAX_NB_SUBFR ];
+    opus_int     best_sum[ MAX_NB_SUBFR ];
     SAVE_STACK;
 
     /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
     LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
 
     psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
 
     /**************************************************************/
@@ -113,57 +117,50 @@ opus_int silk_encode_frame_FIX(
     silk_LP_variable_cutoff( &psEnc->sCmn.sLP, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length );
 
     /*******************************************/
     /* Copy new frame to front of input buffer */
     /*******************************************/
     silk_memcpy( x_frame + LA_SHAPE_MS * psEnc->sCmn.fs_kHz, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.frame_length * sizeof( opus_int16 ) );
 
     if( !psEnc->sCmn.prefillFlag ) {
-        VARDECL( opus_int32, xfw_Q3 );
         VARDECL( opus_int16, res_pitch );
         VARDECL( opus_uint8, ec_buf_copy );
         opus_int16 *res_pitch_frame;
 
         ALLOC( res_pitch,
                psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length
                    + psEnc->sCmn.ltp_mem_length, opus_int16 );
         /* start of pitch LPC residual frame */
         res_pitch_frame = res_pitch + psEnc->sCmn.ltp_mem_length;
 
         /*****************************************/
         /* Find pitch lags, initial LPC analysis */
         /*****************************************/
-        silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, psEnc->sCmn.arch );
+        silk_find_pitch_lags_FIX( psEnc, &sEncCtrl, res_pitch, x_frame - psEnc->sCmn.ltp_mem_length, psEnc->sCmn.arch );
 
         /************************/
         /* Noise shape analysis */
         /************************/
         silk_noise_shape_analysis_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, psEnc->sCmn.arch );
 
         /***************************************************/
         /* Find linear prediction coefficients (LPC + LTP) */
         /***************************************************/
-        silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding );
+        silk_find_pred_coefs_FIX( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
 
         /****************************************/
         /* Process gains                        */
         /****************************************/
         silk_process_gains_FIX( psEnc, &sEncCtrl, condCoding );
 
-        /*****************************************/
-        /* Prefiltering for noise shaper         */
-        /*****************************************/
-        ALLOC( xfw_Q3, psEnc->sCmn.frame_length, opus_int32 );
-        silk_prefilter_FIX( psEnc, &sEncCtrl, xfw_Q3, x_frame );
-
         /****************************************/
         /* Low Bitrate Redundant Encoding       */
         /****************************************/
-        silk_LBRR_encode_FIX( psEnc, &sEncCtrl, xfw_Q3, condCoding );
+        silk_LBRR_encode_FIX( psEnc, &sEncCtrl, x_frame, condCoding );
 
         /* Loop over quantizer and entropy coding to control bitrate */
         maxIter = 6;
         gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
         found_lower = 0;
         found_upper = 0;
         gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
         gainsID_lower = -1;
@@ -189,40 +186,71 @@ opus_int silk_encode_frame_FIX(
                     psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
                     psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
                 }
 
                 /*****************************************/
                 /* Noise shaping quantization            */
                 /*****************************************/
                 if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
-                    silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses,
-                           sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
+                    silk_NSQ_del_dec( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
+                           sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
                            sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
                            psEnc->sCmn.arch );
                 } else {
-                    silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, xfw_Q3, psEnc->sCmn.pulses,
-                            sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR2_Q13, sEncCtrl.HarmShapeGain_Q14,
+                    silk_NSQ( &psEnc->sCmn, &psEnc->sCmn.sNSQ, &psEnc->sCmn.indices, x_frame, psEnc->sCmn.pulses,
+                            sEncCtrl.PredCoef_Q12[ 0 ], sEncCtrl.LTPCoef_Q14, sEncCtrl.AR_Q13, sEncCtrl.HarmShapeGain_Q14,
                             sEncCtrl.Tilt_Q14, sEncCtrl.LF_shp_Q14, sEncCtrl.Gains_Q16, sEncCtrl.pitchL, sEncCtrl.Lambda_Q10, sEncCtrl.LTP_scale_Q14,
                             psEnc->sCmn.arch);
                 }
 
+                if ( iter == maxIter && !found_lower ) {
+                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
+                }
+
                 /****************************************/
                 /* Encode Parameters                    */
                 /****************************************/
                 silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
 
                 /****************************************/
                 /* Encode Excitation Signal             */
                 /****************************************/
                 silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
                     psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
 
                 nBits = ec_tell( psRangeEnc );
 
+                /* If we still bust after the last iteration, do some damage control. */
+                if ( iter == maxIter && !found_lower && nBits > maxBits ) {
+                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
+
+                    /* Keep gains the same as the last frame. */
+                    psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
+                    for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+                        psEnc->sCmn.indices.GainsIndices[ i ] = 4;
+                    }
+                    if (condCoding != CODE_CONDITIONALLY) {
+                       psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
+                    }
+                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
+                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
+                    /* Clear all pulses. */
+                    for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+                        psEnc->sCmn.pulses[ i ] = 0;
+                    }
+
+                    silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
+
+                    silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
+                        psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
+
+                    nBits = ec_tell( psRangeEnc );
+                }
+
                 if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
                     break;
                 }
             }
 
             if( iter == maxIter ) {
                 if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
                     /* Restore output state from earlier iteration that did meet the bitrate budget */
@@ -260,39 +288,65 @@ opus_int silk_encode_frame_FIX(
                     silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
                     LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
                 }
             } else {
                 /* Within 5 bits of budget: close enough */
                 break;
             }
 
+            if ( !found_lower && nBits > maxBits ) {
+                int j;
+                for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+                    int sum=0;
+                    for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
+                        sum += abs( psEnc->sCmn.pulses[j] );
+                    }
+                    if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
+                        best_sum[i] = sum;
+                        best_gain_mult[i] = gainMult_Q8;
+                    } else {
+                        gain_lock[i] = 1;
+                    }
+                }
+            }
             if( ( found_lower & found_upper ) == 0 ) {
                 /* Adjust gain according to high-rate rate/distortion curve */
-                opus_int32 gain_factor_Q16;
-                gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
-                gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
                 if( nBits > maxBits ) {
-                    gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
+                    if (gainMult_Q8 < 16384) {
+                        gainMult_Q8 *= 2;
+                    } else {
+                        gainMult_Q8 = 32767;
+                    }
+                } else {
+                    opus_int32 gain_factor_Q16;
+                    gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
+                    gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
                 }
-                gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
+
             } else {
                 /* Adjust gain by interpolating */
                 gainMult_Q8 = gainMult_lower + silk_DIV32_16( silk_MUL( gainMult_upper - gainMult_lower, maxBits - nBits_lower ), nBits_upper - nBits_lower );
                 /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
                 if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
                     gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
                 } else
                 if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
                     gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
                 }
             }
 
             for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
-                sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
+                opus_int16 tmp;
+                if ( gain_lock[i] ) {
+                    tmp = best_gain_mult[i];
+                } else {
+                    tmp = gainMult_Q8;
+                }
+                sEncCtrl.Gains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
             }
 
             /* Quantize gains */
             psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
             silk_gains_quant( psEnc->sCmn.indices.GainsIndices, sEncCtrl.Gains_Q16,
                   &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
 
             /* Unique identifier of gains vector */
@@ -326,17 +380,17 @@ opus_int silk_encode_frame_FIX(
     RESTORE_STACK;
     return ret;
 }
 
 /* Low-Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode excitation at lower bitrate  */
 static OPUS_INLINE void silk_LBRR_encode_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Pointer to Silk FIX encoder control struct                                  */
-    const opus_int32                xfw_Q3[],                               /* I    Input signal                                                                */
+    const opus_int16                x16[],                                  /* I    Input signal                                                                */
     opus_int                        condCoding                              /* I    The type of conditional coding used so far for this frame                   */
 )
 {
     opus_int32   TempGains_Q16[ MAX_NB_SUBFR ];
     SideInfoIndices *psIndices_LBRR = &psEnc->sCmn.indices_LBRR[ psEnc->sCmn.nFramesEncoded ];
     silk_nsq_state sNSQ_LBRR;
 
     /*******************************************/
@@ -365,23 +419,23 @@ static OPUS_INLINE void silk_LBRR_encode
         /* Overwrite unquantized gains with quantized gains */
         silk_gains_dequant( psEncCtrl->Gains_Q16, psIndices_LBRR->GainsIndices,
             &psEnc->sCmn.LBRRprevLastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
 
         /*****************************************/
         /* Noise shaping quantization            */
         /*****************************************/
         if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
-            silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3,
+            silk_NSQ_del_dec( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
                 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
-                psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
+                psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
                 psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
         } else {
-            silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, xfw_Q3,
+            silk_NSQ( &psEnc->sCmn, &sNSQ_LBRR, psIndices_LBRR, x16,
                 psEnc->sCmn.pulses_LBRR[ psEnc->sCmn.nFramesEncoded ], psEncCtrl->PredCoef_Q12[ 0 ], psEncCtrl->LTPCoef_Q14,
-                psEncCtrl->AR2_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
+                psEncCtrl->AR_Q13, psEncCtrl->HarmShapeGain_Q14, psEncCtrl->Tilt_Q14, psEncCtrl->LF_shp_Q14,
                 psEncCtrl->Gains_Q16, psEncCtrl->pitchL, psEncCtrl->Lambda_Q10, psEncCtrl->LTP_scale_Q14, psEnc->sCmn.arch );
         }
 
         /* Restore original gains */
         silk_memcpy( psEncCtrl->Gains_Q16, TempGains_Q16, psEnc->sCmn.nb_subfr * sizeof( opus_int32 ) );
     }
 }
--- a/media/libopus/silk/fixed/find_LPC_FIX.c
+++ b/media/libopus/silk/fixed/find_LPC_FIX.c
@@ -87,17 +87,17 @@ void silk_find_LPC_FIX(
         ALLOC( LPC_res, 2 * subfr_length, opus_int16 );
 
         /* Search over interpolation indices to find the one with lowest residual energy */
         for( k = 3; k >= 0; k-- ) {
             /* Interpolate NLSFs for first half */
             silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
 
             /* Convert to LPC for residual energy evaluation */
-            silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder );
+            silk_NLSF2A( a_tmp_Q12, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
 
             /* Calculate residual energy with NLSF interpolation */
             silk_LPC_analysis_filter( LPC_res, x, a_tmp_Q12, 2 * subfr_length, psEncC->predictLPCOrder, psEncC->arch );
 
             silk_sum_sqr_shift( &res_nrg0, &rshift0, LPC_res + psEncC->predictLPCOrder,                subfr_length - psEncC->predictLPCOrder );
             silk_sum_sqr_shift( &res_nrg1, &rshift1, LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder );
 
             /* Add subframe energies from first half frame */
--- a/media/libopus/silk/fixed/find_LTP_FIX.c
+++ b/media/libopus/silk/fixed/find_LTP_FIX.c
@@ -27,219 +27,73 @@ POSSIBILITY OF SUCH DAMAGE.
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "main_FIX.h"
 #include "tuning_parameters.h"
 
-/* Head room for correlations */
-#define LTP_CORRS_HEAD_ROOM                             2
-
-void silk_fit_LTP(
-    opus_int32 LTP_coefs_Q16[ LTP_ORDER ],
-    opus_int16 LTP_coefs_Q14[ LTP_ORDER ]
-);
-
 void silk_find_LTP_FIX(
-    opus_int16                      b_Q14[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    LTP coefs                                                                   */
-    opus_int32                      WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization                                           */
-    opus_int                        *LTPredCodGain_Q7,                      /* O    LTP coding gain                                                             */
-    const opus_int16                r_lpc[],                                /* I    residual signal after LPC signal + state for first 10 ms                    */
+    opus_int32                      XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Correlation matrix                                               */
+    opus_int32                      xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ],  /* O    Correlation vector                                                          */
+    const opus_int16                r_ptr[],                                /* I    Residual signal after LPC                                                   */
     const opus_int                  lag[ MAX_NB_SUBFR ],                    /* I    LTP lags                                                                    */
-    const opus_int32                Wght_Q15[ MAX_NB_SUBFR ],               /* I    weights                                                                     */
-    const opus_int                  subfr_length,                           /* I    subframe length                                                             */
-    const opus_int                  nb_subfr,                               /* I    number of subframes                                                         */
-    const opus_int                  mem_offset,                             /* I    number of samples in LTP memory                                             */
-    opus_int                        corr_rshifts[ MAX_NB_SUBFR ],           /* O    right shifts applied to correlations                                        */
+    const opus_int                  subfr_length,                           /* I    Subframe length                                                             */
+    const opus_int                  nb_subfr,                               /* I    Number of subframes                                                         */
     int                             arch                                    /* I    Run-time architecture                                                       */
 )
 {
-    opus_int   i, k, lshift;
-    const opus_int16 *r_ptr, *lag_ptr;
-    opus_int16 *b_Q14_ptr;
-
-    opus_int32 regu;
-    opus_int32 *WLTP_ptr;
-    opus_int32 b_Q16[ LTP_ORDER ], delta_b_Q14[ LTP_ORDER ], d_Q14[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], g_Q26;
-    opus_int32 w[ MAX_NB_SUBFR ], WLTP_max, max_abs_d_Q14, max_w_bits;
+    opus_int   i, k, extra_shifts;
+    opus_int   xx_shifts, xX_shifts, XX_shifts;
+    const opus_int16 *lag_ptr;
+    opus_int32 *XXLTP_Q17_ptr, *xXLTP_Q17_ptr;
+    opus_int32 xx, nrg, temp;
 
-    opus_int32 temp32, denom32;
-    opus_int   extra_shifts;
-    opus_int   rr_shifts, maxRshifts, maxRshifts_wxtra, LZs;
-    opus_int32 LPC_res_nrg, LPC_LTP_res_nrg, div_Q16;
-    opus_int32 Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
-    opus_int32 wd, m_Q12;
-
-    b_Q14_ptr = b_Q14;
-    WLTP_ptr  = WLTP;
-    r_ptr     = &r_lpc[ mem_offset ];
+    xXLTP_Q17_ptr = xXLTP_Q17;
+    XXLTP_Q17_ptr = XXLTP_Q17;
     for( k = 0; k < nb_subfr; k++ ) {
         lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
 
-        silk_sum_sqr_shift( &rr[ k ], &rr_shifts, r_ptr, subfr_length ); /* rr[ k ] in Q( -rr_shifts ) */
-
-        /* Assure headroom */
-        LZs = silk_CLZ32( rr[k] );
-        if( LZs < LTP_CORRS_HEAD_ROOM ) {
-            rr[ k ] = silk_RSHIFT_ROUND( rr[ k ], LTP_CORRS_HEAD_ROOM - LZs );
-            rr_shifts += ( LTP_CORRS_HEAD_ROOM - LZs );
-        }
-        corr_rshifts[ k ] = rr_shifts;
-        silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, LTP_CORRS_HEAD_ROOM, WLTP_ptr, &corr_rshifts[ k ], arch );  /* WLTP_fix_ptr in Q( -corr_rshifts[ k ] ) */
-
-        /* The correlation vector always has lower max abs value than rr and/or RR so head room is assured */
-        silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr, corr_rshifts[ k ], arch );  /* Rr_fix_ptr   in Q( -corr_rshifts[ k ] ) */
-        if( corr_rshifts[ k ] > rr_shifts ) {
-            rr[ k ] = silk_RSHIFT( rr[ k ], corr_rshifts[ k ] - rr_shifts ); /* rr[ k ] in Q( -corr_rshifts[ k ] ) */
-        }
-        silk_assert( rr[ k ] >= 0 );
-
-        regu = 1;
-        regu = silk_SMLAWB( regu, rr[ k ], SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
-        regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
-        regu = silk_SMLAWB( regu, matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER ), SILK_FIX_CONST( LTP_DAMPING/3, 16 ) );
-        silk_regularize_correlations_FIX( WLTP_ptr, &rr[k], regu, LTP_ORDER );
-
-        silk_solve_LDL_FIX( WLTP_ptr, LTP_ORDER, Rr, b_Q16 ); /* WLTP_fix_ptr and Rr_fix_ptr both in Q(-corr_rshifts[k]) */
-
-        /* Limit and store in Q14 */
-        silk_fit_LTP( b_Q16, b_Q14_ptr );
-
-        /* Calculate residual energy */
-        nrg[ k ] = silk_residual_energy16_covar_FIX( b_Q14_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER, 14 ); /* nrg_fix in Q( -corr_rshifts[ k ] ) */
-
-        /* temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length ); */
-        extra_shifts = silk_min_int( corr_rshifts[ k ], LTP_CORRS_HEAD_ROOM );
-        denom32 = silk_LSHIFT_SAT32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 + extra_shifts ) + /* Q( -corr_rshifts[ k ] + extra_shifts ) */
-            silk_RSHIFT( silk_SMULWB( (opus_int32)subfr_length, 655 ), corr_rshifts[ k ] - extra_shifts );    /* Q( -corr_rshifts[ k ] + extra_shifts ) */
-        denom32 = silk_max( denom32, 1 );
-        silk_assert( ((opus_int64)Wght_Q15[ k ] << 16 ) < silk_int32_MAX );                       /* Wght always < 0.5 in Q0 */
-        temp32 = silk_DIV32( silk_LSHIFT( (opus_int32)Wght_Q15[ k ], 16 ), denom32 );             /* Q( 15 + 16 + corr_rshifts[k] - extra_shifts ) */
-        temp32 = silk_RSHIFT( temp32, 31 + corr_rshifts[ k ] - extra_shifts - 26 );               /* Q26 */
-
-        /* Limit temp such that the below scaling never wraps around */
-        WLTP_max = 0;
-        for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
-            WLTP_max = silk_max( WLTP_ptr[ i ], WLTP_max );
-        }
-        lshift = silk_CLZ32( WLTP_max ) - 1 - 3; /* keep 3 bits free for vq_nearest_neighbor_fix */
-        silk_assert( 26 - 18 + lshift >= 0 );
-        if( 26 - 18 + lshift < 31 ) {
-            temp32 = silk_min_32( temp32, silk_LSHIFT( (opus_int32)1, 26 - 18 + lshift ) );
-        }
-
-        silk_scale_vector32_Q26_lshift_18( WLTP_ptr, temp32, LTP_ORDER * LTP_ORDER ); /* WLTP_ptr in Q( 18 - corr_rshifts[ k ] ) */
-
-        w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER/2, LTP_ORDER/2, LTP_ORDER ); /* w in Q( 18 - corr_rshifts[ k ] ) */
-        silk_assert( w[k] >= 0 );
-
-        r_ptr     += subfr_length;
-        b_Q14_ptr += LTP_ORDER;
-        WLTP_ptr  += LTP_ORDER * LTP_ORDER;
-    }
-
-    maxRshifts = 0;
-    for( k = 0; k < nb_subfr; k++ ) {
-        maxRshifts = silk_max_int( corr_rshifts[ k ], maxRshifts );
-    }
-
-    /* Compute LTP coding gain */
-    if( LTPredCodGain_Q7 != NULL ) {
-        LPC_LTP_res_nrg = 0;
-        LPC_res_nrg     = 0;
-        silk_assert( LTP_CORRS_HEAD_ROOM >= 2 ); /* Check that no overflow will happen when adding */
-        for( k = 0; k < nb_subfr; k++ ) {
-            LPC_res_nrg     = silk_ADD32( LPC_res_nrg,     silk_RSHIFT( silk_ADD32( silk_SMULWB(  rr[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
-            LPC_LTP_res_nrg = silk_ADD32( LPC_LTP_res_nrg, silk_RSHIFT( silk_ADD32( silk_SMULWB( nrg[ k ], Wght_Q15[ k ] ), 1 ), 1 + ( maxRshifts - corr_rshifts[ k ] ) ) ); /* Q( -maxRshifts ) */
+        silk_sum_sqr_shift( &xx, &xx_shifts, r_ptr, subfr_length + LTP_ORDER );                            /* xx in Q( -xx_shifts ) */
+        silk_corrMatrix_FIX( lag_ptr, subfr_length, LTP_ORDER, XXLTP_Q17_ptr, &nrg, &XX_shifts, arch );    /* XXLTP_Q17_ptr and nrg in Q( -XX_shifts ) */
+        extra_shifts = xx_shifts - XX_shifts;
+        if( extra_shifts > 0 ) {
+            /* Shift XX */
+            xX_shifts = xx_shifts;
+            for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
+                XXLTP_Q17_ptr[ i ] = silk_RSHIFT32( XXLTP_Q17_ptr[ i ], extra_shifts );              /* Q( -xX_shifts ) */
+            }
+            nrg = silk_RSHIFT32( nrg, extra_shifts );                                                /* Q( -xX_shifts ) */
+        } else if( extra_shifts < 0 ) {
+            /* Shift xx */
+            xX_shifts = XX_shifts;
+            xx = silk_RSHIFT32( xx, -extra_shifts );                                                 /* Q( -xX_shifts ) */
+        } else {
+            xX_shifts = xx_shifts;
         }
-        LPC_LTP_res_nrg = silk_max( LPC_LTP_res_nrg, 1 ); /* avoid division by zero */
-
-        div_Q16 = silk_DIV32_varQ( LPC_res_nrg, LPC_LTP_res_nrg, 16 );
-        *LTPredCodGain_Q7 = ( opus_int )silk_SMULBB( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) );
-
-        silk_assert( *LTPredCodGain_Q7 == ( opus_int )silk_SAT16( silk_MUL( 3, silk_lin2log( div_Q16 ) - ( 16 << 7 ) ) ) );
-    }
-
-    /* smoothing */
-    /* d = sum( B, 1 ); */
-    b_Q14_ptr = b_Q14;
-    for( k = 0; k < nb_subfr; k++ ) {
-        d_Q14[ k ] = 0;
-        for( i = 0; i < LTP_ORDER; i++ ) {
-            d_Q14[ k ] += b_Q14_ptr[ i ];
-        }
-        b_Q14_ptr += LTP_ORDER;
-    }
-
-    /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
-
-    /* Find maximum absolute value of d_Q14 and the bits used by w in Q0 */
-    max_abs_d_Q14 = 0;
-    max_w_bits    = 0;
-    for( k = 0; k < nb_subfr; k++ ) {
-        max_abs_d_Q14 = silk_max_32( max_abs_d_Q14, silk_abs( d_Q14[ k ] ) );
-        /* w[ k ] is in Q( 18 - corr_rshifts[ k ] ) */
-        /* Find bits needed in Q( 18 - maxRshifts ) */
-        max_w_bits = silk_max_32( max_w_bits, 32 - silk_CLZ32( w[ k ] ) + corr_rshifts[ k ] - maxRshifts );
-    }
-
-    /* max_abs_d_Q14 = (5 << 15); worst case, i.e. LTP_ORDER * -silk_int16_MIN */
-    silk_assert( max_abs_d_Q14 <= ( 5 << 15 ) );
-
-    /* How many bits is needed for w*d' in Q( 18 - maxRshifts ) in the worst case, of all d_Q14's being equal to max_abs_d_Q14 */
-    extra_shifts = max_w_bits + 32 - silk_CLZ32( max_abs_d_Q14 ) - 14;
+        silk_corrVector_FIX( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xXLTP_Q17_ptr, xX_shifts, arch );    /* xXLTP_Q17_ptr in Q( -xX_shifts ) */
 
-    /* Subtract what we got available; bits in output var plus maxRshifts */
-    extra_shifts -= ( 32 - 1 - 2 + maxRshifts ); /* Keep sign bit free as well as 2 bits for accumulation */
-    extra_shifts = silk_max_int( extra_shifts, 0 );
-
-    maxRshifts_wxtra = maxRshifts + extra_shifts;
-
-    temp32 = silk_RSHIFT( 262, maxRshifts + extra_shifts ) + 1; /* 1e-3f in Q( 18 - (maxRshifts + extra_shifts) ) */
-    wd = 0;
-    for( k = 0; k < nb_subfr; k++ ) {
-        /* w has at least 2 bits of headroom so no overflow should happen */
-        temp32 = silk_ADD32( temp32,                     silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ) );                      /* Q( 18 - maxRshifts_wxtra ) */
-        wd     = silk_ADD32( wd, silk_LSHIFT( silk_SMULWW( silk_RSHIFT( w[ k ], maxRshifts_wxtra - corr_rshifts[ k ] ), d_Q14[ k ] ), 2 ) ); /* Q( 18 - maxRshifts_wxtra ) */
-    }
-    m_Q12 = silk_DIV32_varQ( wd, temp32, 12 );
-
-    b_Q14_ptr = b_Q14;
-    for( k = 0; k < nb_subfr; k++ ) {
-        /* w_fix[ k ] from Q( 18 - corr_rshifts[ k ] ) to Q( 16 ) */
-        if( 2 - corr_rshifts[k] > 0 ) {
-            temp32 = silk_RSHIFT( w[ k ], 2 - corr_rshifts[ k ] );
-        } else {
-            temp32 = silk_LSHIFT_SAT32( w[ k ], corr_rshifts[ k ] - 2 );
+        /* At this point all correlations are in Q(-xX_shifts) */
+        temp = silk_SMLAWB( 1, nrg, SILK_FIX_CONST( LTP_CORR_INV_MAX, 16 ) );
+        temp = silk_max( temp, xx );
+TIC(div)
+#if 0
+        for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
+            XXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( XXLTP_Q17_ptr[ i ], temp, 17 );
+        }
+        for( i = 0; i < LTP_ORDER; i++ ) {
+            xXLTP_Q17_ptr[ i ] = silk_DIV32_varQ( xXLTP_Q17_ptr[ i ], temp, 17 );
         }
-
-        g_Q26 = silk_MUL(
-            silk_DIV32(
-                SILK_FIX_CONST( LTP_SMOOTHING, 26 ),
-                silk_RSHIFT( SILK_FIX_CONST( LTP_SMOOTHING, 26 ), 10 ) + temp32 ),                          /* Q10 */
-            silk_LSHIFT_SAT32( silk_SUB_SAT32( (opus_int32)m_Q12, silk_RSHIFT( d_Q14[ k ], 2 ) ), 4 ) );    /* Q16 */
-
-        temp32 = 0;
+#else
+        for( i = 0; i < LTP_ORDER * LTP_ORDER; i++ ) {
+            XXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)XXLTP_Q17_ptr[ i ], 17 ) / temp );
+        }
         for( i = 0; i < LTP_ORDER; i++ ) {
-            delta_b_Q14[ i ] = silk_max_16( b_Q14_ptr[ i ], 1638 );     /* 1638_Q14 = 0.1_Q0 */
-            temp32 += delta_b_Q14[ i ];                                 /* Q14 */
+            xXLTP_Q17_ptr[ i ] = (opus_int32)( silk_LSHIFT64( (opus_int64)xXLTP_Q17_ptr[ i ], 17 ) / temp );
         }
-        temp32 = silk_DIV32( g_Q26, temp32 );                           /* Q14 -> Q12 */
-        for( i = 0; i < LTP_ORDER; i++ ) {
-            b_Q14_ptr[ i ] = silk_LIMIT_32( (opus_int32)b_Q14_ptr[ i ] + silk_SMULWB( silk_LSHIFT_SAT32( temp32, 4 ), delta_b_Q14[ i ] ), -16000, 28000 );
-        }
-        b_Q14_ptr += LTP_ORDER;
+#endif
+TOC(div)
+        r_ptr         += subfr_length;
+        XXLTP_Q17_ptr += LTP_ORDER * LTP_ORDER;
+        xXLTP_Q17_ptr += LTP_ORDER;
     }
 }
-
-void silk_fit_LTP(
-    opus_int32 LTP_coefs_Q16[ LTP_ORDER ],
-    opus_int16 LTP_coefs_Q14[ LTP_ORDER ]
-)
-{
-    opus_int i;
-
-    for( i = 0; i < LTP_ORDER; i++ ) {
-        LTP_coefs_Q14[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( LTP_coefs_Q16[ i ], 2 ) );
-    }
-}
--- a/media/libopus/silk/fixed/find_pitch_lags_FIX.c
+++ b/media/libopus/silk/fixed/find_pitch_lags_FIX.c
@@ -39,57 +39,55 @@ void silk_find_pitch_lags_FIX(
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  encoder control                                                             */
     opus_int16                      res[],                                  /* O    residual                                                                    */
     const opus_int16                x[],                                    /* I    Speech signal                                                               */
     int                             arch                                    /* I    Run-time architecture                                                       */
 )
 {
     opus_int   buf_len, i, scale;
     opus_int32 thrhld_Q13, res_nrg;
-    const opus_int16 *x_buf, *x_buf_ptr;
+    const opus_int16 *x_ptr;
     VARDECL( opus_int16, Wsig );
     opus_int16 *Wsig_ptr;
     opus_int32 auto_corr[ MAX_FIND_PITCH_LPC_ORDER + 1 ];
     opus_int16 rc_Q15[    MAX_FIND_PITCH_LPC_ORDER ];
     opus_int32 A_Q24[     MAX_FIND_PITCH_LPC_ORDER ];
     opus_int16 A_Q12[     MAX_FIND_PITCH_LPC_ORDER ];
     SAVE_STACK;
 
     /******************************************/
     /* Set up buffer lengths etc based on Fs  */
     /******************************************/
     buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
 
     /* Safety check */
     silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
 
-    x_buf = x - psEnc->sCmn.ltp_mem_length;
-
     /*************************************/
     /* Estimate LPC AR coefficients      */
     /*************************************/
 
     /* Calculate windowed signal */
 
     ALLOC( Wsig, psEnc->sCmn.pitch_LPC_win_length, opus_int16 );
 
     /* First LA_LTP samples */
-    x_buf_ptr = x_buf + buf_len - psEnc->sCmn.pitch_LPC_win_length;
+    x_ptr = x + buf_len - psEnc->sCmn.pitch_LPC_win_length;
     Wsig_ptr  = Wsig;
-    silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 1, psEnc->sCmn.la_pitch );
+    silk_apply_sine_window( Wsig_ptr, x_ptr, 1, psEnc->sCmn.la_pitch );
 
     /* Middle un - windowed samples */
     Wsig_ptr  += psEnc->sCmn.la_pitch;
-    x_buf_ptr += psEnc->sCmn.la_pitch;
-    silk_memcpy( Wsig_ptr, x_buf_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) );
+    x_ptr += psEnc->sCmn.la_pitch;
+    silk_memcpy( Wsig_ptr, x_ptr, ( psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 ) ) * sizeof( opus_int16 ) );
 
     /* Last LA_LTP samples */
     Wsig_ptr  += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
-    x_buf_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
-    silk_apply_sine_window( Wsig_ptr, x_buf_ptr, 2, psEnc->sCmn.la_pitch );
+    x_ptr += psEnc->sCmn.pitch_LPC_win_length - silk_LSHIFT( psEnc->sCmn.la_pitch, 1 );
+    silk_apply_sine_window( Wsig_ptr, x_ptr, 2, psEnc->sCmn.la_pitch );
 
     /* Calculate autocorrelation sequence */
     silk_autocorr( auto_corr, &scale, Wsig, psEnc->sCmn.pitch_LPC_win_length, psEnc->sCmn.pitchEstimationLPCOrder + 1, arch );
 
     /* Add white noise, as fraction of energy */
     auto_corr[ 0 ] = silk_SMLAWB( auto_corr[ 0 ], auto_corr[ 0 ], SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) ) + 1;
 
     /* Calculate the reflection coefficients using schur */
@@ -107,17 +105,17 @@ void silk_find_pitch_lags_FIX(
     }
 
     /* Do BWE */
     silk_bwexpander( A_Q12, psEnc->sCmn.pitchEstimationLPCOrder, SILK_FIX_CONST( FIND_PITCH_BANDWIDTH_EXPANSION, 16 ) );
 
     /*****************************************/
     /* LPC analysis filtering                */
     /*****************************************/
-    silk_LPC_analysis_filter( res, x_buf, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch );
+    silk_LPC_analysis_filter( res, x, A_Q12, buf_len, psEnc->sCmn.pitchEstimationLPCOrder, psEnc->sCmn.arch );
 
     if( psEnc->sCmn.indices.signalType != TYPE_NO_VOICE_ACTIVITY && psEnc->sCmn.first_frame_after_reset == 0 ) {
         /* Threshold for pitch estimator */
         thrhld_Q13 = SILK_FIX_CONST( 0.6, 13 );
         thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.004, 13 ), psEnc->sCmn.pitchEstimationLPCOrder );
         thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1,   21  ), psEnc->sCmn.speech_activity_Q8 );
         thrhld_Q13 = silk_SMLABB( thrhld_Q13, SILK_FIX_CONST( -0.15,  13 ), silk_RSHIFT( psEnc->sCmn.prevSignalType, 1 ) );
         thrhld_Q13 = silk_SMLAWB( thrhld_Q13, SILK_FIX_CONST( -0.1,   14 ), psEnc->sCmn.input_tilt_Q15 );
--- a/media/libopus/silk/fixed/find_pred_coefs_FIX.c
+++ b/media/libopus/silk/fixed/find_pred_coefs_FIX.c
@@ -36,70 +36,67 @@ void silk_find_pred_coefs_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  encoder state                                                               */
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  encoder control                                                             */
     const opus_int16                res_pitch[],                            /* I    Residual from pitch analysis                                                */
     const opus_int16                x[],                                    /* I    Speech signal                                                               */
     opus_int                        condCoding                              /* I    The type of conditional coding to use                                       */
 )
 {
     opus_int         i;
-    opus_int32       invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ], Wght_Q15[ MAX_NB_SUBFR ];
+    opus_int32       invGains_Q16[ MAX_NB_SUBFR ], local_gains[ MAX_NB_SUBFR ];
     opus_int16       NLSF_Q15[ MAX_LPC_ORDER ];
     const opus_int16 *x_ptr;
     opus_int16       *x_pre_ptr;
     VARDECL( opus_int16, LPC_in_pre );
-    opus_int32       tmp, min_gain_Q16, minInvGain_Q30;
-    opus_int         LTP_corrs_rshift[ MAX_NB_SUBFR ];
+    opus_int32       min_gain_Q16, minInvGain_Q30;
     SAVE_STACK;
 
     /* weighting for weighted least squares */
     min_gain_Q16 = silk_int32_MAX >> 6;
     for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
         min_gain_Q16 = silk_min( min_gain_Q16, psEncCtrl->Gains_Q16[ i ] );
     }
     for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
         /* Divide to Q16 */
         silk_assert( psEncCtrl->Gains_Q16[ i ] > 0 );
         /* Invert and normalize gains, and ensure that maximum invGains_Q16 is within range of a 16 bit int */
         invGains_Q16[ i ] = silk_DIV32_varQ( min_gain_Q16, psEncCtrl->Gains_Q16[ i ], 16 - 2 );
 
-        /* Ensure Wght_Q15 a minimum value 1 */
-        invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 363 );
+        /* Limit inverse */
+        invGains_Q16[ i ] = silk_max( invGains_Q16[ i ], 100 );
 
         /* Square the inverted gains */
         silk_assert( invGains_Q16[ i ] == silk_SAT16( invGains_Q16[ i ] ) );
-        tmp = silk_SMULWB( invGains_Q16[ i ], invGains_Q16[ i ] );
-        Wght_Q15[ i ] = silk_RSHIFT( tmp, 1 );
 
         /* Invert the inverted and normalized gains */
         local_gains[ i ] = silk_DIV32( ( (opus_int32)1 << 16 ), invGains_Q16[ i ] );
     }
 
     ALLOC( LPC_in_pre,
            psEnc->sCmn.nb_subfr * psEnc->sCmn.predictLPCOrder
                + psEnc->sCmn.frame_length, opus_int16 );
     if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
-        VARDECL( opus_int32, WLTP );
+        VARDECL( opus_int32, xXLTP_Q17 );
+        VARDECL( opus_int32, XXLTP_Q17 );
 
         /**********/
         /* VOICED */
         /**********/
         silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
 
-        ALLOC( WLTP, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
+        ALLOC( xXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER, opus_int32 );
+        ALLOC( XXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
 
         /* LTP analysis */
-        silk_find_LTP_FIX( psEncCtrl->LTPCoef_Q14, WLTP, &psEncCtrl->LTPredCodGain_Q7,
-            res_pitch, psEncCtrl->pitchL, Wght_Q15, psEnc->sCmn.subfr_length,
-            psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length, LTP_corrs_rshift, psEnc->sCmn.arch );
+        silk_find_LTP_FIX( XXLTP_Q17, xXLTP_Q17, res_pitch,
+            psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
 
         /* Quantize LTP gain parameters */
         silk_quant_LTP_gains( psEncCtrl->LTPCoef_Q14, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
-            &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
-            psEnc->sCmn.arch);
+            &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain_Q7, XXLTP_Q17, xXLTP_Q17, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
 
         /* Control LTP scaling */
         silk_LTP_scale_ctrl_FIX( psEnc, psEncCtrl, condCoding );
 
         /* Create LTP residual */
         silk_LTP_analysis_filter_FIX( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef_Q14,
             psEncCtrl->pitchL, invGains_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
 
--- a/media/libopus/silk/fixed/k2a_FIX.c
+++ b/media/libopus/silk/fixed/k2a_FIX.c
@@ -34,20 +34,21 @@ POSSIBILITY OF SUCH DAMAGE.
 /* 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                                            */
 )
 {
     opus_int   k, n;
-    opus_int32 Atmp[ SILK_MAX_ORDER_LPC ];
+    opus_int32 rc, tmp1, tmp2;
 
     for( k = 0; k < order; k++ ) {
-        for( n = 0; n < k; n++ ) {
-            Atmp[ n ] = A_Q24[ n ];
-        }
-        for( n = 0; n < k; n++ ) {
-            A_Q24[ n ] = silk_SMLAWB( A_Q24[ n ], silk_LSHIFT( Atmp[ k - n - 1 ], 1 ), rc_Q15[ k ] );
+        rc = rc_Q15[ k ];
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            tmp1 = A_Q24[ n ];
+            tmp2 = A_Q24[ k - n - 1 ];
+            A_Q24[ n ]         = silk_SMLAWB( tmp1, silk_LSHIFT( tmp2, 1 ), rc );
+            A_Q24[ k - n - 1 ] = silk_SMLAWB( tmp2, silk_LSHIFT( tmp1, 1 ), rc );
         }
         A_Q24[ k ] = -silk_LSHIFT( (opus_int32)rc_Q15[ k ], 9 );
     }
 }
--- a/media/libopus/silk/fixed/k2a_Q16_FIX.c
+++ b/media/libopus/silk/fixed/k2a_Q16_FIX.c
@@ -34,20 +34,21 @@ POSSIBILITY OF SUCH DAMAGE.
 /* 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                                            */
 )
 {
     opus_int   k, n;
-    opus_int32 Atmp[ SILK_MAX_ORDER_LPC ];
+    opus_int32 rc, tmp1, tmp2;
 
     for( k = 0; k < order; k++ ) {
-        for( n = 0; n < k; n++ ) {
-            Atmp[ n ] = A_Q24[ n ];
+        rc = rc_Q16[ k ];
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            tmp1 = A_Q24[ n ];
+            tmp2 = A_Q24[ k - n - 1 ];
+            A_Q24[ n ]         = silk_SMLAWW( tmp1, tmp2, rc );
+            A_Q24[ k - n - 1 ] = silk_SMLAWW( tmp2, tmp1, rc );
         }
-        for( n = 0; n < k; n++ ) {
-            A_Q24[ n ] = silk_SMLAWW( A_Q24[ n ], Atmp[ k - n - 1 ], rc_Q16[ k ] );
-        }
-        A_Q24[ k ] = -silk_LSHIFT( rc_Q16[ k ], 8 );
+        A_Q24[ k ] = -silk_LSHIFT( rc, 8 );
     }
 }
--- a/media/libopus/silk/fixed/main_FIX.h
+++ b/media/libopus/silk/fixed/main_FIX.h
@@ -31,27 +31,35 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "SigProc_FIX.h"
 #include "structs_FIX.h"
 #include "control.h"
 #include "main.h"
 #include "PLC.h"
 #include "debug.h"
 #include "entenc.h"
 
+#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
+   || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "fixed/arm/warped_autocorrelation_FIX_arm.h"
+#endif
+
 #ifndef FORCE_CPP_BUILD
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 #endif
 
 #define silk_encoder_state_Fxx      silk_encoder_state_FIX
 #define silk_encode_do_VAD_Fxx      silk_encode_do_VAD_FIX
 #define silk_encode_frame_Fxx       silk_encode_frame_FIX
 
+#define QC  10
+#define QS  13
+
 /*********************/
 /* Encoder Functions */
 /*********************/
 
 /* 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                                                              */
 );
@@ -76,65 +84,48 @@ opus_int silk_init_encoder(
     silk_encoder_state_Fxx          *psEnc,                                 /* I/O  Pointer to Silk FIX encoder state                                           */
     int                              arch                                   /* I    Run-time architecture                                                       */
 );
 
 /* Control the Silk 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
 );
 
-/****************/
-/* Prefiltering */
-/****************/
-void silk_prefilter_FIX(
-    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state                                                               */
-    const silk_encoder_control_FIX  *psEncCtrl,                             /* I    Encoder control                                                             */
-    opus_int32                      xw_Q10[],                               /* O    Weighted signal                                                             */
-    const opus_int16                x[]                                     /* I    Speech signal                                                               */
-);
-
-void silk_warped_LPC_analysis_filter_FIX_c(
-          opus_int32            state[],                    /* I/O  State [order + 1]                   */
-          opus_int32            res_Q2[],                   /* O    Residual signal [length]            */
-    const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
-    const opus_int16            input[],                    /* I    Input signal [length]               */
-    const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
-    const opus_int              length,                     /* I    Length of input signal              */
-    const opus_int              order                       /* I    Filter order (even)                 */
-);
-
-
 /**************************/
 /* Noise shaping analysis */
 /**************************/
 /* Compute noise shaping coefficients and initial gain values */
 void silk_noise_shape_analysis_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state FIX                                                           */
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Encoder control FIX                                                         */
     const opus_int16                *pitch_res,                             /* I    LPC residual from pitch analysis                                            */
     const opus_int16                *x,                                     /* I    Input signal [ frame_length + la_shape ]                                    */
     int                              arch                                   /* I    Run-time architecture                                                       */
 );
 
 /* Autocorrelations for a warped frequency axis */
-void silk_warped_autocorrelation_FIX(
+void silk_warped_autocorrelation_FIX_c(
           opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
           opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
     const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
     const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
     const opus_int                  length,                                 /* I    Length of input                                                             */
     const opus_int                  order                                   /* I    Correlation order (even)                                                    */
 );
 
+#if !defined(OVERRIDE_silk_warped_autocorrelation_FIX)
+#define silk_warped_autocorrelation_FIX(corr, scale, input, warping_Q16, length, order, arch) \
+        ((void)(arch), silk_warped_autocorrelation_FIX_c(corr, scale, input, warping_Q16, length, order))
+#endif
+
 /* Calculation of LTP state scaling */
 void silk_LTP_scale_ctrl_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  encoder state                                                               */
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  encoder control                                                             */
     opus_int                        condCoding                              /* I    The type of conditional coding to use                                       */
 );
 
 /**********************************************/
@@ -163,26 +154,22 @@ void silk_find_LPC_FIX(
     silk_encoder_state              *psEncC,                                /* I/O  Encoder state                                                               */
     opus_int16                      NLSF_Q15[],                             /* O    NLSFs                                                                       */
     const opus_int16                x[],                                    /* I    Input signal                                                                */
     const opus_int32                minInvGain_Q30                          /* I    Inverse of max prediction gain                                              */
 );
 
 /* LTP analysis */
 void silk_find_LTP_FIX(
-    opus_int16                      b_Q14[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    LTP coefs                                                                   */
-    opus_int32                      WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization                                           */
-    opus_int                        *LTPredCodGain_Q7,                      /* O    LTP coding gain                                                             */
-    const opus_int16                r_lpc[],                                /* I    residual signal after LPC signal + state for first 10 ms                    */
+    opus_int32                      XXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Correlation matrix                                               */
+    opus_int32                      xXLTP_Q17[ MAX_NB_SUBFR * LTP_ORDER ],  /* O    Correlation vector                                                          */
+    const opus_int16                r_lpc[],                                /* I    Residual signal after LPC                                                   */
     const opus_int                  lag[ MAX_NB_SUBFR ],                    /* I    LTP lags                                                                    */
-    const opus_int32                Wght_Q15[ MAX_NB_SUBFR ],               /* I    weights                                                                     */
-    const opus_int                  subfr_length,                           /* I    subframe length                                                             */
-    const opus_int                  nb_subfr,                               /* I    number of subframes                                                         */
-    const opus_int                  mem_offset,                             /* I    number of samples in LTP memory                                             */
-    opus_int                        corr_rshifts[ MAX_NB_SUBFR ],           /* O    right shifts applied to correlations                                        */
+    const opus_int                  subfr_length,                           /* I    Subframe length                                                             */
+    const opus_int                  nb_subfr,                               /* I    Number of subframes                                                         */
     int                             arch                                    /* I    Run-time architecture                                                       */
 );
 
 void silk_LTP_analysis_filter_FIX(
     opus_int16                      *LTP_res,                               /* O    LTP residual signal of length MAX_NB_SUBFR * ( pre_length + subfr_length )  */
     const opus_int16                *x,                                     /* I    Pointer to input signal with at least max( pitchL ) preceding samples       */
     const opus_int16                LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],/* I    LTP_ORDER LTP coefficients for each MAX_NB_SUBFR subframe                   */
     const opus_int                  pitchL[ MAX_NB_SUBFR ],                 /* I    Pitch lag, one for each subframe                                            */
@@ -226,47 +213,31 @@ void silk_process_gains_FIX(
 /******************/
 /* Linear Algebra */
 /******************/
 /* Calculates correlation matrix X'*X */
 void silk_corrMatrix_FIX(
     const opus_int16                *x,                                     /* I    x vector [L + order - 1] used to form data matrix X                         */
     const opus_int                  L,                                      /* I    Length of vectors                                                           */
     const opus_int                  order,                                  /* I    Max lag for correlation                                                     */
-    const opus_int                  head_room,                              /* I    Desired headroom                                                            */
     opus_int32                      *XX,                                    /* O    Pointer to X'*X correlation matrix [ order x order ]                        */
-    opus_int                        *rshifts,                               /* I/O  Right shifts of correlations                                                */
+    opus_int32                      *nrg,                                   /* O    Energy of x vector                                                          */
+    opus_int                        *rshifts,                               /* O    Right shifts of correlations                                                */
     int                              arch                                   /* I    Run-time architecture                                                       */
 );
 
 /* Calculates correlation vector X'*t */
 void silk_corrVector_FIX(
     const opus_int16                *x,                                     /* I    x vector [L + order - 1] used to form data matrix X                         */
     const opus_int16                *t,                                     /* I    Target vector [L]                                                           */
     const opus_int                  L,                                      /* I    Length of vectors                                                           */
     const opus_int                  order,                                  /* I    Max lag for correlation                                                     */
     opus_int32                      *Xt,                                    /* O    Pointer to X'*t correlation vector [order]                                  */
     const opus_int                  rshifts,                                /* I    Right shifts of correlations                                                */
     int                             arch                                    /* I    Run-time architecture                                                       */
 );
 
-/* Add noise to matrix diagonal */
-void silk_regularize_correlations_FIX(
-    opus_int32                      *XX,                                    /* I/O  Correlation matrices                                                        */
-    opus_int32                      *xx,                                    /* I/O  Correlation values                                                          */
-    opus_int32                      noise,                                  /* I    Noise to add                                                                */
-    opus_int                        D                                       /* I    Dimension of XX                                                             */
-);
-
-/* Solves Ax = b, assuming A is symmetric */
-void silk_solve_LDL_FIX(
-    opus_int32                      *A,                                     /* I    Pointer to symetric square matrix A                                         */
-    opus_int                        M,                                      /* I    Size of matrix                                                              */
-    const opus_int32                *b,                                     /* I    Pointer to b vector                                                         */
-    opus_int32                      *x_Q16                                  /* O    Pointer to x solution vector                                                */
-);
-
 #ifndef FORCE_CPP_BUILD
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
 #endif /* FORCE_CPP_BUILD */
 #endif /* SILK_MAIN_FIX_H */
--- a/media/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
+++ b/media/libopus/silk/fixed/mips/noise_shape_analysis_FIX_mipsr1.h
@@ -164,17 +164,17 @@ void silk_noise_shape_analysis_FIX(
         shift += flat_part;
         silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part );
 
         /* Update pointer: next LPC analysis block */
         x_ptr += psEnc->sCmn.subfr_length;
 
         if( psEnc->sCmn.warping_Q16 > 0 ) {
             /* Calculate warped auto correlation */
-            silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
+            silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch );
         } else {
             /* Calculate regular auto correlation */
             silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
         }
 
         /* Add white noise, as a fraction of energy */
         auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ),
             SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) );
@@ -219,18 +219,18 @@ void silk_noise_shape_analysis_FIX(
         /* Compute noise shaping filter coefficients */
         silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) );
 
         /* Bandwidth expansion for analysis filter shaping */
         silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) );
         silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
 
         /* Ratio of prediction gains, in energy domain */
-        pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
-        nrg         = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
+        pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder, arch );
+        nrg         = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder, arch );
 
         /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
         pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
         psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 );
 
         /* Convert to monic warped prediction coefficients and limit absolute values */
         limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
 
deleted file mode 100644
--- a/media/libopus/silk/fixed/mips/prefilter_FIX_mipsr1.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-#ifndef __PREFILTER_FIX_MIPSR1_H__
-#define __PREFILTER_FIX_MIPSR1_H__
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "main_FIX.h"
-#include "stack_alloc.h"
-#include "tuning_parameters.h"
-
-#define OVERRIDE_silk_warped_LPC_analysis_filter_FIX
-void silk_warped_LPC_analysis_filter_FIX(
-          opus_int32            state[],                    /* I/O  State [order + 1]                   */
-          opus_int32            res_Q2[],                   /* O    Residual signal [length]            */
-    const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
-    const opus_int16            input[],                    /* I    Input signal [length]               */
-    const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
-    const opus_int              length,                     /* I    Length of input signal              */
-    const opus_int              order,                      /* I    Filter order (even)                 */
-               int              arch
-)
-{
-    opus_int     n, i;
-    opus_int32   acc_Q11, acc_Q22, tmp1, tmp2, tmp3, tmp4;
-    opus_int32   state_cur, state_next;
-
-    (void)arch;
-
-    /* Order must be even */
-    /* Length must be even */
-
-    silk_assert( ( order & 1 ) == 0 );
-    silk_assert( ( length & 1 ) == 0 );
-
-    for( n = 0; n < length; n+=2 ) {
-        /* Output of lowpass section */
-        tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
-        state_cur = silk_LSHIFT( input[ n ], 14 );
-        /* Output of allpass section */
-        tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
-        state_next = tmp2;
-        acc_Q11 = silk_RSHIFT( order, 1 );
-        acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
-
-
-        /* Output of lowpass section */
-        tmp4 = silk_SMLAWB( state_cur, state_next, lambda_Q16 );
-        state[ 0 ] = silk_LSHIFT( input[ n+1 ], 14 );
-        /* Output of allpass section */
-        tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 );
-        state[ 1 ] = tmp4;
-        acc_Q22 = silk_RSHIFT( order, 1 );
-        acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ 0 ] );
-
-        /* Loop over allpass sections */
-        for( i = 2; i < order; i += 2 ) {
-            /* Output of allpass section */
-            tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
-            state_cur = tmp1;
-            acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
-            /* Output of allpass section */
-            tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
-            state_next = tmp2;
-            acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
-
-
-            /* Output of allpass section */
-            tmp4 = silk_SMLAWB( state_cur, state_next - tmp3, lambda_Q16 );
-            state[ i ] = tmp3;
-            acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ i - 1 ] );
-            /* Output of allpass section */
-            tmp3 = silk_SMLAWB( state_next, tmp1 - tmp4, lambda_Q16 );
-            state[ i + 1 ] = tmp4;
-            acc_Q22 = silk_SMLAWB( acc_Q22, tmp4, coef_Q13[ i ] );
-        }
-        acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
-        res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
-
-        state[ order ] = tmp3;
-        acc_Q22 = silk_SMLAWB( acc_Q22, tmp3, coef_Q13[ order - 1 ] );
-        res_Q2[ n+1 ] = silk_LSHIFT( (opus_int32)input[ n+1 ], 2 ) - silk_RSHIFT_ROUND( acc_Q22, 9 );
-    }
-}
-
-
-
-/* Prefilter for finding Quantizer input signal */
-#define OVERRIDE_silk_prefilt_FIX
-static inline void silk_prefilt_FIX(
-    silk_prefilter_state_FIX    *P,                         /* I/O  state                               */
-    opus_int32                  st_res_Q12[],               /* I    short term residual signal          */
-    opus_int32                  xw_Q3[],                    /* O    prefiltered signal                  */
-    opus_int32                  HarmShapeFIRPacked_Q12,     /* I    Harmonic shaping coeficients        */
-    opus_int                    Tilt_Q14,                   /* I    Tilt shaping coeficient             */
-    opus_int32                  LF_shp_Q14,                 /* I    Low-frequancy shaping coeficients   */
-    opus_int                    lag,                        /* I    Lag for harmonic shaping            */
-    opus_int                    length                      /* I    Length of signals                   */
-)
-{
-    opus_int   i, idx, LTP_shp_buf_idx;
-    opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
-    opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
-    opus_int16 *LTP_shp_buf;
-
-    /* To speed up use temp variables instead of using the struct */
-    LTP_shp_buf     = P->sLTP_shp;
-    LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
-    sLF_AR_shp_Q12  = P->sLF_AR_shp_Q12;
-    sLF_MA_shp_Q12  = P->sLF_MA_shp_Q12;
-
-    if( lag > 0 ) {
-        for( i = 0; i < length; i++ ) {
-            /* unrolled loop */
-            silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
-            idx = lag + LTP_shp_buf_idx;
-            n_LTP_Q12 = silk_SMULBB(            LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
-            n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2    ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
-            n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
-
-            n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
-            n_LF_Q10   = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
-
-            sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
-            sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12,  silk_LSHIFT( n_LF_Q10,   2 ) );
-
-            LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
-            LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
-
-            xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
-        }
-    }
-    else
-    {
-        for( i = 0; i < length; i++ ) {
-
-            n_LTP_Q12 = 0;
-
-            n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
-            n_LF_Q10   = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
-
-            sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
-            sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12,  silk_LSHIFT( n_LF_Q10,   2 ) );
-
-            LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
-            LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
-
-            xw_Q3[i] = silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 9 );
-        }
-    }
-
-    /* Copy temp variable back to state */
-    P->sLF_AR_shp_Q12   = sLF_AR_shp_Q12;
-    P->sLF_MA_shp_Q12   = sLF_MA_shp_Q12;
-    P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
-}
-
-#endif /* __PREFILTER_FIX_MIPSR1_H__ */
--- a/media/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
+++ b/media/libopus/silk/fixed/mips/warped_autocorrelation_FIX_mipsr1.h
@@ -43,17 +43,18 @@ POSSIBILITY OF SUCH DAMAGE.
 /* Autocorrelations for a warped frequency axis */
 #define OVERRIDE_silk_warped_autocorrelation_FIX
 void silk_warped_autocorrelation_FIX(
           opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
           opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
     const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
     const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
     const opus_int                  length,                                 /* I    Length of input                                                             */
-    const opus_int                  order                                   /* I    Correlation order (even)                                                    */
+    const opus_int                  order,                                  /* I    Correlation order (even)                                                    */
+    int                             arch                                    /* I    Run-time architecture                                                       */
 )
 {
     opus_int   n, i, lsh;
     opus_int32 tmp1_QS=0, tmp2_QS=0, tmp3_QS=0, tmp4_QS=0, tmp5_QS=0, tmp6_QS=0, tmp7_QS=0, tmp8_QS=0, start_1=0, start_2=0, start_3=0;
     opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
     opus_int64 corr_QC[  MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
     opus_int64 temp64;
 
--- a/media/libopus/silk/fixed/noise_shape_analysis_FIX.c
+++ b/media/libopus/silk/fixed/noise_shape_analysis_FIX.c
@@ -52,122 +52,112 @@ static OPUS_INLINE opus_int32 warped_gai
     }
     gain_Q24  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), gain_Q24, -lambda_Q16 );
     return silk_INVERSE32_varQ( gain_Q24, 40 );
 }
 
 /* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum     */
 /* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
 static OPUS_INLINE void limit_warped_coefs(
-    opus_int32           *coefs_syn_Q24,
-    opus_int32           *coefs_ana_Q24,
+    opus_int32           *coefs_Q24,
     opus_int             lambda_Q16,
     opus_int32           limit_Q24,
     opus_int             order
 ) {
     opus_int   i, iter, ind = 0;
-    opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_syn_Q16, gain_ana_Q16;
+    opus_int32 tmp, maxabs_Q24, chirp_Q16, gain_Q16;
     opus_int32 nom_Q16, den_Q24;
+    opus_int32 limit_Q20, maxabs_Q20;
 
     /* Convert to monic coefficients */
     lambda_Q16 = -lambda_Q16;
     for( i = order - 1; i > 0; i-- ) {
-        coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
-        coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
+        coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
     }
     lambda_Q16 = -lambda_Q16;
-    nom_Q16  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16,        lambda_Q16 );
-    den_Q24  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
-    gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
-    den_Q24  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
-    gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
+    nom_Q16  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16, lambda_Q16 );
+    den_Q24  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 );
+    gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
     for( i = 0; i < order; i++ ) {
-        coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
-        coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
+        coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
     }
-
+    limit_Q20 = silk_RSHIFT(limit_Q24, 4);
     for( iter = 0; iter < 10; iter++ ) {
         /* Find maximum absolute value */
         maxabs_Q24 = -1;
         for( i = 0; i < order; i++ ) {
-            tmp = silk_max( silk_abs_int32( coefs_syn_Q24[ i ] ), silk_abs_int32( coefs_ana_Q24[ i ] ) );
+            tmp = silk_abs_int32( coefs_Q24[ i ] );
             if( tmp > maxabs_Q24 ) {
                 maxabs_Q24 = tmp;
                 ind = i;
             }
         }
-        if( maxabs_Q24 <= limit_Q24 ) {
+        /* Use Q20 to avoid any overflow when multiplying by (ind + 1) later. */
+        maxabs_Q20 = silk_RSHIFT(maxabs_Q24, 4);
+        if( maxabs_Q20 <= limit_Q20 ) {
             /* Coefficients are within range - done */
             return;
         }
 
         /* Convert back to true warped coefficients */
         for( i = 1; i < order; i++ ) {
-            coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
-            coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
+            coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
         }
-        gain_syn_Q16 = silk_INVERSE32_varQ( gain_syn_Q16, 32 );
-        gain_ana_Q16 = silk_INVERSE32_varQ( gain_ana_Q16, 32 );
+        gain_Q16 = silk_INVERSE32_varQ( gain_Q16, 32 );
         for( i = 0; i < order; i++ ) {
-            coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
-            coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
+            coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
         }
 
         /* Apply bandwidth expansion */
         chirp_Q16 = SILK_FIX_CONST( 0.99, 16 ) - silk_DIV32_varQ(
-            silk_SMULWB( maxabs_Q24 - limit_Q24, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
-            silk_MUL( maxabs_Q24, ind + 1 ), 22 );
-        silk_bwexpander_32( coefs_syn_Q24, order, chirp_Q16 );
-        silk_bwexpander_32( coefs_ana_Q24, order, chirp_Q16 );
+            silk_SMULWB( maxabs_Q20 - limit_Q20, silk_SMLABB( SILK_FIX_CONST( 0.8, 10 ), SILK_FIX_CONST( 0.1, 10 ), iter ) ),
+            silk_MUL( maxabs_Q20, ind + 1 ), 22 );
+        silk_bwexpander_32( coefs_Q24, order, chirp_Q16 );
 
         /* Convert to monic warped coefficients */
         lambda_Q16 = -lambda_Q16;
         for( i = order - 1; i > 0; i-- ) {
-            coefs_syn_Q24[ i - 1 ] = silk_SMLAWB( coefs_syn_Q24[ i - 1 ], coefs_syn_Q24[ i ], lambda_Q16 );
-            coefs_ana_Q24[ i - 1 ] = silk_SMLAWB( coefs_ana_Q24[ i - 1 ], coefs_ana_Q24[ i ], lambda_Q16 );
+            coefs_Q24[ i - 1 ] = silk_SMLAWB( coefs_Q24[ i - 1 ], coefs_Q24[ i ], lambda_Q16 );
         }
         lambda_Q16 = -lambda_Q16;
         nom_Q16  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 16 ), -(opus_int32)lambda_Q16,        lambda_Q16 );
-        den_Q24  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_syn_Q24[ 0 ], lambda_Q16 );
-        gain_syn_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
-        den_Q24  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_ana_Q24[ 0 ], lambda_Q16 );
-        gain_ana_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
+        den_Q24  = silk_SMLAWB( SILK_FIX_CONST( 1.0, 24 ), coefs_Q24[ 0 ], lambda_Q16 );
+        gain_Q16 = silk_DIV32_varQ( nom_Q16, den_Q24, 24 );
         for( i = 0; i < order; i++ ) {
-            coefs_syn_Q24[ i ] = silk_SMULWW( gain_syn_Q16, coefs_syn_Q24[ i ] );
-            coefs_ana_Q24[ i ] = silk_SMULWW( gain_ana_Q16, coefs_ana_Q24[ i ] );
+            coefs_Q24[ i ] = silk_SMULWW( gain_Q16, coefs_Q24[ i ] );
         }
     }
     silk_assert( 0 );
 }
 
-#if defined(MIPSr1_ASM)
+/* Disable MIPS version until it's updated. */
+#if 0 && defined(MIPSr1_ASM)
 #include "mips/noise_shape_analysis_FIX_mipsr1.h"
 #endif
 
 /**************************************************************/
 /* Compute noise shaping coefficients and initial gain values */
 /**************************************************************/
 #ifndef OVERRIDE_silk_noise_shape_analysis_FIX
 void silk_noise_shape_analysis_FIX(
     silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state FIX                                                           */
     silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Encoder control FIX                                                         */
     const opus_int16                *pitch_res,                             /* I    LPC residual from pitch analysis                                            */
     const opus_int16                *x,                                     /* I    Input signal [ frame_length + la_shape ]                                    */
     int                              arch                                   /* I    Run-time architecture                                                       */
 )
 {
     silk_shape_state_FIX *psShapeSt = &psEnc->sShape;
-    opus_int     k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0;
-    opus_int32   SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32;
-    opus_int32   nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
-    opus_int32   delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
+    opus_int     k, i, nSamples, nSegs, Qnrg, b_Q14, warping_Q16, scale = 0;
+    opus_int32   SNR_adj_dB_Q7, HarmShapeGain_Q16, Tilt_Q16, tmp32;
+    opus_int32   nrg, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
+    opus_int32   BWExp_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
     opus_int32   auto_corr[     MAX_SHAPE_LPC_ORDER + 1 ];
     opus_int32   refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ];
-    opus_int32   AR1_Q24[       MAX_SHAPE_LPC_ORDER ];
-    opus_int32   AR2_Q24[       MAX_SHAPE_LPC_ORDER ];
+    opus_int32   AR_Q24[       MAX_SHAPE_LPC_ORDER ];
     VARDECL( opus_int16, x_windowed );
     const opus_int16 *x_ptr, *pitch_res_ptr;
     SAVE_STACK;
 
     /* Point to start of first LPC analysis block */
     x_ptr = x - psEnc->sCmn.la_shape;
 
     /****************/
@@ -204,62 +194,50 @@ void silk_noise_shape_analysis_FIX(
 
     /*************************/
     /* SPARSENESS PROCESSING */
     /*************************/
     /* Set quantizer offset */
     if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
         /* Initially set to 0; may be overruled in process_gains(..) */
         psEnc->sCmn.indices.quantOffsetType = 0;
-        psEncCtrl->sparseness_Q8 = 0;
     } else {
         /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
         nSamples = silk_LSHIFT( psEnc->sCmn.fs_kHz, 1 );
         energy_variation_Q7 = 0;
         log_energy_prev_Q7  = 0;
         pitch_res_ptr = pitch_res;
-        for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
+        nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
+        for( k = 0; k < nSegs; k++ ) {
             silk_sum_sqr_shift( &nrg, &scale, pitch_res_ptr, nSamples );
             nrg += silk_RSHIFT( nSamples, scale );           /* Q(-scale)*/
 
             log_energy_Q7 = silk_lin2log( nrg );
             if( k > 0 ) {
                 energy_variation_Q7 += silk_abs( log_energy_Q7 - log_energy_prev_Q7 );
             }
             log_energy_prev_Q7 = log_energy_Q7;
             pitch_res_ptr += nSamples;
         }
 
-        psEncCtrl->sparseness_Q8 = silk_RSHIFT( silk_sigm_Q15( silk_SMULWB( energy_variation_Q7 -
-            SILK_FIX_CONST( 5.0, 7 ), SILK_FIX_CONST( 0.1, 16 ) ) ), 7 );
-
         /* Set quantization offset depending on sparseness measure */
-        if( psEncCtrl->sparseness_Q8 > SILK_FIX_CONST( SPARSENESS_THRESHOLD_QNT_OFFSET, 8 ) ) {
+        if( energy_variation_Q7 > SILK_FIX_CONST( ENERGY_VARIATION_THRESHOLD_QNT_OFFSET, 7 ) * (nSegs-1) ) {
             psEnc->sCmn.indices.quantOffsetType = 0;
         } else {
             psEnc->sCmn.indices.quantOffsetType = 1;
         }
-
-        /* Increase coding SNR for sparse signals */
-        SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7, SILK_FIX_CONST( SPARSE_SNR_INCR_dB, 15 ), psEncCtrl->sparseness_Q8 - SILK_FIX_CONST( 0.5, 8 ) );
     }
 
     /*******************************/
     /* Control bandwidth expansion */
     /*******************************/
     /* More BWE for signals with high prediction gain */
     strength_Q16 = silk_SMULWB( psEncCtrl->predGain_Q16, SILK_FIX_CONST( FIND_PITCH_WHITE_NOISE_FRACTION, 16 ) );
-    BWExp1_Q16 = BWExp2_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
+    BWExp_Q16 = silk_DIV32_varQ( SILK_FIX_CONST( BANDWIDTH_EXPANSION, 16 ),
         silk_SMLAWW( SILK_FIX_CONST( 1.0, 16 ), strength_Q16, strength_Q16 ), 16 );
-    delta_Q16  = silk_SMULWB( SILK_FIX_CONST( 1.0, 16 ) - silk_SMULBB( 3, psEncCtrl->coding_quality_Q14 ),
-        SILK_FIX_CONST( LOW_RATE_BANDWIDTH_EXPANSION_DELTA, 16 ) );
-    BWExp1_Q16 = silk_SUB32( BWExp1_Q16, delta_Q16 );
-    BWExp2_Q16 = silk_ADD32( BWExp2_Q16, delta_Q16 );
-    /* BWExp1 will be applied after BWExp2, so make it relative */
-    BWExp1_Q16 = silk_DIV32_16( silk_LSHIFT( BWExp1_Q16, 14 ), silk_RSHIFT( BWExp2_Q16, 2 ) );
 
     if( psEnc->sCmn.warping_Q16 > 0 ) {
         /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
         warping_Q16 = silk_SMLAWB( psEnc->sCmn.warping_Q16, (opus_int32)psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( 0.01, 18 ) );
     } else {
         warping_Q16 = 0;
     }
 
@@ -279,32 +257,32 @@ void silk_noise_shape_analysis_FIX(
         shift += flat_part;
         silk_apply_sine_window( x_windowed + shift, x_ptr + shift, 2, slope_part );
 
         /* Update pointer: next LPC analysis block */
         x_ptr += psEnc->sCmn.subfr_length;
 
         if( psEnc->sCmn.warping_Q16 > 0 ) {
             /* Calculate warped auto correlation */
-            silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
+            silk_warped_autocorrelation_FIX( auto_corr, &scale, x_windowed, warping_Q16, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder, arch );
         } else {
             /* Calculate regular auto correlation */
             silk_autocorr( auto_corr, &scale, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1, arch );
         }
 
         /* Add white noise, as a fraction of energy */
         auto_corr[0] = silk_ADD32( auto_corr[0], silk_max_32( silk_SMULWB( silk_RSHIFT( auto_corr[ 0 ], 4 ),
             SILK_FIX_CONST( SHAPE_WHITE_NOISE_FRACTION, 20 ) ), 1 ) );
 
         /* Calculate the reflection coefficients using schur */
         nrg = silk_schur64( refl_coef_Q16, auto_corr, psEnc->sCmn.shapingLPCOrder );
         silk_assert( nrg >= 0 );
 
         /* Convert reflection coefficients to prediction coefficients */
-        silk_k2a_Q16( AR2_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
+        silk_k2a_Q16( AR_Q24, refl_coef_Q16, psEnc->sCmn.shapingLPCOrder );
 
         Qnrg = -scale;          /* range: -12...30*/
         silk_assert( Qnrg >= -12 );
         silk_assert( Qnrg <=  30 );
 
         /* Make sure that Qnrg is an even number */
         if( Qnrg & 1 ) {
             Qnrg -= 1;
@@ -313,71 +291,60 @@ void silk_noise_shape_analysis_FIX(
 
         tmp32 = silk_SQRT_APPROX( nrg );
         Qnrg >>= 1;             /* range: -6...15*/
 
         psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT_SAT32( tmp32, 16 - Qnrg );
 
         if( psEnc->sCmn.warping_Q16 > 0 ) {
             /* Adjust gain for warping */
-            gain_mult_Q16 = warped_gain( AR2_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
-            silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
-            if ( silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 ) >= ( silk_int32_MAX >> 1 ) ) {
-               psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
+            gain_mult_Q16 = warped_gain( AR_Q24, warping_Q16, psEnc->sCmn.shapingLPCOrder );
+            silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 );
+            if( psEncCtrl->Gains_Q16[ k ] < SILK_FIX_CONST( 0.25, 16 ) ) {
+                psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
             } else {
-               psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
+                psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( silk_RSHIFT_ROUND( psEncCtrl->Gains_Q16[ k ], 1 ), gain_mult_Q16 );
+                if ( psEncCtrl->Gains_Q16[ k ] >= ( silk_int32_MAX >> 1 ) ) {
+                    psEncCtrl->Gains_Q16[ k ] = silk_int32_MAX;
+                } else {
+                    psEncCtrl->Gains_Q16[ k ] = silk_LSHIFT32( psEncCtrl->Gains_Q16[ k ], 1 );
+                }
             }
+            silk_assert( psEncCtrl->Gains_Q16[ k ] > 0 );
         }
 
-        /* Bandwidth expansion for synthesis filter shaping */
-        silk_bwexpander_32( AR2_Q24, psEnc->sCmn.shapingLPCOrder, BWExp2_Q16 );
+        /* Bandwidth expansion */
+        silk_bwexpander_32( AR_Q24, psEnc->sCmn.shapingLPCOrder, BWExp_Q16 );
 
-        /* Compute noise shaping filter coefficients */
-        silk_memcpy( AR1_Q24, AR2_Q24, psEnc->sCmn.shapingLPCOrder * sizeof( opus_int32 ) );
-
-        /* Bandwidth expansion for analysis filter shaping */
-        silk_assert( BWExp1_Q16 <= SILK_FIX_CONST( 1.0, 16 ) );
-        silk_bwexpander_32( AR1_Q24, psEnc->sCmn.shapingLPCOrder, BWExp1_Q16 );
+        if( psEnc->sCmn.warping_Q16 > 0 ) {
+            /* Convert to monic warped prediction coefficients and limit absolute values */
+            limit_warped_coefs( AR_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
 
-        /* Ratio of prediction gains, in energy domain */
-        pre_nrg_Q30 = silk_LPC_inverse_pred_gain_Q24( AR2_Q24, psEnc->sCmn.shapingLPCOrder );
-        nrg         = silk_LPC_inverse_pred_gain_Q24( AR1_Q24, psEnc->sCmn.shapingLPCOrder );
-
-        /*psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg ) = 0.3f + 0.7f * pre_nrg / nrg;*/
-        pre_nrg_Q30 = silk_LSHIFT32( silk_SMULWB( pre_nrg_Q30, SILK_FIX_CONST( 0.7, 15 ) ), 1 );
-        psEncCtrl->GainsPre_Q14[ k ] = ( opus_int ) SILK_FIX_CONST( 0.3, 14 ) + silk_DIV32_varQ( pre_nrg_Q30, nrg, 14 );
-
-        /* Convert to monic warped prediction coefficients and limit absolute values */
-        limit_warped_coefs( AR2_Q24, AR1_Q24, warping_Q16, SILK_FIX_CONST( 3.999, 24 ), psEnc->sCmn.shapingLPCOrder );
-
-        /* Convert from Q24 to Q13 and store in int16 */
-        for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
-            psEncCtrl->AR1_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR1_Q24[ i ], 11 ) );
-            psEncCtrl->AR2_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR2_Q24[ i ], 11 ) );
+            /* Convert from Q24 to Q13 and store in int16 */
+            for( i = 0; i < psEnc->sCmn.shapingLPCOrder; i++ ) {
+                psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER + i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( AR_Q24[ i ], 11 ) );
+            }
+        } else {
+            silk_LPC_fit( &psEncCtrl->AR_Q13[ k * MAX_SHAPE_LPC_ORDER ], AR_Q24, 13, 24, psEnc->sCmn.shapingLPCOrder );
         }
     }
 
     /*****************/
     /* Gain tweaking */
     /*****************/
     /* Increase gains during low speech activity and put lower limit on gains */
     gain_mult_Q16 = silk_log2lin( -silk_SMLAWB( -SILK_FIX_CONST( 16.0, 7 ), SNR_adj_dB_Q7, SILK_FIX_CONST( 0.16, 16 ) ) );
     gain_add_Q16  = silk_log2lin(  silk_SMLAWB(  SILK_FIX_CONST( 16.0, 7 ), SILK_FIX_CONST( MIN_QGAIN_DB, 7 ), SILK_FIX_CONST( 0.16, 16 ) ) );
     silk_assert( gain_mult_Q16 > 0 );
     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
         psEncCtrl->Gains_Q16[ k ] = silk_SMULWW( psEncCtrl->Gains_Q16[ k ], gain_mult_Q16 );
         silk_assert( psEncCtrl->Gains_Q16[ k ] >= 0 );
         psEncCtrl->Gains_Q16[ k ] = silk_ADD_POS_SAT32( psEncCtrl->Gains_Q16[ k ], gain_add_Q16 );
     }
 
-    gain_mult_Q16 = SILK_FIX_CONST( 1.0, 16 ) + silk_RSHIFT_ROUND( silk_MLA( SILK_FIX_CONST( INPUT_TILT, 26 ),
-        psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) ), 10 );
-    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
-        psEncCtrl->GainsPre_Q14[ k ] = silk_SMULWB( gain_mult_Q16, psEncCtrl->GainsPre_Q14[ k ] );
-    }
 
     /************************************************/
     /* Control low-frequency shaping and noise tilt */
     /************************************************/
     /* Less low frequency shaping for noisy inputs */
     strength_Q16 = silk_MUL( SILK_FIX_CONST( LOW_FREQ_SHAPING, 4 ), silk_SMLAWB( SILK_FIX_CONST( 1.0, 12 ),
         SILK_FIX_CONST( LOW_QUALITY_LOW_FREQ_SHAPING_DECR, 13 ), psEnc->sCmn.input_quality_bands_Q15[ 0 ] - SILK_FIX_CONST( 1.0, 15 ) ) );
     strength_Q16 = silk_RSHIFT( silk_MUL( strength_Q16, psEnc->sCmn.speech_activity_Q8 ), 8 );
@@ -405,24 +372,16 @@ void silk_noise_shape_analysis_FIX(
             psEncCtrl->LF_shp_Q14[ k ] = psEncCtrl->LF_shp_Q14[ 0 ];
         }
         Tilt_Q16 = -SILK_FIX_CONST( HP_NOISE_COEF, 16 );
     }
 
     /****************************/
     /* HARMONIC SHAPING CONTROL */
     /****************************/
-    /* Control boosting of harmonic frequencies */
-    HarmBoost_Q16 = silk_SMULWB( silk_SMULWB( SILK_FIX_CONST( 1.0, 17 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 3 ),
-        psEnc->LTPCorr_Q15 ), SILK_FIX_CONST( LOW_RATE_HARMONIC_BOOST, 16 ) );
-
-    /* More harmonic boost for noisy input signals */
-    HarmBoost_Q16 = silk_SMLAWB( HarmBoost_Q16,
-        SILK_FIX_CONST( 1.0, 16 ) - silk_LSHIFT( psEncCtrl->input_quality_Q14, 2 ), SILK_FIX_CONST( LOW_INPUT_QUALITY_HARMONIC_BOOST, 16 ) );
-
     if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
         /* More harmonic noise shaping for high bitrates or noisy input */
         HarmShapeGain_Q16 = silk_SMLAWB( SILK_FIX_CONST( HARMONIC_SHAPING, 16 ),
                 SILK_FIX_CONST( 1.0, 16 ) - silk_SMULWB( SILK_FIX_CONST( 1.0, 18 ) - silk_LSHIFT( psEncCtrl->coding_quality_Q14, 4 ),
                 psEncCtrl->input_quality_Q14 ), SILK_FIX_CONST( HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING, 16 ) );
 
         /* Less harmonic noise shaping for less periodic signals */
         HarmShapeGain_Q16 = silk_SMULWB( silk_LSHIFT( HarmShapeGain_Q16, 1 ),
@@ -430,22 +389,19 @@ void silk_noise_shape_analysis_FIX(
     } else {
         HarmShapeGain_Q16 = 0;
     }
 
     /*************************/
     /* Smooth over subframes */
     /*************************/
     for( k = 0; k < MAX_NB_SUBFR; k++ ) {
-        psShapeSt->HarmBoost_smth_Q16 =
-            silk_SMLAWB( psShapeSt->HarmBoost_smth_Q16,     HarmBoost_Q16     - psShapeSt->HarmBoost_smth_Q16,     SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
         psShapeSt->HarmShapeGain_smth_Q16 =
             silk_SMLAWB( psShapeSt->HarmShapeGain_smth_Q16, HarmShapeGain_Q16 - psShapeSt->HarmShapeGain_smth_Q16, SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
         psShapeSt->Tilt_smth_Q16 =
             silk_SMLAWB( psShapeSt->Tilt_smth_Q16,          Tilt_Q16          - psShapeSt->Tilt_smth_Q16,          SILK_FIX_CONST( SUBFR_SMTH_COEF, 16 ) );
 
-        psEncCtrl->HarmBoost_Q14[ k ]     = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmBoost_smth_Q16,     2 );
         psEncCtrl->HarmShapeGain_Q14[ k ] = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->HarmShapeGain_smth_Q16, 2 );
         psEncCtrl->Tilt_Q14[ k ]          = ( opus_int )silk_RSHIFT_ROUND( psShapeSt->Tilt_smth_Q16,          2 );
     }
     RESTORE_STACK;
 }
 #endif /* OVERRIDE_silk_noise_shape_analysis_FIX */
--- a/media/libopus/silk/fixed/pitch_analysis_core_FIX.c
+++ b/media/libopus/silk/fixed/pitch_analysis_core_FIX.c
@@ -75,55 +75,57 @@ static void silk_P_Ana_calc_energy_st3(
     opus_int          complexity,                      /* I Complexity setting          */
     int               arch                             /* I Run-time architecture       */
 );
 
 /*************************************************************/
 /*      FIXED POINT CORE PITCH ANALYSIS FUNCTION             */
 /*************************************************************/
 opus_int silk_pitch_analysis_core(                  /* O    Voicing estimate: 0 voiced, 1 unvoiced                      */
-    const opus_int16            *frame,             /* I    Signal of length PE_FRAME_LENGTH_MS*Fs_kHz                  */
+    const opus_int16            *frame_unscaled,    /* 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_Q13,  /* 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                                    */
     int                         arch                /* I    Run-time architecture                                       */
 )
 {
-    VARDECL( opus_int16, frame_8kHz );
+    VARDECL( opus_int16, frame_8kHz_buf );
     VARDECL( opus_int16, frame_4kHz );
+    VARDECL( opus_int16, frame_scaled );
     opus_int32 filt_state[ 6 ];
-    const opus_int16 *input_frame_ptr;
+    const opus_int16 *frame, *frame_8kHz;
     opus_int   i, k, d, j;
     VARDECL( opus_int16, C );
     VARDECL( opus_int32, xcorr32 );
     const opus_int16 *target_ptr, *basis_ptr;
-    opus_int32 cross_corr, normalizer, energy, shift, energy_basis, energy_target;
-    opus_int   d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp;
+    opus_int32 cross_corr, normalizer, energy, energy_basis, energy_target;
+    opus_int   d_srch[ PE_D_SRCH_LENGTH ], Cmax, length_d_srch, length_d_comp, shift;
     VARDECL( opus_int16, d_comp );
     opus_int32 sum, threshold, lag_counter;
     opus_int   CBimax, CBimax_new, CBimax_old, lag, start_lag, end_lag, lag_new;
     opus_int32 CC[ PE_NB_CBKS_STAGE2_EXT ], CCmax, CCmax_b, CCmax_new_b, CCmax_new;
     VARDECL( silk_pe_stage3_vals, energies_st3 );
     VARDECL( silk_pe_stage3_vals, cross_corr_st3 );
     opus_int   frame_length, frame_length_8kHz, frame_length_4kHz;
     opus_int   sf_length;
     opus_int   min_lag;
     opus_int   max_lag;
     opus_int32 contour_bias_Q15, diff;
     opus_int   nb_cbk_search, cbk_size;
     opus_int32 delta_lag_log2_sqr_Q7, lag_log2_Q7, prevLag_log2_Q7, prev_lag_bias_Q13;
     const opus_int8 *Lag_CB_ptr;
     SAVE_STACK;
+
     /* Check for valid sampling frequency */
     silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
 
     /* Check for valid complexity setting */
     silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
     silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
 
     silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) );
@@ -132,52 +134,55 @@ opus_int silk_pitch_analysis_core(      
     /* Set up frame lengths max / min lag for the sampling frequency */
     frame_length      = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * Fs_kHz;
     frame_length_4kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 4;
     frame_length_8kHz = ( PE_LTP_MEM_LENGTH_MS + nb_subfr * PE_SUBFR_LENGTH_MS ) * 8;
     sf_length         = PE_SUBFR_LENGTH_MS * Fs_kHz;
     min_lag           = PE_MIN_LAG_MS * Fs_kHz;
     max_lag           = PE_MAX_LAG_MS * Fs_kHz - 1;
 
+    /* Downscale input if necessary */
+    silk_sum_sqr_shift( &energy, &shift, frame_unscaled, frame_length );
+    shift += 3 - silk_CLZ32( energy );        /* at least two bits headroom */
+    ALLOC( frame_scaled, frame_length, opus_int16 );
+    if( shift > 0 ) {
+        shift = silk_RSHIFT( shift + 1, 1 );
+        for( i = 0; i < frame_length; i++ ) {
+            frame_scaled[ i ] = silk_RSHIFT( frame_unscaled[ i ], shift );
+        }
+        frame = frame_scaled;
+    } else {
+        frame = frame_unscaled;
+    }
+
+    ALLOC( frame_8kHz_buf, ( Fs_kHz == 8 ) ? 1 : frame_length_8kHz, opus_int16 );
     /* Resample from input sampled at Fs_kHz to 8 kHz */
-    ALLOC( frame_8kHz, frame_length_8kHz, opus_int16 );
     if( Fs_kHz == 16 ) {
         silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
-        silk_resampler_down2( filt_state, frame_8kHz, frame, frame_length );
+        silk_resampler_down2( filt_state, frame_8kHz_buf, frame, frame_length );
+        frame_8kHz = frame_8kHz_buf;
     } else if( Fs_kHz == 12 ) {
         silk_memset( filt_state, 0, 6 * sizeof( opus_int32 ) );
-        silk_resampler_down2_3( filt_state, frame_8kHz, frame, frame_length );
+        silk_resampler_down2_3( filt_state, frame_8kHz_buf, frame, frame_length );
+        frame_8kHz = frame_8kHz_buf;
     } else {
         silk_assert( Fs_kHz == 8 );
-        silk_memcpy( frame_8kHz, frame, frame_length_8kHz * sizeof(opus_int16) );
+        frame_8kHz = frame;
     }
 
     /* Decimate again to 4 kHz */
     silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );/* Set state to zero */
     ALLOC( frame_4kHz, frame_length_4kHz, opus_int16 );
     silk_resampler_down2( filt_state, frame_4kHz, frame_8kHz, frame_length_8kHz );
 
     /* Low-pass filter */
     for( i = frame_length_4kHz - 1; i > 0; i-- ) {
         frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
     }
 
-    /*******************************************************************************
-    ** Scale 4 kHz signal down to prevent correlations measures from overflowing
-    ** find scaling as max scaling for each 8kHz(?) subframe
-    *******************************************************************************/
-
-    /* Inner product is calculated with different lengths, so scale for the worst case */
-    silk_sum_sqr_shift( &energy, &shift, frame_4kHz, frame_length_4kHz );
-    if( shift > 0 ) {
-        shift = silk_RSHIFT( shift, 1 );
-        for( i = 0; i < frame_length_4kHz; i++ ) {
-            frame_4kHz[ i ] = silk_RSHIFT( frame_4kHz[ i ], shift );
-        }
-    }
 
     /******************************************************************************
     * FIRST STAGE, operating in 4 khz
     ******************************************************************************/
     ALLOC( C, nb_subfr * CSTRIDE_8KHZ, opus_int16 );
     ALLOC( xcorr32, MAX_LAG_4KHZ-MIN_LAG_4KHZ+1, opus_int32 );
     silk_memset( C, 0, (nb_subfr >> 1) * CSTRIDE_4KHZ * sizeof( opus_int16 ) );
     target_ptr = &frame_4kHz[ silk_LSHIFT( SF_LENGTH_4KHZ, 2 ) ];
@@ -306,28 +311,16 @@ opus_int silk_pitch_analysis_core(      
             length_d_comp++;
         }
     }
 
     /**********************************************************************************
     ** SECOND STAGE, operating at 8 kHz, on lag sections with high correlation
     *************************************************************************************/
 
-    /******************************************************************************
-    ** Scale signal down to avoid correlations measures from overflowing
-    *******************************************************************************/
-    /* find scaling as max scaling for each subframe */
-    silk_sum_sqr_shift( &energy, &shift, frame_8kHz, frame_length_8kHz );
-    if( shift > 0 ) {
-        shift = silk_RSHIFT( shift, 1 );
-        for( i = 0; i < frame_length_8kHz; i++ ) {
-            frame_8kHz[ i ] = silk_RSHIFT( frame_8kHz[ i ], shift );
-        }
-    }
-
     /*********************************************************************************
     * Find energy of each subframe projected onto its history, for a range of delays
     *********************************************************************************/
     silk_memset( C, 0, nb_subfr * CSTRIDE_8KHZ * sizeof( opus_int16 ) );
 
     target_ptr = &frame_8kHz[ PE_LTP_MEM_LENGTH_MS * 8 ];
     for( k = 0; k < nb_subfr; k++ ) {
 
@@ -457,34 +450,16 @@ opus_int silk_pitch_analysis_core(      
         return 1;
     }
 
     /* Output normalized correlation */
     *LTPCorr_Q15 = (opus_int)silk_LSHIFT( silk_DIV32_16( CCmax, nb_subfr ), 2 );
     silk_assert( *LTPCorr_Q15 >= 0 );
 
     if( Fs_kHz > 8 ) {
-        VARDECL( opus_int16, scratch_mem );
-        /***************************************************************************/
-        /* Scale input signal down to avoid correlations measures from overflowing */
-        /***************************************************************************/
-        /* find scaling as max scaling for each subframe */
-        silk_sum_sqr_shift( &energy, &shift, frame, frame_length );
-        ALLOC( scratch_mem, shift > 0 ? frame_length : ALLOC_NONE, opus_int16 );
-        if( shift > 0 ) {
-            /* Move signal to scratch mem because the input signal should be unchanged */
-            shift = silk_RSHIFT( shift, 1 );
-            for( i = 0; i < frame_length; i++ ) {
-                scratch_mem[ i ] = silk_RSHIFT( frame[ i ], shift );
-            }
-            input_frame_ptr = scratch_mem;
-        } else {
-            input_frame_ptr = frame;
-        }
-
         /* Search in original signal */
 
         CBimax_old = CBimax;
         /* Compensate for decimation */
         silk_assert( lag == silk_SAT16( lag ) );
         if( Fs_kHz == 12 ) {
             lag = silk_RSHIFT( silk_SMULBB( lag, 3 ), 1 );
         } else if( Fs_kHz == 16 ) {
@@ -514,24 +489,24 @@ opus_int silk_pitch_analysis_core(      
             nb_cbk_search   = PE_NB_CBKS_STAGE3_10MS;
             cbk_size        = PE_NB_CBKS_STAGE3_10MS;
             Lag_CB_ptr      = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
         }
 
         /* Calculate the correlations and energies needed in stage 3 */
         ALLOC( energies_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals );
         ALLOC( cross_corr_st3, nb_subfr * nb_cbk_search, silk_pe_stage3_vals );
-        silk_P_Ana_calc_corr_st3(  cross_corr_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch );
-        silk_P_Ana_calc_energy_st3( energies_st3, input_frame_ptr, start_lag, sf_length, nb_subfr, complexity, arch );
+        silk_P_Ana_calc_corr_st3(  cross_corr_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
+        silk_P_Ana_calc_energy_st3( energies_st3, frame, start_lag, sf_length, nb_subfr, complexity, arch );
 
         lag_counter = 0;
         silk_assert( lag == silk_SAT16( lag ) );
         contour_bias_Q15 = silk_DIV32_16( SILK_FIX_CONST( PE_FLATCONTOUR_BIAS, 15 ), lag );
 
-        target_ptr = &input_frame_ptr[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
+        target_ptr = &frame[ PE_LTP_MEM_LENGTH_MS * Fs_kHz ];
         energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, nb_subfr * sf_length, arch ), 1 );
         for( d = start_lag; d <= end_lag; d++ ) {
             for( j = 0; j < nb_cbk_search; j++ ) {
                 cross_corr = 0;
                 energy     = energy_target;
                 for( k = 0; k < nb_subfr; k++ ) {
                     cross_corr = silk_ADD32( cross_corr,
                         matrix_ptr( cross_corr_st3, k, j,
deleted file mode 100644
--- a/media/libopus/silk/fixed/prefilter_FIX.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "main_FIX.h"
-#include "stack_alloc.h"
-#include "tuning_parameters.h"
-
-#if defined(MIPSr1_ASM)
-#include "mips/prefilter_FIX_mipsr1.h"
-#endif
-
-
-#if !defined(OVERRIDE_silk_warped_LPC_analysis_filter_FIX)
-#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
-    ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
-#endif
-
-/* Prefilter for finding Quantizer input signal */
-static OPUS_INLINE void silk_prefilt_FIX(
-    silk_prefilter_state_FIX    *P,                         /* I/O  state                               */
-    opus_int32                  st_res_Q12[],               /* I    short term residual signal          */
-    opus_int32                  xw_Q3[],                    /* O    prefiltered signal                  */
-    opus_int32                  HarmShapeFIRPacked_Q12,     /* I    Harmonic shaping coeficients        */
-    opus_int                    Tilt_Q14,                   /* I    Tilt shaping coeficient             */
-    opus_int32                  LF_shp_Q14,                 /* I    Low-frequancy shaping coeficients   */
-    opus_int                    lag,                        /* I    Lag for harmonic shaping            */
-    opus_int                    length                      /* I    Length of signals                   */
-);
-
-void silk_warped_LPC_analysis_filter_FIX_c(
-          opus_int32            state[],                    /* I/O  State [order + 1]                   */
-          opus_int32            res_Q2[],                   /* O    Residual signal [length]            */
-    const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
-    const opus_int16            input[],                    /* I    Input signal [length]               */
-    const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
-    const opus_int              length,                     /* I    Length of input signal              */
-    const opus_int              order                       /* I    Filter order (even)                 */
-)
-{
-    opus_int     n, i;
-    opus_int32   acc_Q11, tmp1, tmp2;
-
-    /* Order must be even */
-    silk_assert( ( order & 1 ) == 0 );
-
-    for( n = 0; n < length; n++ ) {
-        /* Output of lowpass section */
-        tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
-        state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
-        /* Output of allpass section */
-        tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
-        state[ 1 ] = tmp2;
-        acc_Q11 = silk_RSHIFT( order, 1 );
-        acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
-        /* Loop over allpass sections */
-        for( i = 2; i < order; i += 2 ) {
-            /* Output of allpass section */
-            tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
-            state[ i ] = tmp1;
-            acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
-            /* Output of allpass section */
-            tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
-            state[ i + 1 ] = tmp2;
-            acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
-        }
-        state[ order ] = tmp1;
-        acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
-        res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
-    }
-}
-
-void silk_prefilter_FIX(
-    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state                                                               */
-    const silk_encoder_control_FIX  *psEncCtrl,                             /* I    Encoder control                                                             */
-    opus_int32                      xw_Q3[],                                /* O    Weighted signal                                                             */
-    const opus_int16                x[]                                     /* I    Speech signal                                                               */
-)
-{
-    silk_prefilter_state_FIX *P = &psEnc->sPrefilt;
-    opus_int   j, k, lag;
-    opus_int32 tmp_32;
-    const opus_int16 *AR1_shp_Q13;
-    const opus_int16 *px;
-    opus_int32 *pxw_Q3;
-    opus_int   HarmShapeGain_Q12, Tilt_Q14;
-    opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14;
-    VARDECL( opus_int32, x_filt_Q12 );
-    VARDECL( opus_int32, st_res_Q2 );
-    opus_int16 B_Q10[ 2 ];
-    SAVE_STACK;
-
-    /* Set up pointers */
-    px  = x;
-    pxw_Q3 = xw_Q3;
-    lag = P->lagPrev;
-    ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 );
-    ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 );
-    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
-        /* Update Variables that change per sub frame */
-        if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
-            lag = psEncCtrl->pitchL[ k ];
-        }
-
-        /* Noise shape parameters */
-        HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] );
-        silk_assert( HarmShapeGain_Q12 >= 0 );
-        HarmShapeFIRPacked_Q12  =                          silk_RSHIFT( HarmShapeGain_Q12, 2 );
-        HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 );
-        Tilt_Q14    = psEncCtrl->Tilt_Q14[   k ];
-        LF_shp_Q14  = psEncCtrl->LF_shp_Q14[ k ];
-        AR1_shp_Q13 = &psEncCtrl->AR1_Q13[   k * MAX_SHAPE_LPC_ORDER ];
-
-        /* Short term FIR filtering*/
-        silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px,
-            psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder, psEnc->sCmn.arch );
-
-        /* Reduce (mainly) low frequencies during harmonic emphasis */
-        B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 );
-        tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 );   /* Q26 */
-        tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) );    /* Q26 */
-        tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] );                                                /* Q24 */
-        tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 );                                                                     /* Q10 */
-        B_Q10[ 1 ]= silk_SAT16( tmp_32 );
-        x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] );
-        for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
-            x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] );
-        }
-        P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ];
-
-        silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length );
-
-        px  += psEnc->sCmn.subfr_length;
-        pxw_Q3 += psEnc->sCmn.subfr_length;
-    }
-
-    P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
-    RESTORE_STACK;
-}
-
-#ifndef OVERRIDE_silk_prefilt_FIX
-/* Prefilter for finding Quantizer input signal */
-static OPUS_INLINE void silk_prefilt_FIX(
-    silk_prefilter_state_FIX    *P,                         /* I/O  state                               */
-    opus_int32                  st_res_Q12[],               /* I    short term residual signal          */
-    opus_int32                  xw_Q3[],                    /* O    prefiltered signal                  */
-    opus_int32                  HarmShapeFIRPacked_Q12,     /* I    Harmonic shaping coeficients        */
-    opus_int                    Tilt_Q14,                   /* I    Tilt shaping coeficient             */
-    opus_int32                  LF_shp_Q14,                 /* I    Low-frequancy shaping coeficients   */
-    opus_int                    lag,                        /* I    Lag for harmonic shaping            */
-    opus_int                    length                      /* I    Length of signals                   */
-)
-{
-    opus_int   i, idx, LTP_shp_buf_idx;
-    opus_int32 n_LTP_Q12, n_Tilt_Q10, n_LF_Q10;
-    opus_int32 sLF_MA_shp_Q12, sLF_AR_shp_Q12;
-    opus_int16 *LTP_shp_buf;
-
-    /* To speed up use temp variables instead of using the struct */
-    LTP_shp_buf     = P->sLTP_shp;
-    LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
-    sLF_AR_shp_Q12  = P->sLF_AR_shp_Q12;
-    sLF_MA_shp_Q12  = P->sLF_MA_shp_Q12;
-
-    for( i = 0; i < length; i++ ) {
-        if( lag > 0 ) {
-            /* unrolled loop */
-            silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
-            idx = lag + LTP_shp_buf_idx;
-            n_LTP_Q12 = silk_SMULBB(            LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
-            n_LTP_Q12 = silk_SMLABT( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2    ) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
-            n_LTP_Q12 = silk_SMLABB( n_LTP_Q12, LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ], HarmShapeFIRPacked_Q12 );
-        } else {
-            n_LTP_Q12 = 0;
-        }
-
-        n_Tilt_Q10 = silk_SMULWB( sLF_AR_shp_Q12, Tilt_Q14 );
-        n_LF_Q10   = silk_SMLAWB( silk_SMULWT( sLF_AR_shp_Q12, LF_shp_Q14 ), sLF_MA_shp_Q12, LF_shp_Q14 );
-
-        sLF_AR_shp_Q12 = silk_SUB32( st_res_Q12[ i ], silk_LSHIFT( n_Tilt_Q10, 2 ) );
-        sLF_MA_shp_Q12 = silk_SUB32( sLF_AR_shp_Q12,  silk_LSHIFT( n_LF_Q10,   2 ) );
-
-        LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
-        LTP_shp_buf[ LTP_shp_buf_idx ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( sLF_MA_shp_Q12, 12 ) );
-
-        xw_Q3[i] = silk_RSHIFT_ROUND( silk_SUB32( sLF_MA_shp_Q12, n_LTP_Q12 ), 9 );
-    }
-
-    /* Copy temp variable back to state */
-    P->sLF_AR_shp_Q12   = sLF_AR_shp_Q12;
-    P->sLF_MA_shp_Q12   = sLF_MA_shp_Q12;
-    P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
-}
-#endif /* OVERRIDE_silk_prefilt_FIX */
--- a/media/libopus/silk/fixed/schur64_FIX.c
+++ b/media/libopus/silk/fixed/schur64_FIX.c
@@ -38,27 +38,28 @@ opus_int32 silk_schur64(                
     const opus_int32            c[],                /* I    Correlations [order+1]                                      */
     opus_int32                  order               /* I    Prediction order                                            */
 )
 {
     opus_int   k, n;
     opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
     opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31;
 
-    silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
+    silk_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
 
     /* Check for invalid input */
     if( c[ 0 ] <= 0 ) {
         silk_memset( rc_Q16, 0, order * sizeof( opus_int32 ) );
         return 0;
     }
 
-    for( k = 0; k < order + 1; k++ ) {
+    k = 0;
+    do {
         C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ];
-    }
+    } while( ++k <= order );
 
     for( k = 0; k < order; k++ ) {
         /* Check that we won't be getting an unstable rc, otherwise stop here. */
         if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) {
            if ( C[ k + 1 ][ 0 ] > 0 ) {
               rc_Q16[ k ] = -SILK_FIX_CONST( .99f, 16 );
            } else {
               rc_Q16[ k ] = SILK_FIX_CONST( .99f, 16 );
--- a/media/libopus/silk/fixed/schur_FIX.c
+++ b/media/libopus/silk/fixed/schur_FIX.c
@@ -38,38 +38,39 @@ opus_int32 silk_schur(                  
     const opus_int32            *c,                 /* I    correlations [order+1]                                      */
     const opus_int32            order               /* I    prediction order                                            */
 )
 {
     opus_int        k, n, lz;
     opus_int32    C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
     opus_int32    Ctmp1, Ctmp2, rc_tmp_Q15;
 
-    silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
+    silk_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
 
     /* Get number of leading zeros */
     lz = silk_CLZ32( c[ 0 ] );
 
     /* Copy correlations and adjust level to Q30 */
+    k = 0;
     if( lz < 2 ) {
         /* lz must be 1, so shift one to the right */
-        for( k = 0; k < order + 1; k++ ) {
+        do {
             C[ k ][ 0 ] = C[ k ][ 1 ] = silk_RSHIFT( c[ k ], 1 );
-        }
+        } while( ++k <= order );
     } else if( lz > 2 ) {
         /* Shift to the left */
         lz -= 2;
-        for( k = 0; k < order + 1; k++ ) {
+        do {
             C[ k ][ 0 ] = C[ k ][ 1 ] = silk_LSHIFT( c[ k ], lz );
-        }
+        } while( ++k <= order );
     } else {
         /* No need to shift */
-        for( k = 0; k < order + 1; k++ ) {
+        do {
             C[ k ][ 0 ] = C[ k ][ 1 ] = c[ k ];
-        }
+        } while( ++k <= order );
     }
 
     for( k = 0; k < order; k++ ) {
         /* Check that we won't be getting an unstable rc, otherwise stop here. */
         if (silk_abs_int32(C[ k + 1 ][ 0 ]) >= C[ 0 ][ 1 ]) {
            if ( C[ k + 1 ][ 0 ] > 0 ) {
               rc_Q15[ k ] = -SILK_FIX_CONST( .99f, 15 );
            } else {
deleted file mode 100644
--- a/media/libopus/silk/fixed/solve_LS_FIX.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "main_FIX.h"
-#include "stack_alloc.h"
-#include "tuning_parameters.h"
-
-/*****************************/
-/* Internal function headers */
-/*****************************/
-
-typedef struct {
-    opus_int32 Q36_part;
-    opus_int32 Q48_part;
-} inv_D_t;
-
-/* Factorize square matrix A into LDL form */
-static OPUS_INLINE void silk_LDL_factorize_FIX(
-    opus_int32          *A,         /* I/O Pointer to Symetric Square Matrix                            */
-    opus_int            M,          /* I   Size of Matrix                                               */
-    opus_int32          *L_Q16,     /* I/O Pointer to Square Upper triangular Matrix                    */
-    inv_D_t             *inv_D      /* I/O Pointer to vector holding inverted diagonal elements of D    */
-);
-
-/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */
-static OPUS_INLINE void silk_LS_SolveFirst_FIX(
-    const opus_int32    *L_Q16,     /* I    Pointer to Lower Triangular Matrix                          */
-    opus_int            M,          /* I    Dim of Matrix equation                                      */
-    const opus_int32    *b,         /* I    b Vector                                                    */
-    opus_int32          *x_Q16      /* O    x Vector                                                    */
-);
-
-/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */
-static OPUS_INLINE void silk_LS_SolveLast_FIX(
-    const opus_int32    *L_Q16,     /* I    Pointer to Lower Triangular Matrix                          */
-    const opus_int      M,          /* I    Dim of Matrix equation                                      */
-    const opus_int32    *b,         /* I    b Vector                                                    */
-    opus_int32          *x_Q16      /* O    x Vector                                                    */
-);
-
-static OPUS_INLINE void silk_LS_divide_Q16_FIX(
-    opus_int32          T[],        /* I/O  Numenator vector                                            */
-    inv_D_t             *inv_D,     /* I    1 / D vector                                                */
-    opus_int            M           /* I    dimension                                                   */
-);
-
-/* Solves Ax = b, assuming A is symmetric */
-void silk_solve_LDL_FIX(
-    opus_int32                      *A,                                     /* I    Pointer to symetric square matrix A                                         */
-    opus_int                        M,                                      /* I    Size of matrix                                                              */
-    const opus_int32                *b,                                     /* I    Pointer to b vector                                                         */
-    opus_int32                      *x_Q16                                  /* O    Pointer to x solution vector                                                */
-)
-{
-    VARDECL( opus_int32, L_Q16 );
-    opus_int32 Y[      MAX_MATRIX_SIZE ];
-    inv_D_t   inv_D[  MAX_MATRIX_SIZE ];
-    SAVE_STACK;
-
-    silk_assert( M <= MAX_MATRIX_SIZE );
-    ALLOC( L_Q16, M * M, opus_int32 );
-
-    /***************************************************
-    Factorize A by LDL such that A = L*D*L',
-    where L is lower triangular with ones on diagonal
-    ****************************************************/
-    silk_LDL_factorize_FIX( A, M, L_Q16, inv_D );
-
-    /****************************************************
-    * substitute D*L'*x = Y. ie:
-    L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b
-    ******************************************************/
-    silk_LS_SolveFirst_FIX( L_Q16, M, b, Y );
-
-    /****************************************************
-    D*L'*x = Y <=> L'*x = inv(D)*Y, because D is
-    diagonal just multiply with 1/d_i
-    ****************************************************/
-    silk_LS_divide_Q16_FIX( Y, inv_D, M );
-
-    /****************************************************
-    x = inv(L') * inv(D) * Y
-    *****************************************************/
-    silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 );
-    RESTORE_STACK;
-}
-
-static OPUS_INLINE void silk_LDL_factorize_FIX(
-    opus_int32          *A,         /* I/O Pointer to Symetric Square Matrix                            */
-    opus_int            M,          /* I   Size of Matrix                                               */
-    opus_int32          *L_Q16,     /* I/O Pointer to Square Upper triangular Matrix                    */
-    inv_D_t             *inv_D      /* I/O Pointer to vector holding inverted diagonal elements of D    */
-)
-{
-    opus_int   i, j, k, status, loop_count;
-    const opus_int32 *ptr1, *ptr2;
-    opus_int32 diag_min_value, tmp_32, err;
-    opus_int32 v_Q0[ MAX_MATRIX_SIZE ], D_Q0[ MAX_MATRIX_SIZE ];
-    opus_int32 one_div_diag_Q36, one_div_diag_Q40, one_div_diag_Q48;
-
-    silk_assert( M <= MAX_MATRIX_SIZE );
-
-    status = 1;
-    diag_min_value = silk_max_32( silk_SMMUL( silk_ADD_SAT32( A[ 0 ], A[ silk_SMULBB( M, M ) - 1 ] ), SILK_FIX_CONST( FIND_LTP_COND_FAC, 31 ) ), 1 << 9 );
-    for( loop_count = 0; loop_count < M && status == 1; loop_count++ ) {
-        status = 0;
-        for( j = 0; j < M; j++ ) {
-            ptr1 = matrix_adr( L_Q16, j, 0, M );
-            tmp_32 = 0;
-            for( i = 0; i < j; i++ ) {
-                v_Q0[ i ] = silk_SMULWW(         D_Q0[ i ], ptr1[ i ] ); /* Q0 */
-                tmp_32    = silk_SMLAWW( tmp_32, v_Q0[ i ], ptr1[ i ] ); /* Q0 */
-            }
-            tmp_32 = silk_SUB32( matrix_ptr( A, j, j, M ), tmp_32 );
-
-            if( tmp_32 < diag_min_value ) {
-                tmp_32 = silk_SUB32( silk_SMULBB( loop_count + 1, diag_min_value ), tmp_32 );
-                /* Matrix not positive semi-definite, or ill conditioned */
-                for( i = 0; i < M; i++ ) {
-                    matrix_ptr( A, i, i, M ) = silk_ADD32( matrix_ptr( A, i, i, M ), tmp_32 );
-                }
-                status = 1;
-                break;
-            }
-            D_Q0[ j ] = tmp_32;                         /* always < max(Correlation) */
-
-            /* two-step division */
-            one_div_diag_Q36 = silk_INVERSE32_varQ( tmp_32, 36 );                    /* Q36 */
-            one_div_diag_Q40 = silk_LSHIFT( one_div_diag_Q36, 4 );                   /* Q40 */
-            err = silk_SUB32( (opus_int32)1 << 24, silk_SMULWW( tmp_32, one_div_diag_Q40 ) );     /* Q24 */
-            one_div_diag_Q48 = silk_SMULWW( err, one_div_diag_Q40 );                 /* Q48 */
-
-            /* Save 1/Ds */
-            inv_D[ j ].Q36_part = one_div_diag_Q36;
-            inv_D[ j ].Q48_part = one_div_diag_Q48;
-
-            matrix_ptr( L_Q16, j, j, M ) = 65536; /* 1.0 in Q16 */
-            ptr1 = matrix_adr( A, j, 0, M );
-            ptr2 = matrix_adr( L_Q16, j + 1, 0, M );
-            for( i = j + 1; i < M; i++ ) {
-                tmp_32 = 0;
-                for( k = 0; k < j; k++ ) {
-                    tmp_32 = silk_SMLAWW( tmp_32, v_Q0[ k ], ptr2[ k ] ); /* Q0 */
-                }
-                tmp_32 = silk_SUB32( ptr1[ i ], tmp_32 ); /* always < max(Correlation) */
-
-                /* tmp_32 / D_Q0[j] : Divide to Q16 */
-                matrix_ptr( L_Q16, i, j, M ) = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ),
-                    silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) );
-
-                /* go to next column */
-                ptr2 += M;
-            }
-        }
-    }
-
-    silk_assert( status == 0 );
-}
-
-static OPUS_INLINE void silk_LS_divide_Q16_FIX(
-    opus_int32          T[],        /* I/O  Numenator vector                                            */
-    inv_D_t             *inv_D,     /* I    1 / D vector                                                */
-    opus_int            M           /* I    dimension                                                   */
-)
-{
-    opus_int   i;
-    opus_int32 tmp_32;
-    opus_int32 one_div_diag_Q36, one_div_diag_Q48;
-
-    for( i = 0; i < M; i++ ) {
-        one_div_diag_Q36 = inv_D[ i ].Q36_part;
-        one_div_diag_Q48 = inv_D[ i ].Q48_part;
-
-        tmp_32 = T[ i ];
-        T[ i ] = silk_ADD32( silk_SMMUL( tmp_32, one_div_diag_Q48 ), silk_RSHIFT( silk_SMULWW( tmp_32, one_div_diag_Q36 ), 4 ) );
-    }
-}
-
-/* Solve Lx = b, when L is lower triangular and has ones on the diagonal */
-static OPUS_INLINE void silk_LS_SolveFirst_FIX(
-    const opus_int32    *L_Q16,     /* I    Pointer to Lower Triangular Matrix                          */
-    opus_int            M,          /* I    Dim of Matrix equation                                      */
-    const opus_int32    *b,         /* I    b Vector                                                    */
-    opus_int32          *x_Q16      /* O    x Vector                                                    */
-)
-{
-    opus_int i, j;
-    const opus_int32 *ptr32;
-    opus_int32 tmp_32;
-
-    for( i = 0; i < M; i++ ) {
-        ptr32 = matrix_adr( L_Q16, i, 0, M );
-        tmp_32 = 0;
-        for( j = 0; j < i; j++ ) {
-            tmp_32 = silk_SMLAWW( tmp_32, ptr32[ j ], x_Q16[ j ] );
-        }
-        x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 );
-    }
-}
-
-/* Solve L^t*x = b, where L is lower triangular with ones on the diagonal */
-static OPUS_INLINE void silk_LS_SolveLast_FIX(
-    const opus_int32    *L_Q16,     /* I    Pointer to Lower Triangular Matrix                          */
-    const opus_int      M,          /* I    Dim of Matrix equation                                      */
-    const opus_int32    *b,         /* I    b Vector                                                    */
-    opus_int32          *x_Q16      /* O    x Vector                                                    */
-)
-{
-    opus_int i, j;
-    const opus_int32 *ptr32;
-    opus_int32 tmp_32;
-
-    for( i = M - 1; i >= 0; i-- ) {
-        ptr32 = matrix_adr( L_Q16, 0, i, M );
-        tmp_32 = 0;
-        for( j = M - 1; j > i; j-- ) {
-            tmp_32 = silk_SMLAWW( tmp_32, ptr32[ silk_SMULBB( j, M ) ], x_Q16[ j ] );
-        }
-        x_Q16[ i ] = silk_SUB32( b[ i ], tmp_32 );
-    }
-}
--- a/media/libopus/silk/fixed/structs_FIX.h
+++ b/media/libopus/silk/fixed/structs_FIX.h
@@ -43,68 +43,50 @@ extern "C"
 typedef struct {
     opus_int8                   LastGainIndex;
     opus_int32                  HarmBoost_smth_Q16;
     opus_int32                  HarmShapeGain_smth_Q16;
     opus_int32                  Tilt_smth_Q16;
 } silk_shape_state_FIX;
 
 /********************************/
-/* Prefilter state              */
-/********************************/
-typedef struct {
-    opus_int16                  sLTP_shp[ LTP_BUF_LENGTH ];
-    opus_int32                  sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ];
-    opus_int                    sLTP_shp_buf_idx;
-    opus_int32                  sLF_AR_shp_Q12;
-    opus_int32                  sLF_MA_shp_Q12;
-    opus_int32                  sHarmHP_Q2;
-    opus_int32                  rand_seed;
-    opus_int                    lagPrev;
-} silk_prefilter_state_FIX;
-
-/********************************/
 /* Encoder state FIX            */
 /********************************/
 typedef struct {
     silk_encoder_state          sCmn;                                   /* Common struct, shared with floating-point code       */
     silk_shape_state_FIX        sShape;                                 /* Shape state                                          */
-    silk_prefilter_state_FIX    sPrefilt;                               /* Prefilter State                                      */
 
     /* Buffer for find pitch and noise shape analysis */
     silk_DWORD_ALIGN opus_int16 x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis  */
     opus_int                    LTPCorr_Q15;                            /* Normalized correlation from pitch lag estimator      */
+    opus_int32                    resNrgSmth;
 } silk_encoder_state_FIX;
 
 /************************/
 /* Encoder control FIX  */
 /************************/
 typedef struct {
     /* Prediction and coding parameters */
     opus_int32                  Gains_Q16[ MAX_NB_SUBFR ];
     silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
     opus_int16                  LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
     opus_int                    LTP_scale_Q14;
     opus_int                    pitchL[ MAX_NB_SUBFR ];
 
     /* Noise shaping parameters */
     /* Testing */
-    silk_DWORD_ALIGN opus_int16 AR1_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
-    silk_DWORD_ALIGN opus_int16 AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+    silk_DWORD_ALIGN opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
     opus_int32                  LF_shp_Q14[        MAX_NB_SUBFR ];      /* Packs two int16 coefficients per int32 value         */
-    opus_int                    GainsPre_Q14[      MAX_NB_SUBFR ];
-    opus_int                    HarmBoost_Q14[     MAX_NB_SUBFR ];
     opus_int                    Tilt_Q14[          MAX_NB_SUBFR ];
     opus_int                    HarmShapeGain_Q14[ MAX_NB_SUBFR ];
     opus_int                    Lambda_Q10;
     opus_int                    input_quality_Q14;
     opus_int                    coding_quality_Q14;
 
     /* measures */
-    opus_int                    sparseness_Q8;
     opus_int32                  predGain_Q16;
     opus_int                    LTPredCodGain_Q7;
     opus_int32                  ResNrg[ MAX_NB_SUBFR ];                 /* Residual energy per subframe                         */
     opus_int                    ResNrgQ[ MAX_NB_SUBFR ];                /* Q domain for the residual energy > 0                 */
 
     /* Parameters for CBR mode */
     opus_int32                  GainsUnq_Q16[ MAX_NB_SUBFR ];
     opus_int8                   lastGainIndexPrev;
--- a/media/libopus/silk/fixed/warped_autocorrelation_FIX.c
+++ b/media/libopus/silk/fixed/warped_autocorrelation_FIX.c
@@ -26,27 +26,23 @@ POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "main_FIX.h"
 
-#define QC  10
-#define QS  14
-
 #if defined(MIPSr1_ASM)
 #include "mips/warped_autocorrelation_FIX_mipsr1.h"
 #endif
 
 
-#ifndef OVERRIDE_silk_warped_autocorrelation_FIX
 /* Autocorrelations for a warped frequency axis */
-void silk_warped_autocorrelation_FIX(
+void silk_warped_autocorrelation_FIX_c(
           opus_int32                *corr,                                  /* O    Result [order + 1]                                                          */
           opus_int                  *scale,                                 /* O    Scaling of the correlation vector                                           */
     const opus_int16                *input,                                 /* I    Input data to correlate                                                     */
     const opus_int                  warping_Q16,                            /* I    Warping coefficient                                                         */
     const opus_int                  length,                                 /* I    Length of input                                                             */
     const opus_int                  order                                   /* I    Correlation order (even)                                                    */
 )
 {
@@ -87,9 +83,8 @@ void silk_warped_autocorrelation_FIX(
         }
     } else {
         for( i = 0; i < order + 1; i++ ) {
             corr[ i ] = (opus_int32)silk_CHECK_FIT32( silk_RSHIFT64( corr_QC[ i ], -lsh ) );
         }
     }
     silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/
 }
-#endif /* OVERRIDE_silk_warped_autocorrelation_FIX */
deleted file mode 100644
--- a/media/libopus/silk/fixed/x86/prefilter_FIX_sse.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* Copyright (c) 2014, Cisco Systems, INC
-   Written by XiangMingZhu WeiZhou MinPeng YanWang
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   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 <xmmintrin.h>
-#include <emmintrin.h>
-#include <smmintrin.h>
-#include "main.h"
-#include "celt/x86/x86cpu.h"
-
-void silk_warped_LPC_analysis_filter_FIX_sse4_1(
-    opus_int32                  state[],                    /* I/O  State [order + 1]                   */
-    opus_int32                  res_Q2[],                   /* O    Residual signal [length]            */
-    const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
-    const opus_int16            input[],                    /* I    Input signal [length]               */
-    const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
-    const opus_int              length,                     /* I    Length of input signal              */
-    const opus_int              order                       /* I    Filter order (even)                 */
-)
-{
-    opus_int     n, i;
-    opus_int32   acc_Q11, tmp1, tmp2;
-
-    /* Order must be even */
-    silk_assert( ( order & 1 ) == 0 );
-
-    if (order == 10)
-    {
-        if (0 == lambda_Q16)
-        {
-            __m128i coef_Q13_3210, coef_Q13_7654;
-            __m128i coef_Q13_0123, coef_Q13_4567;
-            __m128i state_0123, state_4567;
-            __m128i xmm_product1, xmm_product2;
-            __m128i xmm_tempa, xmm_tempb;
-
-            register opus_int32 sum;
-            register opus_int32 state_8, state_9, state_a;
-            register opus_int64 coef_Q13_8, coef_Q13_9;
-
-            silk_assert( length > 0 );
-
-            coef_Q13_3210 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 0 ] );
-            coef_Q13_7654 = OP_CVTEPI16_EPI32_M64( &coef_Q13[ 4 ] );
-
-            coef_Q13_0123 = _mm_shuffle_epi32( coef_Q13_3210, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-            coef_Q13_4567 = _mm_shuffle_epi32( coef_Q13_7654, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-
-            coef_Q13_8 = (opus_int64) coef_Q13[ 8 ];
-            coef_Q13_9 = (opus_int64) coef_Q13[ 9 ];
-
-            state_0123 = _mm_loadu_si128( (__m128i *)(&state[ 0 ] ) );
-            state_4567 = _mm_loadu_si128( (__m128i *)(&state[ 4 ] ) );
-
-            state_0123 = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-            state_4567 = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-
-            state_8 = state[ 8 ];
-            state_9 = state[ 9 ];
-            state_a = 0;
-
-            for( n = 0; n < length; n++ )
-            {
-                xmm_product1 = _mm_mul_epi32( coef_Q13_0123, state_0123 ); /* 64-bit multiply, only 2 pairs */
-                xmm_product2 = _mm_mul_epi32( coef_Q13_4567, state_4567 );
-
-                xmm_tempa = _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-                xmm_tempb = _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) );
-
-                xmm_product1 = _mm_srli_epi64( xmm_product1, 16 ); /* >> 16, zero extending works */
-                xmm_product2 = _mm_srli_epi64( xmm_product2, 16 );
-
-                xmm_tempa = _mm_mul_epi32( coef_Q13_3210, xmm_tempa );
-                xmm_tempb = _mm_mul_epi32( coef_Q13_7654, xmm_tempb );
-
-                xmm_tempa = _mm_srli_epi64( xmm_tempa, 16 );
-                xmm_tempb = _mm_srli_epi64( xmm_tempb, 16 );
-
-                xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_product1 );
-                xmm_tempb = _mm_add_epi32( xmm_tempb, xmm_product2 );
-                xmm_tempa = _mm_add_epi32( xmm_tempa, xmm_tempb );
-
-                sum  = (coef_Q13_8 * state_8) >> 16;
-                sum += (coef_Q13_9 * state_9) >> 16;
-
-                xmm_tempa = _mm_add_epi32( xmm_tempa, _mm_shuffle_epi32( xmm_tempa, _MM_SHUFFLE( 0, 0, 0, 2 ) ) );
-                sum += _mm_cvtsi128_si32( xmm_tempa);
-                res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( ( 5 + sum ), 9);
-
-                /* move right */
-                state_a = state_9;
-                state_9 = state_8;
-                state_8 = _mm_cvtsi128_si32( state_4567 );
-                state_4567 = _mm_alignr_epi8( state_0123, state_4567, 4 );
-
-                state_0123 = _mm_alignr_epi8( _mm_cvtsi32_si128( silk_LSHIFT( input[ n ], 14 ) ), state_0123, 4 );
-            }
-
-            _mm_storeu_si128( (__m128i *)( &state[ 0 ] ), _mm_shuffle_epi32( state_0123, _MM_SHUFFLE( 0, 1, 2, 3 ) ) );
-            _mm_storeu_si128( (__m128i *)( &state[ 4 ] ), _mm_shuffle_epi32( state_4567, _MM_SHUFFLE( 0, 1, 2, 3 ) ) );
-            state[ 8 ] = state_8;
-            state[ 9 ] = state_9;
-            state[ 10 ] = state_a;
-
-            return;
-        }
-    }
-
-    for( n = 0; n < length; n++ ) {
-        /* Output of lowpass section */
-        tmp2 = silk_SMLAWB( state[ 0 ], state[ 1 ], lambda_Q16 );
-        state[ 0 ] = silk_LSHIFT( input[ n ], 14 );
-        /* Output of allpass section */
-        tmp1 = silk_SMLAWB( state[ 1 ], state[ 2 ] - tmp2, lambda_Q16 );
-        state[ 1 ] = tmp2;
-        acc_Q11 = silk_RSHIFT( order, 1 );
-        acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ 0 ] );
-        /* Loop over allpass sections */
-        for( i = 2; i < order; i += 2 ) {
-            /* Output of allpass section */
-            tmp2 = silk_SMLAWB( state[ i ], state[ i + 1 ] - tmp1, lambda_Q16 );
-            state[ i ] = tmp1;
-            acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ i - 1 ] );
-            /* Output of allpass section */
-            tmp1 = silk_SMLAWB( state[ i + 1 ], state[ i + 2 ] - tmp2, lambda_Q16 );
-            state[ i + 1 ] = tmp2;
-            acc_Q11 = silk_SMLAWB( acc_Q11, tmp2, coef_Q13[ i ] );
-        }
-        state[ order ] = tmp1;
-        acc_Q11 = silk_SMLAWB( acc_Q11, tmp1, coef_Q13[ order - 1 ] );
-        res_Q2[ n ] = silk_LSHIFT( (opus_int32)input[ n ], 2 ) - silk_RSHIFT_ROUND( acc_Q11, 9 );
-    }
-}
--- a/media/libopus/silk/float/LPC_inv_pred_gain_FLP.c
+++ b/media/libopus/silk/float/LPC_inv_pred_gain_FLP.c
@@ -26,51 +26,48 @@ POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "SigProc_FIX.h"
 #include "SigProc_FLP.h"
-
-#define RC_THRESHOLD        0.9999f
+#include "define.h"
 
 /* compute inverse of LPC prediction gain, and                          */
 /* test if LPC coefficients are stable (all poles within unit circle)   */
 /* this code is based on silk_a2k_FLP()                                 */
 silk_float silk_LPC_inverse_pred_gain_FLP(  /* O    return inverse prediction gain, energy domain               */
     const silk_float    *A,                 /* I    prediction coefficients [order]                             */
     opus_int32          order               /* I    prediction order                                            */
 )
 {
     opus_int   k, n;
-    double     invGain, rc, rc_mult1, rc_mult2;
-    silk_float Atmp[ 2 ][ SILK_MAX_ORDER_LPC ];
-    silk_float *Aold, *Anew;
+    double     invGain, rc, rc_mult1, rc_mult2, tmp1, tmp2;
+    silk_float Atmp[ SILK_MAX_ORDER_LPC ];
 
-    Anew = Atmp[ order & 1 ];
-    silk_memcpy( Anew, A, order * sizeof(silk_float) );
+    silk_memcpy( Atmp, A, order * sizeof(silk_float) );
 
     invGain = 1.0;
     for( k = order - 1; k > 0; k-- ) {
-        rc = -Anew[ k ];
-        if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
+        rc = -Atmp[ k ];
+        rc_mult1 = 1.0f - rc * rc;
+        invGain *= rc_mult1;
+        if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
             return 0.0f;
         }
-        rc_mult1 = 1.0f - rc * rc;
         rc_mult2 = 1.0f / rc_mult1;
-        invGain *= rc_mult1;
-        /* swap pointers */
-        Aold = Anew;
-        Anew = Atmp[ k & 1 ];
-        for( n = 0; n < k; n++ ) {
-            Anew[ n ] = (silk_float)( ( Aold[ n ] - Aold[ k - n - 1 ] * rc ) * rc_mult2 );
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            tmp1 = Atmp[ n ];
+            tmp2 = Atmp[ k - n - 1 ];
+            Atmp[ n ]         = (silk_float)( ( tmp1 - tmp2 * rc ) * rc_mult2 );
+            Atmp[ k - n - 1 ] = (silk_float)( ( tmp2 - tmp1 * rc ) * rc_mult2 );
         }
     }
-    rc = -Anew[ 0 ];
-    if( rc > RC_THRESHOLD || rc < -RC_THRESHOLD ) {
+    rc = -Atmp[ 0 ];
+    rc_mult1 = 1.0f - rc * rc;
+    invGain *= rc_mult1;
+    if( invGain * MAX_PREDICTION_POWER_GAIN < 1.0f ) {
         return 0.0f;
     }
-    rc_mult1 = 1.0f - rc * rc;
-    invGain *= rc_mult1;
     return (silk_float)invGain;
 }
--- a/media/libopus/silk/float/SigProc_FLP.h
+++ b/media/libopus/silk/float/SigProc_FLP.h
@@ -63,23 +63,16 @@ silk_float silk_schur_FLP(              
 );
 
 void silk_k2a_FLP(
     silk_float          *A,                 /* O     prediction coefficients [order]                            */
     const silk_float    *rc,                /* I     reflection coefficients [order]                            */
     opus_int32          order               /* I     prediction order                                           */
 );
 
-/* Solve the normal equations using the Levinson-Durbin recursion */
-silk_float silk_levinsondurbin_FLP(         /* O    prediction error energy                                     */
-    silk_float          A[],                /* O    prediction coefficients [order]                             */
-    const silk_float    corr[],             /* I    input auto-correlations [order + 1]                         */
-    const opus_int      order               /* I    prediction order                                            */
-);
-
 /* compute autocorrelation */
 void silk_autocorrelation_FLP(
     silk_float          *results,           /* O    result (length correlationCount)                            */
     const silk_float    *inputData,         /* I    input data to correlate                                     */
     opus_int            inputDataSize,      /* I    length of input                                             */
     opus_int            correlationCount    /* I    number of correlation taps to compute                       */
 );
 
--- a/media/libopus/silk/float/encode_frame_FLP.c
+++ b/media/libopus/silk/float/encode_frame_FLP.c
@@ -24,16 +24,17 @@ CONTRACT, STRICT LIABILITY, OR TORT (INC
 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_FLP.h"
 #include "tuning_parameters.h"
 
 /* Low Bitrate Redundancy (LBRR) encoding. Reuse all parameters but encode with lower bitrate */
 static OPUS_INLINE void silk_LBRR_encode_FLP(
     silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
     silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
     const silk_float                xfw[],                              /* I    Input signal                                */
@@ -80,28 +81,30 @@ opus_int silk_encode_frame_FLP(
     opus_int                        condCoding,                         /* I    The type of conditional coding to use       */
     opus_int                        maxBits,                            /* I    If > 0: maximum number of output bits       */
     opus_int                        useCBR                              /* I    Flag to force constant-bitrate operation    */
 )
 {
     silk_encoder_control_FLP sEncCtrl;
     opus_int     i, iter, maxIter, found_upper, found_lower, ret = 0;
     silk_float   *x_frame, *res_pitch_frame;
-    silk_float   xfw[ MAX_FRAME_LENGTH ];
     silk_float   res_pitch[ 2 * MAX_FRAME_LENGTH + LA_PITCH_MAX ];
     ec_enc       sRangeEnc_copy, sRangeEnc_copy2;
     silk_nsq_state sNSQ_copy, sNSQ_copy2;
     opus_int32   seed_copy, nBits, nBits_lower, nBits_upper, gainMult_lower, gainMult_upper;
     opus_int32   gainsID, gainsID_lower, gainsID_upper;
     opus_int16   gainMult_Q8;
     opus_int16   ec_prevLagIndex_copy;
     opus_int     ec_prevSignalType_copy;
     opus_int8    LastGainIndex_copy2;
     opus_int32   pGains_Q16[ MAX_NB_SUBFR ];
     opus_uint8   ec_buf_copy[ 1275 ];
+    opus_int     gain_lock[ MAX_NB_SUBFR ] = {0};
+    opus_int16   best_gain_mult[ MAX_NB_SUBFR ];
+    opus_int     best_sum[ MAX_NB_SUBFR ];
 
     /* This is totally unnecessary but many compilers (including gcc) are too dumb to realise it */
     LastGainIndex_copy2 = nBits_lower = nBits_upper = gainMult_lower = gainMult_upper = 0;
 
     psEnc->sCmn.indices.Seed = psEnc->sCmn.frameCounter++ & 3;
 
     /**************************************************************/
     /* Set up Input Pointers, and insert frame in input buffer    */
@@ -134,32 +137,27 @@ opus_int silk_encode_frame_FLP(
         /************************/
         /* Noise shape analysis */
         /************************/
         silk_noise_shape_analysis_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame );
 
         /***************************************************/
         /* Find linear prediction coefficients (LPC + LTP) */
         /***************************************************/
-        silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch, x_frame, condCoding );
+        silk_find_pred_coefs_FLP( psEnc, &sEncCtrl, res_pitch_frame, x_frame, condCoding );
 
         /****************************************/
         /* Process gains                        */
         /****************************************/
         silk_process_gains_FLP( psEnc, &sEncCtrl, condCoding );
 
-        /*****************************************/
-        /* Prefiltering for noise shaper         */
-        /*****************************************/
-        silk_prefilter_FLP( psEnc, &sEncCtrl, xfw, x_frame );
-
         /****************************************/
         /* Low Bitrate Redundant Encoding       */
         /****************************************/
-        silk_LBRR_encode_FLP( psEnc, &sEncCtrl, xfw, condCoding );
+        silk_LBRR_encode_FLP( psEnc, &sEncCtrl, x_frame, condCoding );
 
         /* Loop over quantizer and entroy coding to control bitrate */
         maxIter = 6;
         gainMult_Q8 = SILK_FIX_CONST( 1, 8 );
         found_lower = 0;
         found_upper = 0;
         gainsID = silk_gains_ID( psEnc->sCmn.indices.GainsIndices, psEnc->sCmn.nb_subfr );
         gainsID_lower = -1;
@@ -183,31 +181,62 @@ opus_int silk_encode_frame_FLP(
                     psEnc->sCmn.indices.Seed = seed_copy;
                     psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
                     psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
                 }
 
                 /*****************************************/
                 /* Noise shaping quantization            */
                 /*****************************************/
-                silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, xfw );
+                silk_NSQ_wrapper_FLP( psEnc, &sEncCtrl, &psEnc->sCmn.indices, &psEnc->sCmn.sNSQ, psEnc->sCmn.pulses, x_frame );
+
+                if ( iter == maxIter && !found_lower ) {
+                    silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
+                }
 
                 /****************************************/
                 /* Encode Parameters                    */
                 /****************************************/
                 silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
 
                 /****************************************/
                 /* Encode Excitation Signal             */
                 /****************************************/
                 silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
                       psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
 
                 nBits = ec_tell( psRangeEnc );
 
+                /* If we still bust after the last iteration, do some damage control. */
+                if ( iter == maxIter && !found_lower && nBits > maxBits ) {
+                    silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
+
+                    /* Keep gains the same as the last frame. */
+                    psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
+                    for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+                        psEnc->sCmn.indices.GainsIndices[ i ] = 4;
+                    }
+                    if (condCoding != CODE_CONDITIONALLY) {
+                       psEnc->sCmn.indices.GainsIndices[ 0 ] = sEncCtrl.lastGainIndexPrev;
+                    }
+                    psEnc->sCmn.ec_prevLagIndex = ec_prevLagIndex_copy;
+                    psEnc->sCmn.ec_prevSignalType = ec_prevSignalType_copy;
+                    /* Clear all pulses. */
+                    for ( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
+                        psEnc->sCmn.pulses[ i ] = 0;
+                    }
+
+                    silk_encode_indices( &psEnc->sCmn, psRangeEnc, psEnc->sCmn.nFramesEncoded, 0, condCoding );
+
+                    silk_encode_pulses( psRangeEnc, psEnc->sCmn.indices.signalType, psEnc->sCmn.indices.quantOffsetType,
+                        psEnc->sCmn.pulses, psEnc->sCmn.frame_length );
+
+                    nBits = ec_tell( psRangeEnc );
+                }
+
                 if( useCBR == 0 && iter == 0 && nBits <= maxBits ) {
                     break;
                 }
             }
 
             if( iter == maxIter ) {
                 if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
                     /* Restore output state from earlier iteration that did meet the bitrate budget */
@@ -218,17 +247,19 @@ opus_int silk_encode_frame_FLP(
                     psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
                 }
                 break;
             }
 
             if( nBits > maxBits ) {
                 if( found_lower == 0 && iter >= 2 ) {
                     /* Adjust the quantizer's rate/distortion tradeoff and discard previous "upper" results */
-                    sEncCtrl.Lambda *= 1.5f;
+                    sEncCtrl.Lambda = silk_max_float(sEncCtrl.Lambda*1.5f, 1.5f);
+                    /* Reducing dithering can help us hit the target. */
+                    psEnc->sCmn.indices.quantOffsetType = 0;
                     found_upper = 0;
                     gainsID_upper = -1;
                 } else {
                     found_upper = 1;
                     nBits_upper = nBits;
                     gainMult_upper = gainMult_Q8;
                     gainsID_upper = gainsID;
                 }
@@ -245,39 +276,64 @@ opus_int silk_encode_frame_FLP(
                     silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
                     LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
                 }
             } else {
                 /* Within 5 bits of budget: close enough */
                 break;
             }
 
+            if ( !found_lower && nBits > maxBits ) {
+                int j;
+                for ( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
+                    int sum=0;
+                    for ( j = i*psEnc->sCmn.subfr_length; j < (i+1)*psEnc->sCmn.subfr_length; j++ ) {
+                        sum += abs( psEnc->sCmn.pulses[j] );
+                    }
+                    if ( iter == 0 || (sum < best_sum[i] && !gain_lock[i]) ) {
+                        best_sum[i] = sum;
+                        best_gain_mult[i] = gainMult_Q8;
+                    } else {
+                        gain_lock[i] = 1;
+                    }
+                }
+            }
             if( ( found_lower & found_upper ) == 0 ) {
                 /* Adjust gain according to high-rate rate/distortion curve */
-                opus_int32 gain_factor_Q16;
-                gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
-                gain_factor_Q16 = silk_min_32( gain_factor_Q16, SILK_FIX_CONST( 2, 16 ) );
                 if( nBits > maxBits ) {
-                    gain_factor_Q16 = silk_max_32( gain_factor_Q16, SILK_FIX_CONST( 1.3, 16 ) );
+                    if (gainMult_Q8 < 16384) {
+                        gainMult_Q8 *= 2;
+                    } else {
+                        gainMult_Q8 = 32767;
+                    }
+                } else {
+                    opus_int32 gain_factor_Q16;
+                    gain_factor_Q16 = silk_log2lin( silk_LSHIFT( nBits - maxBits, 7 ) / psEnc->sCmn.frame_length + SILK_FIX_CONST( 16, 7 ) );
+                    gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
                 }
-                gainMult_Q8 = silk_SMULWB( gain_factor_Q16, gainMult_Q8 );
             } else {
                 /* Adjust gain by interpolating */
                 gainMult_Q8 = gainMult_lower + ( ( gainMult_upper - gainMult_lower ) * ( maxBits - nBits_lower ) ) / ( nBits_upper - nBits_lower );
                 /* New gain multplier must be between 25% and 75% of old range (note that gainMult_upper < gainMult_lower) */
                 if( gainMult_Q8 > silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 ) ) {
                     gainMult_Q8 = silk_ADD_RSHIFT32( gainMult_lower, gainMult_upper - gainMult_lower, 2 );
                 } else
                 if( gainMult_Q8 < silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 ) ) {
                     gainMult_Q8 = silk_SUB_RSHIFT32( gainMult_upper, gainMult_upper - gainMult_lower, 2 );
                 }
             }
 
             for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
-                pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], gainMult_Q8 ), 8 );
+                opus_int16 tmp;
+                if ( gain_lock[i] ) {
+                    tmp = best_gain_mult[i];
+                } else {
+                    tmp = gainMult_Q8;
+                }
+                pGains_Q16[ i ] = silk_LSHIFT_SAT32( silk_SMULWB( sEncCtrl.GainsUnq_Q16[ i ], tmp ), 8 );
             }
 
             /* Quantize gains */
             psEnc->sShape.LastGainIndex = sEncCtrl.lastGainIndexPrev;
             silk_gains_quant( psEnc->sCmn.indices.GainsIndices, pGains_Q16,
                   &psEnc->sShape.LastGainIndex, condCoding == CODE_CONDITIONALLY, psEnc->sCmn.nb_subfr );
 
             /* Unique identifier of gains vector */
--- a/media/libopus/silk/float/energy_FLP.c
+++ b/media/libopus/silk/float/energy_FLP.c
@@ -32,23 +32,22 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "SigProc_FLP.h"
 
 /* sum of squares of a silk_float array, with result as double */
 double silk_energy_FLP(
     const silk_float    *data,
     opus_int            dataSize
 )
 {
-    opus_int  i, dataSize4;
+    opus_int i;
     double   result;
 
     /* 4x unrolled loop */
     result = 0.0;
-    dataSize4 = dataSize & 0xFFFC;
-    for( i = 0; i < dataSize4; i += 4 ) {
+    for( i = 0; i < dataSize - 3; i += 4 ) {
         result += data[ i + 0 ] * (double)data[ i + 0 ] +
                   data[ i + 1 ] * (double)data[ i + 1 ] +
                   data[ i + 2 ] * (double)data[ i + 2 ] +
                   data[ i + 3 ] * (double)data[ i + 3 ];
     }
 
     /* add any remaining products */
     for( ; i < dataSize; i++ ) {
--- a/media/libopus/silk/float/find_LPC_FLP.c
+++ b/media/libopus/silk/float/find_LPC_FLP.c
@@ -68,17 +68,17 @@ void silk_find_LPC_FLP(
 
         /* Search over interpolation indices to find the one with lowest residual energy */
         res_nrg_2nd = silk_float_MAX;
         for( k = 3; k >= 0; k-- ) {
             /* Interpolate NLSFs for first half */
             silk_interpolate( NLSF0_Q15, psEncC->prev_NLSFq_Q15, NLSF_Q15, k, psEncC->predictLPCOrder );
 
             /* Convert to LPC for residual energy evaluation */
-            silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder );
+            silk_NLSF2A_FLP( a_tmp, NLSF0_Q15, psEncC->predictLPCOrder, psEncC->arch );
 
             /* Calculate residual energy with LSF interpolation */
             silk_LPC_analysis_filter_FLP( LPC_res, a_tmp, x, 2 * subfr_length, psEncC->predictLPCOrder );
             res_nrg_interp = (silk_float)(
                 silk_energy_FLP( LPC_res + psEncC->predictLPCOrder,                subfr_length - psEncC->predictLPCOrder ) +
                 silk_energy_FLP( LPC_res + psEncC->predictLPCOrder + subfr_length, subfr_length - psEncC->predictLPCOrder ) );
 
             /* Determine whether current interpolated NLSFs are best so far */
--- a/media/libopus/silk/float/find_LTP_FLP.c
+++ b/media/libopus/silk/float/find_LTP_FLP.c
@@ -28,105 +28,37 @@ POSSIBILITY OF SUCH DAMAGE.
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "main_FLP.h"
 #include "tuning_parameters.h"
 
 void silk_find_LTP_FLP(
-    silk_float                      b[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    LTP coefs                                   */
-    silk_float                      WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization       */
-    silk_float                      *LTPredCodGain,                     /* O    LTP coding gain                             */
-    const silk_float                r_lpc[],                            /* I    LPC residual                                */
-    const opus_int                  lag[  MAX_NB_SUBFR ],               /* I    LTP lags                                    */
-    const silk_float                Wght[ MAX_NB_SUBFR ],               /* I    Weights                                     */
+    silk_float                      XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization         */
+    silk_float                      xX[ MAX_NB_SUBFR * LTP_ORDER ],     /* O    Weight for LTP quantization                 */
+    const silk_float                r_ptr[],                            /* I    LPC residual                                */
+    const opus_int                  lag[ MAX_NB_SUBFR ],                /* I    LTP lags                                    */
     const opus_int                  subfr_length,                       /* I    Subframe length                             */
-    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
-    const opus_int                  mem_offset                          /* I    Number of samples in LTP memory             */
+    const opus_int                  nb_subfr                            /* I    number of subframes                         */
 )
 {
-    opus_int   i, k;
-    silk_float *b_ptr, temp, *WLTP_ptr;
-    silk_float LPC_res_nrg, LPC_LTP_res_nrg;
-    silk_float d[ MAX_NB_SUBFR ], m, g, delta_b[ LTP_ORDER ];
-    silk_float w[ MAX_NB_SUBFR ], nrg[ MAX_NB_SUBFR ], regu;
-    silk_float Rr[ LTP_ORDER ], rr[ MAX_NB_SUBFR ];
-    const silk_float *r_ptr, *lag_ptr;
+    opus_int   k;
+    silk_float *xX_ptr, *XX_ptr;
+    const silk_float *lag_ptr;
+    silk_float xx, temp;
 
-    b_ptr    = b;
-    WLTP_ptr = WLTP;
-    r_ptr    = &r_lpc[ mem_offset ];
+    xX_ptr = xX;
+    XX_ptr = XX;
     for( k = 0; k < nb_subfr; k++ ) {
         lag_ptr = r_ptr - ( lag[ k ] + LTP_ORDER / 2 );
-
-        silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, WLTP_ptr );
-        silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, Rr );
-
-        rr[ k ] = ( silk_float )silk_energy_FLP( r_ptr, subfr_length );
-        regu = 1.0f + rr[ k ] +
-            matrix_ptr( WLTP_ptr, 0, 0, LTP_ORDER ) +
-            matrix_ptr( WLTP_ptr, LTP_ORDER-1, LTP_ORDER-1, LTP_ORDER );
-        regu *= LTP_DAMPING / 3;
-        silk_regularize_correlations_FLP( WLTP_ptr, &rr[ k ], regu, LTP_ORDER );
-        silk_solve_LDL_FLP( WLTP_ptr, LTP_ORDER, Rr, b_ptr );
-
-        /* Calculate residual energy */
-        nrg[ k ] = silk_residual_energy_covar_FLP( b_ptr, WLTP_ptr, Rr, rr[ k ], LTP_ORDER );
-
-        temp = Wght[ k ] / ( nrg[ k ] * Wght[ k ] + 0.01f * subfr_length );
-        silk_scale_vector_FLP( WLTP_ptr, temp, LTP_ORDER * LTP_ORDER );
-        w[ k ] = matrix_ptr( WLTP_ptr, LTP_ORDER / 2, LTP_ORDER / 2, LTP_ORDER );
-
-        r_ptr    += subfr_length;
-        b_ptr    += LTP_ORDER;
-        WLTP_ptr += LTP_ORDER * LTP_ORDER;
-    }
-
-    /* Compute LTP coding gain */
-    if( LTPredCodGain != NULL ) {
-        LPC_LTP_res_nrg = 1e-6f;
-        LPC_res_nrg     = 0.0f;
-        for( k = 0; k < nb_subfr; k++ ) {
-            LPC_res_nrg     += rr[  k ] * Wght[ k ];
-            LPC_LTP_res_nrg += nrg[ k ] * Wght[ k ];
-        }
+        silk_corrMatrix_FLP( lag_ptr, subfr_length, LTP_ORDER, XX_ptr );
+        silk_corrVector_FLP( lag_ptr, r_ptr, subfr_length, LTP_ORDER, xX_ptr );
+        xx = ( silk_float )silk_energy_FLP( r_ptr, subfr_length + LTP_ORDER );
+        temp = 1.0f / silk_max( xx, LTP_CORR_INV_MAX * 0.5f * ( XX_ptr[ 0 ] + XX_ptr[ 24 ] ) + 1.0f );
+        silk_scale_vector_FLP( XX_ptr, temp, LTP_ORDER * LTP_ORDER );
+        silk_scale_vector_FLP( xX_ptr, temp, LTP_ORDER );
 
-        silk_assert( LPC_LTP_res_nrg > 0 );
-        *LTPredCodGain = 3.0f * silk_log2( LPC_res_nrg / LPC_LTP_res_nrg );
-    }
-
-    /* Smoothing */
-    /* d = sum( B, 1 ); */
-    b_ptr = b;
-    for( k = 0; k < nb_subfr; k++ ) {
-        d[ k ] = 0;
-        for( i = 0; i < LTP_ORDER; i++ ) {
-            d[ k ] += b_ptr[ i ];
-        }
-        b_ptr += LTP_ORDER;
-    }
-    /* m = ( w * d' ) / ( sum( w ) + 1e-3 ); */
-    temp = 1e-3f;
-    for( k = 0; k < nb_subfr; k++ ) {
-        temp += w[ k ];
-    }
-    m = 0;
-    for( k = 0; k < nb_subfr; k++ ) {
-        m += d[ k ] * w[ k ];
-    }
-    m = m / temp;
-
-    b_ptr = b;
-    for( k = 0; k < nb_subfr; k++ ) {
-        g = LTP_SMOOTHING / ( LTP_SMOOTHING + w[ k ] ) * ( m - d[ k ] );
-        temp = 0;
-        for( i = 0; i < LTP_ORDER; i++ ) {
-            delta_b[ i ] = silk_max_float( b_ptr[ i ], 0.1f );
-            temp += delta_b[ i ];
-        }
-        temp = g / temp;
-        for( i = 0; i < LTP_ORDER; i++ ) {
-            b_ptr[ i ] = b_ptr[ i ] + delta_b[ i ] * temp;
-        }
-        b_ptr += LTP_ORDER;
+        r_ptr  += subfr_length;
+        XX_ptr += LTP_ORDER * LTP_ORDER;
+        xX_ptr += LTP_ORDER;
     }
 }
--- a/media/libopus/silk/float/find_pred_coefs_FLP.c
+++ b/media/libopus/silk/float/find_pred_coefs_FLP.c
@@ -36,44 +36,42 @@ void silk_find_pred_coefs_FLP(
     silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
     silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
     const silk_float                res_pitch[],                        /* I    Residual from pitch analysis                */
     const silk_float                x[],                                /* I    Speech signal                               */
     opus_int                        condCoding                          /* I    The type of conditional coding to use       */
 )
 {
     opus_int         i;
-    silk_float       WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
-    silk_float       invGains[ MAX_NB_SUBFR ], Wght[ MAX_NB_SUBFR ];
+    silk_float       XXLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+    silk_float       xXLTP[ MAX_NB_SUBFR * LTP_ORDER ];
+    silk_float       invGains[ MAX_NB_SUBFR ];
     opus_int16       NLSF_Q15[ MAX_LPC_ORDER ];
     const silk_float *x_ptr;
     silk_float       *x_pre_ptr, LPC_in_pre[ MAX_NB_SUBFR * MAX_LPC_ORDER + MAX_FRAME_LENGTH ];
     silk_float       minInvGain;
 
     /* Weighting for weighted least squares */
     for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
         silk_assert( psEncCtrl->Gains[ i ] > 0.0f );
         invGains[ i ] = 1.0f / psEncCtrl->Gains[ i ];
-        Wght[ i ]     = invGains[ i ] * invGains[ i ];
     }
 
     if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
         /**********/
         /* VOICED */
         /**********/
         silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
 
         /* LTP analysis */
-        silk_find_LTP_FLP( psEncCtrl->LTPCoef, WLTP, &psEncCtrl->LTPredCodGain, res_pitch,
-            psEncCtrl->pitchL, Wght, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.ltp_mem_length );
+        silk_find_LTP_FLP( XXLTP, xXLTP, res_pitch, psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );
 
         /* Quantize LTP gain parameters */
         silk_quant_LTP_gains_FLP( psEncCtrl->LTPCoef, psEnc->sCmn.indices.LTPIndex, &psEnc->sCmn.indices.PERIndex,
-            &psEnc->sCmn.sum_log_gain_Q7, WLTP, psEnc->sCmn.mu_LTP_Q9, psEnc->sCmn.LTPQuantLowComplexity, psEnc->sCmn.nb_subfr,
-            psEnc->sCmn.arch );
+            &psEnc->sCmn.sum_log_gain_Q7, &psEncCtrl->LTPredCodGain, XXLTP, xXLTP, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.arch );
 
         /* Control LTP scaling */
         silk_LTP_scale_ctrl_FLP( psEnc, psEncCtrl, condCoding );
 
         /* Create LTP residual */
         silk_LTP_analysis_filter_FLP( LPC_in_pre, x - psEnc->sCmn.predictLPCOrder, psEncCtrl->LTPCoef,
             psEncCtrl->pitchL, invGains, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr, psEnc->sCmn.predictLPCOrder );
     } else {
--- a/media/libopus/silk/float/inner_product_FLP.c
+++ b/media/libopus/silk/float/inner_product_FLP.c
@@ -33,23 +33,22 @@ POSSIBILITY OF SUCH DAMAGE.
 
 /* inner product of two silk_float arrays, with result as double */
 double silk_inner_product_FLP(
     const silk_float    *data1,
     const silk_float    *data2,
     opus_int            dataSize
 )
 {
-    opus_int  i, dataSize4;
+    opus_int i;
     double   result;
 
     /* 4x unrolled loop */
     result = 0.0;
-    dataSize4 = dataSize & 0xFFFC;
-    for( i = 0; i < dataSize4; i += 4 ) {
+    for( i = 0; i < dataSize - 3; i += 4 ) {
         result += data1[ i + 0 ] * (double)data2[ i + 0 ] +
                   data1[ i + 1 ] * (double)data2[ i + 1 ] +
                   data1[ i + 2 ] * (double)data2[ i + 2 ] +
                   data1[ i + 3 ] * (double)data2[ i + 3 ];
     }
 
     /* add any remaining products */
     for( ; i < dataSize; i++ ) {
--- a/media/libopus/silk/float/k2a_FLP.c
+++ b/media/libopus/silk/float/k2a_FLP.c
@@ -34,20 +34,21 @@ POSSIBILITY OF SUCH DAMAGE.
 /* step up function, converts reflection coefficients to prediction coefficients */
 void silk_k2a_FLP(
     silk_float          *A,                 /* O     prediction coefficients [order]                            */
     const silk_float    *rc,                /* I     reflection coefficients [order]                            */
     opus_int32          order               /* I     prediction order                                           */
 )
 {
     opus_int   k, n;
-    silk_float Atmp[ SILK_MAX_ORDER_LPC ];
+    silk_float rck, tmp1, tmp2;
 
     for( k = 0; k < order; k++ ) {
-        for( n = 0; n < k; n++ ) {
-            Atmp[ n ] = A[ n ];
+        rck = rc[ k ];
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            tmp1 = A[ n ];
+            tmp2 = A[ k - n - 1 ];
+            A[ n ]         = tmp1 + tmp2 * rck;
+            A[ k - n - 1 ] = tmp2 + tmp1 * rck;
         }
-        for( n = 0; n < k; n++ ) {
-            A[ n ] += Atmp[ k - n - 1 ] * rc[ k ];
-        }
-        A[ k ] = -rc[ k ];
+        A[ k ] = -rck;
     }
 }
deleted file mode 100644
--- a/media/libopus/silk/float/levinsondurbin_FLP.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "SigProc_FLP.h"
-
-/* Solve the normal equations using the Levinson-Durbin recursion */
-silk_float silk_levinsondurbin_FLP(         /* O    prediction error energy                                     */
-    silk_float          A[],                /* O    prediction coefficients    [order]                          */
-    const silk_float    corr[],             /* I    input auto-correlations [order + 1]                         */
-    const opus_int      order               /* I    prediction order                                            */
-)
-{
-    opus_int   i, mHalf, m;
-    silk_float min_nrg, nrg, t, km, Atmp1, Atmp2;
-
-    min_nrg = 1e-12f * corr[ 0 ] + 1e-9f;
-    nrg = corr[ 0 ];
-    nrg = silk_max_float(min_nrg, nrg);
-    A[ 0 ] = corr[ 1 ] / nrg;
-    nrg -= A[ 0 ] * corr[ 1 ];
-    nrg = silk_max_float(min_nrg, nrg);
-
-    for( m = 1; m < order; m++ )
-    {
-        t = corr[ m + 1 ];
-        for( i = 0; i < m; i++ ) {
-            t -= A[ i ] * corr[ m - i ];
-        }
-
-        /* reflection coefficient */
-        km = t / nrg;
-
-        /* residual energy */
-        nrg -= km * t;
-        nrg = silk_max_float(min_nrg, nrg);
-
-        mHalf = m >> 1;
-        for( i = 0; i < mHalf; i++ ) {
-            Atmp1 = A[ i ];
-            Atmp2 = A[ m - i - 1 ];
-            A[ m - i - 1 ] -= km * Atmp1;
-            A[ i ]         -= km * Atmp2;
-        }
-        if( m & 1 ) {
-            A[ mHalf ]     -= km * A[ mHalf ];
-        }
-        A[ m ] = km;
-    }
-
-    /* return the residual energy */
-    return nrg;
-}
-
--- a/media/libopus/silk/float/main_FLP.h
+++ b/media/libopus/silk/float/main_FLP.h
@@ -74,32 +74,21 @@ opus_int silk_init_encoder(
     silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
     int                              arch                               /* I    Run-tim architecture                        */
 );
 
 /* Control the Silk encoder */
 opus_int silk_control_encoder(
     silk_encoder_state_FLP          *psEnc,                             /* I/O  Pointer to Silk encoder state FLP           */
     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
 );
 
-/****************/
-/* Prefiltering */
-/****************/
-void silk_prefilter_FLP(
-    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
-    const silk_encoder_control_FLP  *psEncCtrl,                         /* I    Encoder control FLP                         */
-    silk_float                      xw[],                               /* O    Weighted signal                             */
-    const silk_float                x[]                                 /* I    Speech signal                               */
-);
-
 /**************************/
 /* Noise shaping analysis */
 /**************************/
 /* Compute noise shaping coefficients and initial gain values */
 void silk_noise_shape_analysis_FLP(
     silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
     silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
     const silk_float                *pitch_res,                         /* I    LPC residual from pitch analysis            */
@@ -148,25 +137,22 @@ void silk_find_LPC_FLP(
     silk_encoder_state              *psEncC,                            /* I/O  Encoder state                               */
     opus_int16                      NLSF_Q15[],                         /* O    NLSFs                                       */
     const silk_float                x[],                                /* I    Input signal                                */
     const silk_float                minInvGain                          /* I    Prediction gain from LTP (dB)               */
 );
 
 /* LTP analysis */
 void silk_find_LTP_FLP(
-    silk_float                      b[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    LTP coefs                                   */
-    silk_float                      WLTP[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization       */
-    silk_float                      *LTPredCodGain,                     /* O    LTP coding gain                             */
-    const silk_float                r_lpc[],                            /* I    LPC residual                                */
+    silk_float                      XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* O    Weight for LTP quantization         */
+    silk_float                      xX[ MAX_NB_SUBFR * LTP_ORDER ],     /* O    Weight for LTP quantization                 */
+    const silk_float                r_ptr[],                            /* I    LPC residual                                */
     const opus_int                  lag[  MAX_NB_SUBFR ],               /* I    LTP lags                                    */
-    const silk_float                Wght[ MAX_NB_SUBFR ],               /* I    Weights                                     */
     const opus_int                  subfr_length,                       /* I    Subframe length                             */
-    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
-    const opus_int                  mem_offset                          /* I    Number of samples in LTP memory             */
+    const opus_int                  nb_subfr                            /* I    number of subframes                         */
 );
 
 void silk_LTP_analysis_filter_FLP(
     silk_float                      *LTP_res,                           /* O    LTP res MAX_NB_SUBFR*(pre_lgth+subfr_lngth) */
     const silk_float                *x,                                 /* I    Input signal, with preceding samples        */
     const silk_float                B[ LTP_ORDER * MAX_NB_SUBFR ],      /* I    LTP coefficients for each subframe          */
     const opus_int                  pitchL[   MAX_NB_SUBFR ],           /* I    Pitch lags                                  */
     const silk_float                invGains[ MAX_NB_SUBFR ],           /* I    Inverse quantization gains                  */
@@ -193,24 +179,25 @@ void silk_LPC_analysis_filter_FLP(
     const silk_float                PredCoef[],                         /* I    LPC coefficients                            */
     const silk_float                s[],                                /* I    Input signal                                */
     const opus_int                  length,                             /* I    Length of input signal                      */
     const opus_int                  Order                               /* I    LPC order                                   */
 );
 
 /* LTP tap quantizer */
 void silk_quant_LTP_gains_FLP(
-    silk_float                      B[ MAX_NB_SUBFR * LTP_ORDER ],      /* I/O  (Un-)quantized LTP gains                    */
+    silk_float                      B[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    Quantized LTP gains                         */
     opus_int8                       cbk_index[ MAX_NB_SUBFR ],          /* O    Codebook index                              */
     opus_int8                       *periodicity_index,                 /* O    Periodicity index                           */
     opus_int32                      *sum_log_gain_Q7,                   /* I/O  Cumulative max prediction gain  */
-    const silk_float                W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I    Error weights                        */
-    const opus_int                  mu_Q10,                             /* I    Mu value (R/D tradeoff)                     */
-    const opus_int                  lowComplexity,                      /* I    Flag for low complexity                     */
-    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
+    silk_float                      *pred_gain_dB,                      /* O    LTP prediction gain                         */
+    const silk_float                XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I    Correlation matrix                  */
+    const silk_float                xX[ MAX_NB_SUBFR * LTP_ORDER ],     /* I    Correlation vector                          */
+    const opus_int                  subfr_len,                          /* I    Number of samples per subframe              */
+    const opus_int                  nb_subfr,                           /* I    Number of subframes                         */
     int                             arch                                /* I    Run-time architecture                       */
 );
 
 /* Residual energy: nrg = wxx - 2 * wXx * c + c' * wXX * c */
 silk_float silk_residual_energy_covar_FLP(                              /* O    Weighted residual energy                    */
     const silk_float                *c,                                 /* I    Filter coefficients                         */
     silk_float                      *wXX,                               /* I/O  Weighted correlation matrix, reg. out       */
     const silk_float                *wXx,                               /* I    Weighted correlation vector                 */
@@ -240,32 +227,16 @@ void silk_corrMatrix_FLP(
 void silk_corrVector_FLP(
     const silk_float                *x,                                 /* I    x vector [L+order-1] used to create X       */
     const silk_float                *t,                                 /* I    Target vector [L]                           */
     const opus_int                  L,                                  /* I    Length of vecors                            */
     const opus_int                  Order,                              /* I    Max lag for correlation                     */
     silk_float                      *Xt                                 /* O    X'*t correlation vector [order]             */
 );
 
-/* Add noise to matrix diagonal */
-void silk_regularize_correlations_FLP(
-    silk_float                      *XX,                                /* I/O  Correlation matrices                        */
-    silk_float                      *xx,                                /* I/O  Correlation values                          */
-    const silk_float                noise,                              /* I    Noise energy to add                         */
-    const opus_int                  D                                   /* I    Dimension of XX                             */
-);
-
-/* Function to solve linear equation Ax = b, where A is an MxM symmetric matrix */
-void silk_solve_LDL_FLP(
-    silk_float                      *A,                                 /* I/O  Symmetric square matrix, out: reg.          */
-    const opus_int                  M,                                  /* I    Size of matrix                              */
-    const silk_float                *b,                                 /* I    Pointer to b vector                         */
-    silk_float                      *x                                  /* O    Pointer to x solution vector                */
-);
-
 /* Apply sine window to signal vector.  */
 /* Window types:                        */
 /*  1 -> sine window from 0 to pi/2     */
 /*  2 -> sine window from pi/2 to pi    */
 void silk_apply_sine_window_FLP(
     silk_float                      px_win[],                           /* O    Pointer to windowed signal                  */
     const silk_float                px[],                               /* I    Pointer to input signal                     */
     const opus_int                  win_type,                           /* I    Selects a window type                       */
@@ -280,17 +251,18 @@ void silk_A2NLSF_FLP(
     const silk_float                *pAR,                               /* I    LPC coefficients [ LPC_order ]              */
     const opus_int                  LPC_order                           /* I    LPC order                                   */
 );
 
 /* Convert NLSF parameters to AR prediction filter coefficients */
 void silk_NLSF2A_FLP(
     silk_float                      *pAR,                               /* O    LPC coefficients [ LPC_order ]              */
     const opus_int16                *NLSF_Q15,                          /* I    NLSF vector      [ LPC_order ]              */
-    const opus_int                  LPC_order                           /* I    LPC order                                   */
+    const opus_int                  LPC_order,                          /* I    LPC order                                   */
+    int                             arch                                /* I    Run-time architecture                       */
 );
 
 /* Limit, stabilize, and quantize NLSFs */
 void silk_process_NLSFs_FLP(
     silk_encoder_state              *psEncC,                            /* I/O  Encoder state                               */
     silk_float                      PredCoef[ 2 ][ MAX_LPC_ORDER ],     /* O    Prediction coefficients                     */
     opus_int16                      NLSF_Q15[      MAX_LPC_ORDER ],     /* I/O  Normalized LSFs (quant out) (0 - (2^15-1))  */
     const opus_int16                prev_NLSF_Q15[ MAX_LPC_ORDER ]      /* I    Previous Normalized LSFs (0 - (2^15-1))     */
--- a/media/libopus/silk/float/noise_shape_analysis_FLP.c
+++ b/media/libopus/silk/float/noise_shape_analysis_FLP.c
@@ -50,100 +50,120 @@ static OPUS_INLINE silk_float warped_gai
         gain = lambda * gain + coefs[ i ];
     }
     return (silk_float)( 1.0f / ( 1.0f - lambda * gain ) );
 }
 
 /* Convert warped filter coefficients to monic pseudo-warped coefficients and limit maximum     */
 /* amplitude of monic warped coefficients by using bandwidth expansion on the true coefficients */
 static OPUS_INLINE void warped_true2monic_coefs(
-    silk_float           *coefs_syn,
-    silk_float           *coefs_ana,
+    silk_float           *coefs,
     silk_float           lambda,
     silk_float           limit,
     opus_int             order
 ) {
     opus_int   i, iter, ind = 0;
-    silk_float tmp, maxabs, chirp, gain_syn, gain_ana;
+    silk_float tmp, maxabs, chirp, gain;
 
     /* Convert to monic coefficients */
     for( i = order - 1; i > 0; i-- ) {
-        coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
-        coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
+        coefs[ i - 1 ] -= lambda * coefs[ i ];
     }
-    gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
-    gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
+    gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
     for( i = 0; i < order; i++ ) {
-        coefs_syn[ i ] *= gain_syn;
-        coefs_ana[ i ] *= gain_ana;
+        coefs[ i ] *= gain;
     }
 
     /* Limit */
     for( iter = 0; iter < 10; iter++ ) {
         /* Find maximum absolute value */
         maxabs = -1.0f;
         for( i = 0; i < order; i++ ) {
-            tmp = silk_max( silk_abs_float( coefs_syn[ i ] ), silk_abs_float( coefs_ana[ i ] ) );
+            tmp = silk_abs_float( coefs[ i ] );
             if( tmp > maxabs ) {
                 maxabs = tmp;
                 ind = i;
             }
         }
         if( maxabs <= limit ) {
             /* Coefficients are within range - done */
             return;
         }
 
         /* Convert back to true warped coefficients */
         for( i = 1; i < order; i++ ) {
-            coefs_syn[ i - 1 ] += lambda * coefs_syn[ i ];
-            coefs_ana[ i - 1 ] += lambda * coefs_ana[ i ];
+            coefs[ i - 1 ] += lambda * coefs[ i ];
         }
-        gain_syn = 1.0f / gain_syn;
-        gain_ana = 1.0f / gain_ana;
+        gain = 1.0f / gain;
         for( i = 0; i < order; i++ ) {
-            coefs_syn[ i ] *= gain_syn;
-            coefs_ana[ i ] *= gain_ana;
+            coefs[ i ] *= gain;
         }
 
         /* Apply bandwidth expansion */
         chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
-        silk_bwexpander_FLP( coefs_syn, order, chirp );
-        silk_bwexpander_FLP( coefs_ana, order, chirp );
+        silk_bwexpander_FLP( coefs, order, chirp );
 
         /* Convert to monic warped coefficients */
         for( i = order - 1; i > 0; i-- ) {
-            coefs_syn[ i - 1 ] -= lambda * coefs_syn[ i ];
-            coefs_ana[ i - 1 ] -= lambda * coefs_ana[ i ];
+            coefs[ i - 1 ] -= lambda * coefs[ i ];
+        }
+        gain = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs[ 0 ] );
+        for( i = 0; i < order; i++ ) {
+            coefs[ i ] *= gain;
         }
-        gain_syn = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_syn[ 0 ] );
-        gain_ana = ( 1.0f - lambda * lambda ) / ( 1.0f + lambda * coefs_ana[ 0 ] );
+    }
+    silk_assert( 0 );
+}
+
+static OPUS_INLINE void limit_coefs(
+    silk_float           *coefs,
+    silk_float           limit,
+    opus_int             order
+) {
+    opus_int   i, iter, ind = 0;
+    silk_float tmp, maxabs, chirp;
+
+    for( iter = 0; iter < 10; iter++ ) {
+        /* Find maximum absolute value */
+        maxabs = -1.0f;
         for( i = 0; i < order; i++ ) {
-            coefs_syn[ i ] *= gain_syn;
-            coefs_ana[ i ] *= gain_ana;
+            tmp = silk_abs_float( coefs[ i ] );
+            if( tmp > maxabs ) {
+                maxabs = tmp;
+                ind = i;
+            }
         }
+        if( maxabs <= limit ) {
+            /* Coefficients are within range - done */
+            return;
+        }
+
+        /* Apply bandwidth expansion */
+        chirp = 0.99f - ( 0.8f + 0.1f * iter ) * ( maxabs - limit ) / ( maxabs * ( ind + 1 ) );
+        silk_bwexpander_FLP( coefs, order, chirp );
     }
     silk_assert( 0 );
 }
 
 /* Compute noise shaping coefficients and initial gain values */
 void silk_noise_shape_analysis_FLP(
     silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
     silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
     const silk_float                *pitch_res,                         /* I    LPC residual from pitch analysis            */
     const silk_float                *x                                  /* I    Input signal [frame_length + la_shape]      */
 )
 {
     silk_shape_state_FLP *psShapeSt = &psEnc->sShape;
-    opus_int     k, nSamples;
-    silk_float   SNR_adj_dB, HarmBoost, HarmShapeGain, Tilt;
-    silk_float   nrg, pre_nrg, log_energy, log_energy_prev, energy_variation;
-    silk_float   delta, BWExp1, BWExp2, gain_mult, gain_add, strength, b, warping;
+    opus_int     k, nSamples, nSegs;
+    silk_float   SNR_adj_dB, HarmShapeGain, Tilt;
+    silk_float   nrg, log_energy, log_energy_prev, energy_variation;
+    silk_float   BWExp, gain_mult, gain_add, strength, b, warping;
     silk_float   x_windowed[ SHAPE_LPC_WIN_MAX ];
     silk_float   auto_corr[ MAX_SHAPE_LPC_ORDER + 1 ];
+    silk_float   rc[ MAX_SHAPE_LPC_ORDER + 1 ];
     const silk_float *x_ptr, *pitch_res_ptr;
 
     /* Point to start of first LPC analysis block */
     x_ptr = x - psEnc->sCmn.la_shape;
 
     /****************/
     /* GAIN CONTROL */
     /****************/
@@ -171,63 +191,50 @@ void silk_noise_shape_analysis_FLP(
 
     /*************************/
     /* SPARSENESS PROCESSING */
     /*************************/
     /* Set quantizer offset */
     if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
         /* Initially set to 0; may be overruled in process_gains(..) */
         psEnc->sCmn.indices.quantOffsetType = 0;
-        psEncCtrl->sparseness = 0.0f;
     } else {
         /* Sparseness measure, based on relative fluctuations of energy per 2 milliseconds */
         nSamples = 2 * psEnc->sCmn.fs_kHz;
         energy_variation = 0.0f;
         log_energy_prev  = 0.0f;
         pitch_res_ptr = pitch_res;
-        for( k = 0; k < silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2; k++ ) {
+        nSegs = silk_SMULBB( SUB_FRAME_LENGTH_MS, psEnc->sCmn.nb_subfr ) / 2;
+        for( k = 0; k < nSegs; k++ ) {
             nrg = ( silk_float )nSamples + ( silk_float )silk_energy_FLP( pitch_res_ptr, nSamples );
             log_energy = silk_log2( nrg );
             if( k > 0 ) {
                 energy_variation += silk_abs_float( log_energy - log_energy_prev );
             }
             log_energy_prev = log_energy;
             pitch_res_ptr += nSamples;
         }
-        psEncCtrl->sparseness = silk_sigmoid( 0.4f * ( energy_variation - 5.0f ) );
 
         /* Set quantization offset depending on sparseness measure */
-        if( psEncCtrl->sparseness > SPARSENESS_THRESHOLD_QNT_OFFSET ) {
+        if( energy_variation > ENERGY_VARIATION_THRESHOLD_QNT_OFFSET * (nSegs-1) ) {
             psEnc->sCmn.indices.quantOffsetType = 0;
         } else {
             psEnc->sCmn.indices.quantOffsetType = 1;
         }
-
-        /* Increase coding SNR for sparse signals */
-        SNR_adj_dB += SPARSE_SNR_INCR_dB * ( psEncCtrl->sparseness - 0.5f );
     }
 
     /*******************************/
     /* Control bandwidth expansion */
     /*******************************/
     /* More BWE for signals with high prediction gain */
     strength = FIND_PITCH_WHITE_NOISE_FRACTION * psEncCtrl->predGain;           /* between 0.0 and 1.0 */
-    BWExp1 = BWExp2 = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
-    delta  = LOW_RATE_BANDWIDTH_EXPANSION_DELTA * ( 1.0f - 0.75f * psEncCtrl->coding_quality );
-    BWExp1 -= delta;
-    BWExp2 += delta;
-    /* BWExp1 will be applied after BWExp2, so make it relative */
-    BWExp1 /= BWExp2;
+    BWExp = BANDWIDTH_EXPANSION / ( 1.0f + strength * strength );
 
-    if( psEnc->sCmn.warping_Q16 > 0 ) {
-        /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
-        warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
-    } else {
-        warping = 0.0f;
-    }
+    /* Slightly more warping in analysis will move quantization noise up in frequency, where it's better masked */
+    warping = (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f + 0.01f * psEncCtrl->coding_quality;
 
     /********************************************/
     /* Compute noise shaping AR coefs and gains */
     /********************************************/
     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
         /* Apply window: sine slope followed by flat part followed by cosine slope */
         opus_int shift, slope_part, flat_part;
         flat_part = psEnc->sCmn.fs_kHz * 3;
@@ -247,65 +254,51 @@ void silk_noise_shape_analysis_FLP(
             silk_warped_autocorrelation_FLP( auto_corr, x_windowed, warping,
                 psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder );
         } else {
             /* Calculate regular auto correlation */
             silk_autocorrelation_FLP( auto_corr, x_windowed, psEnc->sCmn.shapeWinLength, psEnc->sCmn.shapingLPCOrder + 1 );
         }
 
         /* Add white noise, as a fraction of energy */
-        auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION;
+        auto_corr[ 0 ] += auto_corr[ 0 ] * SHAPE_WHITE_NOISE_FRACTION + 1.0f;
 
         /* Convert correlations to prediction coefficients, and compute residual energy */
-        nrg = silk_levinsondurbin_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], auto_corr, psEnc->sCmn.shapingLPCOrder );
+        nrg = silk_schur_FLP( rc, auto_corr, psEnc->sCmn.shapingLPCOrder );
+        silk_k2a_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], rc, psEnc->sCmn.shapingLPCOrder );
         psEncCtrl->Gains[ k ] = ( silk_float )sqrt( nrg );
 
         if( psEnc->sCmn.warping_Q16 > 0 ) {
             /* Adjust gain for warping */
-            psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
+            psEncCtrl->Gains[ k ] *= warped_gain( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, psEnc->sCmn.shapingLPCOrder );
         }
 
         /* Bandwidth expansion for synthesis filter shaping */
-        silk_bwexpander_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp2 );
-
-        /* Compute noise shaping filter coefficients */
-        silk_memcpy(
-            &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
-            &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ],
-            psEnc->sCmn.shapingLPCOrder * sizeof( silk_float ) );
+        silk_bwexpander_FLP( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp );
 
-        /* Bandwidth expansion for analysis filter shaping */
-        silk_bwexpander_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder, BWExp1 );
-
-        /* Ratio of prediction gains, in energy domain */
-        pre_nrg = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
-        nrg     = silk_LPC_inverse_pred_gain_FLP( &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ], psEnc->sCmn.shapingLPCOrder );
-        psEncCtrl->GainsPre[ k ] = 1.0f - 0.7f * ( 1.0f - pre_nrg / nrg );
-
-        /* Convert to monic warped prediction coefficients and limit absolute values */
-        warped_true2monic_coefs( &psEncCtrl->AR2[ k * MAX_SHAPE_LPC_ORDER ], &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ],
-            warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
+        if( psEnc->sCmn.warping_Q16 > 0 ) {
+            /* Convert to monic warped prediction coefficients and limit absolute values */
+            warped_true2monic_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], warping, 3.999f, psEnc->sCmn.shapingLPCOrder );
+        } else {
+            /* Limit absolute values */
+            limit_coefs( &psEncCtrl->AR[ k * MAX_SHAPE_LPC_ORDER ], 3.999f, psEnc->sCmn.shapingLPCOrder );
+        }
     }
 
     /*****************/
     /* Gain tweaking */
     /*****************/
     /* Increase gains during low speech activity */
     gain_mult = (silk_float)pow( 2.0f, -0.16f * SNR_adj_dB );
     gain_add  = (silk_float)pow( 2.0f,  0.16f * MIN_QGAIN_DB );
     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
         psEncCtrl->Gains[ k ] *= gain_mult;
         psEncCtrl->Gains[ k ] += gain_add;
     }
 
-    gain_mult = 1.0f + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT;
-    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
-        psEncCtrl->GainsPre[ k ] *= gain_mult;
-    }
-
     /************************************************/
     /* Control low-frequency shaping and noise tilt */
     /************************************************/
     /* Less low frequency shaping for noisy inputs */
     strength = LOW_FREQ_SHAPING * ( 1.0f + LOW_QUALITY_LOW_FREQ_SHAPING_DECR * ( psEnc->sCmn.input_quality_bands_Q15[ 0 ] * ( 1.0f / 32768.0f ) - 1.0f ) );
     strength *= psEnc->sCmn.speech_activity_Q8 * ( 1.0f /  256.0f );
     if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
         /* Reduce low frequencies quantization noise for periodic signals, depending on pitch lag */
@@ -326,22 +319,16 @@ void silk_noise_shape_analysis_FLP(
             psEncCtrl->LF_AR_shp[ k ] = psEncCtrl->LF_AR_shp[ 0 ];
         }
         Tilt = -HP_NOISE_COEF;
     }
 
     /****************************/
     /* HARMONIC SHAPING CONTROL */
     /****************************/
-    /* Control boosting of harmonic frequencies */
-    HarmBoost = LOW_RATE_HARMONIC_BOOST * ( 1.0f - psEncCtrl->coding_quality ) * psEnc->LTPCorr;
-
-    /* More harmonic boost for noisy input signals */
-    HarmBoost += LOW_INPUT_QUALITY_HARMONIC_BOOST * ( 1.0f - psEncCtrl->input_quality );
-
     if( USE_HARM_SHAPING && psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
         /* Harmonic noise shaping */
         HarmShapeGain = HARMONIC_SHAPING;
 
         /* More harmonic noise shaping for high bitrates or noisy input */
         HarmShapeGain += HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING *
             ( 1.0f - ( 1.0f - psEncCtrl->coding_quality ) * psEncCtrl->input_quality );
 
@@ -350,16 +337,14 @@ void silk_noise_shape_analysis_FLP(
     } else {
         HarmShapeGain = 0.0f;
     }
 
     /*************************/
     /* Smooth over subframes */
     /*************************/
     for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
-        psShapeSt->HarmBoost_smth     += SUBFR_SMTH_COEF * ( HarmBoost - psShapeSt->HarmBoost_smth );
-        psEncCtrl->HarmBoost[ k ]      = psShapeSt->HarmBoost_smth;
         psShapeSt->HarmShapeGain_smth += SUBFR_SMTH_COEF * ( HarmShapeGain - psShapeSt->HarmShapeGain_smth );
         psEncCtrl->HarmShapeGain[ k ]  = psShapeSt->HarmShapeGain_smth;
         psShapeSt->Tilt_smth          += SUBFR_SMTH_COEF * ( Tilt - psShapeSt->Tilt_smth );
         psEncCtrl->Tilt[ k ]           = psShapeSt->Tilt_smth;
     }
 }
--- a/media/libopus/silk/float/pitch_analysis_core_FLP.c
+++ b/media/libopus/silk/float/pitch_analysis_core_FLP.c
@@ -154,17 +154,17 @@ opus_int silk_pitch_analysis_core_FLP(  
 
     /* Decimate again to 4 kHz */
     silk_memset( filt_state, 0, 2 * sizeof( opus_int32 ) );
     silk_resampler_down2( filt_state, frame_4_FIX, frame_8_FIX, frame_length_8kHz );
     silk_short2float_array( frame_4kHz, frame_4_FIX, frame_length_4kHz );
 
     /* Low-pass filter */
     for( i = frame_length_4kHz - 1; i > 0; i-- ) {
-        frame_4kHz[ i ] += frame_4kHz[ i - 1 ];
+        frame_4kHz[ i ] = silk_ADD_SAT16( frame_4kHz[ i ], frame_4kHz[ i - 1 ] );
     }
 
     /******************************************************************************
     * FIRST STAGE, operating in 4 khz
     ******************************************************************************/
     silk_memset(C, 0, sizeof(silk_float) * nb_subfr * ((PE_MAX_LAG >> 1) + 5));
     target_ptr = &frame_4kHz[ silk_LSHIFT( sf_length_4kHz, 2 ) ];
     for( k = 0; k < nb_subfr >> 1; k++ ) {
deleted file mode 100644
--- a/media/libopus/silk/float/prefilter_FLP.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "main_FLP.h"
-#include "tuning_parameters.h"
-
-/*
-* Prefilter for finding Quantizer input signal
-*/
-static OPUS_INLINE void silk_prefilt_FLP(
-    silk_prefilter_state_FLP    *P,                 /* I/O state */
-    silk_float                  st_res[],           /* I */
-    silk_float                  xw[],               /* O */
-    silk_float                  *HarmShapeFIR,      /* I */
-    silk_float                  Tilt,               /* I */
-    silk_float                  LF_MA_shp,          /* I */
-    silk_float                  LF_AR_shp,          /* I */
-    opus_int                    lag,                /* I */
-    opus_int                    length              /* I */
-);
-
-static void silk_warped_LPC_analysis_filter_FLP(
-          silk_float                 state[],            /* I/O  State [order + 1]                       */
-          silk_float                 res[],              /* O    Residual signal [length]                */
-    const silk_float                 coef[],             /* I    Coefficients [order]                    */
-    const silk_float                 input[],            /* I    Input signal [length]                   */
-    const silk_float                 lambda,             /* I    Warping factor                          */
-    const opus_int                   length,             /* I    Length of input signal                  */
-    const opus_int                   order               /* I    Filter order (even)                     */
-)
-{
-    opus_int     n, i;
-    silk_float   acc, tmp1, tmp2;
-
-    /* Order must be even */
-    silk_assert( ( order & 1 ) == 0 );
-
-    for( n = 0; n < length; n++ ) {
-        /* Output of lowpass section */
-        tmp2 = state[ 0 ] + lambda * state[ 1 ];
-        state[ 0 ] = input[ n ];
-        /* Output of allpass section */
-        tmp1 = state[ 1 ] + lambda * ( state[ 2 ] - tmp2 );
-        state[ 1 ] = tmp2;
-        acc = coef[ 0 ] * tmp2;
-        /* Loop over allpass sections */
-        for( i = 2; i < order; i += 2 ) {
-            /* Output of allpass section */
-            tmp2 = state[ i ] + lambda * ( state[ i + 1 ] - tmp1 );
-            state[ i ] = tmp1;
-            acc += coef[ i - 1 ] * tmp1;
-            /* Output of allpass section */
-            tmp1 = state[ i + 1 ] + lambda * ( state[ i + 2 ] - tmp2 );
-            state[ i + 1 ] = tmp2;
-            acc += coef[ i ] * tmp2;
-        }
-        state[ order ] = tmp1;
-        acc += coef[ order - 1 ] * tmp1;
-        res[ n ] = input[ n ] - acc;
-    }
-}
-
-/*
-* silk_prefilter. Main prefilter function
-*/
-void silk_prefilter_FLP(
-    silk_encoder_state_FLP          *psEnc,                             /* I/O  Encoder state FLP                           */
-    const silk_encoder_control_FLP  *psEncCtrl,                         /* I    Encoder control FLP                         */
-    silk_float                      xw[],                               /* O    Weighted signal                             */
-    const silk_float                x[]                                 /* I    Speech signal                               */
-)
-{
-    silk_prefilter_state_FLP *P = &psEnc->sPrefilt;
-    opus_int   j, k, lag;
-    silk_float HarmShapeGain, Tilt, LF_MA_shp, LF_AR_shp;
-    silk_float B[ 2 ];
-    const silk_float *AR1_shp;
-    const silk_float *px;
-    silk_float *pxw;
-    silk_float HarmShapeFIR[ 3 ];
-    silk_float st_res[ MAX_SUB_FRAME_LENGTH + MAX_LPC_ORDER ];
-
-    /* Set up pointers */
-    px  = x;
-    pxw = xw;
-    lag = P->lagPrev;
-    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
-        /* Update Variables that change per sub frame */
-        if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
-            lag = psEncCtrl->pitchL[ k ];
-        }
-
-        /* Noise shape parameters */
-        HarmShapeGain = psEncCtrl->HarmShapeGain[ k ] * ( 1.0f - psEncCtrl->HarmBoost[ k ] );
-        HarmShapeFIR[ 0 ] = 0.25f               * HarmShapeGain;
-        HarmShapeFIR[ 1 ] = 32767.0f / 65536.0f * HarmShapeGain;
-        HarmShapeFIR[ 2 ] = 0.25f               * HarmShapeGain;
-        Tilt      =  psEncCtrl->Tilt[ k ];
-        LF_MA_shp =  psEncCtrl->LF_MA_shp[ k ];
-        LF_AR_shp =  psEncCtrl->LF_AR_shp[ k ];
-        AR1_shp   = &psEncCtrl->AR1[ k * MAX_SHAPE_LPC_ORDER ];
-
-        /* Short term FIR filtering */
-        silk_warped_LPC_analysis_filter_FLP( P->sAR_shp, st_res, AR1_shp, px,
-            (silk_float)psEnc->sCmn.warping_Q16 / 65536.0f, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder );
-
-        /* Reduce (mainly) low frequencies during harmonic emphasis */
-        B[ 0 ] =  psEncCtrl->GainsPre[ k ];
-        B[ 1 ] = -psEncCtrl->GainsPre[ k ] *
-            ( psEncCtrl->HarmBoost[ k ] * HarmShapeGain + INPUT_TILT + psEncCtrl->coding_quality * HIGH_RATE_INPUT_TILT );
-        pxw[ 0 ] = B[ 0 ] * st_res[ 0 ] + B[ 1 ] * P->sHarmHP;
-        for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
-            pxw[ j ] = B[ 0 ] * st_res[ j ] + B[ 1 ] * st_res[ j - 1 ];
-        }
-        P->sHarmHP = st_res[ psEnc->sCmn.subfr_length - 1 ];
-
-        silk_prefilt_FLP( P, pxw, pxw, HarmShapeFIR, Tilt, LF_MA_shp, LF_AR_shp, lag, psEnc->sCmn.subfr_length );
-
-        px  += psEnc->sCmn.subfr_length;
-        pxw += psEnc->sCmn.subfr_length;
-    }
-    P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
-}
-
-/*
-* Prefilter for finding Quantizer input signal
-*/
-static OPUS_INLINE void silk_prefilt_FLP(
-    silk_prefilter_state_FLP    *P,                 /* I/O state */
-    silk_float                  st_res[],           /* I */
-    silk_float                  xw[],               /* O */
-    silk_float                  *HarmShapeFIR,      /* I */
-    silk_float                  Tilt,               /* I */
-    silk_float                  LF_MA_shp,          /* I */
-    silk_float                  LF_AR_shp,          /* I */
-    opus_int                    lag,                /* I */
-    opus_int                    length              /* I */
-)
-{
-    opus_int   i;
-    opus_int   idx, LTP_shp_buf_idx;
-    silk_float n_Tilt, n_LF, n_LTP;
-    silk_float sLF_AR_shp, sLF_MA_shp;
-    silk_float *LTP_shp_buf;
-
-    /* To speed up use temp variables instead of using the struct */
-    LTP_shp_buf     = P->sLTP_shp;
-    LTP_shp_buf_idx = P->sLTP_shp_buf_idx;
-    sLF_AR_shp      = P->sLF_AR_shp;
-    sLF_MA_shp      = P->sLF_MA_shp;
-
-    for( i = 0; i < length; i++ ) {
-        if( lag > 0 ) {
-            silk_assert( HARM_SHAPE_FIR_TAPS == 3 );
-            idx = lag + LTP_shp_buf_idx;
-            n_LTP  = LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 - 1) & LTP_MASK ] * HarmShapeFIR[ 0 ];
-            n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2    ) & LTP_MASK ] * HarmShapeFIR[ 1 ];
-            n_LTP += LTP_shp_buf[ ( idx - HARM_SHAPE_FIR_TAPS / 2 + 1) & LTP_MASK ] * HarmShapeFIR[ 2 ];
-        } else {
-            n_LTP = 0;
-        }
-
-        n_Tilt = sLF_AR_shp * Tilt;
-        n_LF   = sLF_AR_shp * LF_AR_shp + sLF_MA_shp * LF_MA_shp;
-
-        sLF_AR_shp = st_res[ i ] - n_Tilt;
-        sLF_MA_shp = sLF_AR_shp - n_LF;
-
-        LTP_shp_buf_idx = ( LTP_shp_buf_idx - 1 ) & LTP_MASK;
-        LTP_shp_buf[ LTP_shp_buf_idx ] = sLF_MA_shp;
-
-        xw[ i ] = sLF_MA_shp - n_LTP;
-    }
-    /* Copy temp variable back to state */
-    P->sLF_AR_shp       = sLF_AR_shp;
-    P->sLF_MA_shp       = sLF_MA_shp;
-    P->sLTP_shp_buf_idx = LTP_shp_buf_idx;
-}
--- a/media/libopus/silk/float/schur_FLP.c
+++ b/media/libopus/silk/float/schur_FLP.c
@@ -33,38 +33,38 @@ POSSIBILITY OF SUCH DAMAGE.
 
 silk_float silk_schur_FLP(                  /* O    returns residual energy                                     */
     silk_float          refl_coef[],        /* O    reflection coefficients (length order)                      */
     const silk_float    auto_corr[],        /* I    autocorrelation sequence (length order+1)                   */
     opus_int            order               /* I    order                                                       */
 )
 {
     opus_int   k, n;
-    silk_float C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
-    silk_float Ctmp1, Ctmp2, rc_tmp;
+    double C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
+    double Ctmp1, Ctmp2, rc_tmp;
 
-    silk_assert( order==6||order==8||order==10||order==12||order==14||order==16 );
+    silk_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
 
     /* Copy correlations */
-    for( k = 0; k < order+1; k++ ) {
+    k = 0;
+    do {
         C[ k ][ 0 ] = C[ k ][ 1 ] = auto_corr[ k ];
-    }
+    } while( ++k <= order );
 
     for( k = 0; k < order; k++ ) {
         /* Get reflection coefficient */
         rc_tmp = -C[ k + 1 ][ 0 ] / silk_max_float( C[ 0 ][ 1 ], 1e-9f );
 
         /* Save the output */
-        refl_coef[ k ] = rc_tmp;
+        refl_coef[ k ] = (silk_float)rc_tmp;
 
         /* Update correlations */
         for( n = 0; n < order - k; n++ ) {
             Ctmp1 = C[ n + k + 1 ][ 0 ];
             Ctmp2 = C[ n ][ 1 ];
             C[ n + k + 1 ][ 0 ] = Ctmp1 + Ctmp2 * rc_tmp;
             C[ n ][ 1 ]         = Ctmp2 + Ctmp1 * rc_tmp;
         }
     }
 
     /* Return residual energy */
-    return C[ 0 ][ 1 ];
+    return (silk_float)C[ 0 ][ 1 ];
 }
-
deleted file mode 100644
--- a/media/libopus/silk/float/solve_LS_FLP.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/***********************************************************************
-Copyright (c) 2006-2011, Skype Limited. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-- Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-- Neither the name of Internet Society, IETF or IETF Trust, nor the
-names of specific contributors, may be used to endorse or promote
-products derived from this software without specific prior written
-permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-***********************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "main_FLP.h"
-#include "tuning_parameters.h"
-
-/**********************************************************************
- * LDL Factorisation. Finds the upper triangular matrix L and the diagonal
- * Matrix D (only the diagonal elements returned in a vector)such that
- * the symmetric matric A is given by A = L*D*L'.
- **********************************************************************/
-static OPUS_INLINE void silk_LDL_FLP(
-    silk_float          *A,         /* I/O  Pointer to Symetric Square Matrix                               */
-    opus_int            M,          /* I    Size of Matrix                                                  */
-    silk_float          *L,         /* I/O  Pointer to Square Upper triangular Matrix                       */
-    silk_float          *Dinv       /* I/O  Pointer to vector holding the inverse diagonal elements of D    */
-);
-
-/**********************************************************************
- * Function to solve linear equation Ax = b, when A is a MxM lower
- * triangular matrix, with ones on the diagonal.
- **********************************************************************/
-static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP(
-    const silk_float    *L,         /* I    Pointer to Lower Triangular Matrix                              */
-    opus_int            M,          /* I    Dim of Matrix equation                                          */
-    const silk_float    *b,         /* I    b Vector                                                        */
-    silk_float          *x          /* O    x Vector                                                        */
-);
-
-/**********************************************************************
- * Function to solve linear equation (A^T)x = b, when A is a MxM lower
- * triangular, with ones on the diagonal. (ie then A^T is upper triangular)
- **********************************************************************/
-static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP(
-    const silk_float    *L,         /* I    Pointer to Lower Triangular Matrix                              */
-    opus_int            M,          /* I    Dim of Matrix equation                                          */
-    const silk_float    *b,         /* I    b Vector                                                        */
-    silk_float          *x          /* O    x Vector                                                        */
-);
-
-/**********************************************************************
- * Function to solve linear equation Ax = b, when A is a MxM
- * symmetric square matrix - using LDL factorisation
- **********************************************************************/
-void silk_solve_LDL_FLP(
-    silk_float                      *A,                                 /* I/O  Symmetric square matrix, out: reg.          */
-    const opus_int                  M,                                  /* I    Size of matrix                              */
-    const silk_float                *b,                                 /* I    Pointer to b vector                         */
-    silk_float                      *x                                  /* O    Pointer to x solution vector                */
-)
-{
-    opus_int   i;
-    silk_float L[    MAX_MATRIX_SIZE ][ MAX_MATRIX_SIZE ];
-    silk_float T[    MAX_MATRIX_SIZE ];
-    silk_float Dinv[ MAX_MATRIX_SIZE ]; /* inverse diagonal elements of D*/
-
-    silk_assert( M <= MAX_MATRIX_SIZE );
-
-    /***************************************************
-    Factorize A by LDL such that A = L*D*(L^T),
-    where L is lower triangular with ones on diagonal
-    ****************************************************/
-    silk_LDL_FLP( A, M, &L[ 0 ][ 0 ], Dinv );
-
-    /****************************************************
-    * substitute D*(L^T) = T. ie:
-    L*D*(L^T)*x = b => L*T = b <=> T = inv(L)*b
-    ******************************************************/
-    silk_SolveWithLowerTriangularWdiagOnes_FLP( &L[ 0 ][ 0 ], M, b, T );
-
-    /****************************************************
-    D*(L^T)*x = T <=> (L^T)*x = inv(D)*T, because D is
-    diagonal just multiply with 1/d_i
-    ****************************************************/
-    for( i = 0; i < M; i++ ) {
-        T[ i ] = T[ i ] * Dinv[ i ];
-    }
-    /****************************************************
-    x = inv(L') * inv(D) * T
-    *****************************************************/
-    silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP( &L[ 0 ][ 0 ], M, T, x );
-}
-
-static OPUS_INLINE void silk_SolveWithUpperTriangularFromLowerWdiagOnes_FLP(
-    const silk_float    *L,         /* I    Pointer to Lower Triangular Matrix                              */
-    opus_int            M,          /* I    Dim of Matrix equation                                          */
-    const silk_float    *b,         /* I    b Vector                                                        */
-    silk_float          *x          /* O    x Vector                                                        */
-)
-{
-    opus_int   i, j;
-    silk_float temp;
-    const silk_float *ptr1;
-
-    for( i = M - 1; i >= 0; i-- ) {
-        ptr1 =  matrix_adr( L, 0, i, M );
-        temp = 0;
-        for( j = M - 1; j > i ; j-- ) {
-            temp += ptr1[ j * M ] * x[ j ];
-        }
-        temp = b[ i ] - temp;
-        x[ i ] = temp;
-    }
-}
-
-static OPUS_INLINE void silk_SolveWithLowerTriangularWdiagOnes_FLP(
-    const silk_float    *L,         /* I    Pointer to Lower Triangular Matrix                              */
-    opus_int            M,          /* I    Dim of Matrix equation                                          */
-    const silk_float    *b,         /* I    b Vector                                                        */
-    silk_float          *x          /* O    x Vector                                                        */
-)
-{
-    opus_int   i, j;
-    silk_float temp;
-    const silk_float *ptr1;
-
-    for( i = 0; i < M; i++ ) {
-        ptr1 =  matrix_adr( L, i, 0, M );
-        temp = 0;
-        for( j = 0; j < i; j++ ) {
-            temp += ptr1[ j ] * x[ j ];
-        }
-        temp = b[ i ] - temp;
-        x[ i ] = temp;
-    }
-}
-
-static OPUS_INLINE void silk_LDL_FLP(
-    silk_float          *A,         /* I/O  Pointer to Symetric Square Matrix                               */
-    opus_int            M,          /* I    Size of Matrix                                                  */
-    silk_float          *L,         /* I/O  Pointer to Square Upper triangular Matrix                       */
-    silk_float          *Dinv       /* I/O  Pointer to vector holding the inverse diagonal elements of D    */
-)
-{
-    opus_int i, j, k, loop_count, err = 1;
-    silk_float *ptr1, *ptr2;
-    double temp, diag_min_value;
-    silk_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; /* temp arrays*/
-
-    silk_assert( M <= MAX_MATRIX_SIZE );
-
-    diag_min_value = FIND_LTP_COND_FAC * 0.5f * ( A[ 0 ] + A[ M * M - 1 ] );
-    for( loop_count = 0; loop_count < M && err == 1; loop_count++ ) {
-        err = 0;
-        for( j = 0; j < M; j++ ) {
-            ptr1 = matrix_adr( L, j, 0, M );
-            temp = matrix_ptr( A, j, j, M ); /* element in row j column j*/
-            for( i = 0; i < j; i++ ) {
-                v[ i ] = ptr1[ i ] * D[ i ];
-                temp  -= ptr1[ i ] * v[ i ];
-            }
-            if( temp < diag_min_value ) {
-                /* Badly conditioned matrix: add white noise and run again */
-                temp = ( loop_count + 1 ) * diag_min_value - temp;
-                for( i = 0; i < M; i++ ) {
-                    matrix_ptr( A, i, i, M ) += ( silk_float )temp;
-                }
-                err = 1;
-                break;
-            }
-            D[ j ]    = ( silk_float )temp;
-            Dinv[ j ] = ( silk_float )( 1.0f / temp );
-            matrix_ptr( L, j, j, M ) = 1.0f;
-
-            ptr1 = matrix_adr( A, j, 0, M );
-            ptr2 = matrix_adr( L, j + 1, 0, M);
-            for( i = j + 1; i < M; i++ ) {
-                temp = 0.0;
-                for( k = 0; k < j; k++ ) {
-                    temp += ptr2[ k ] * v[ k ];
-                }
-                matrix_ptr( L, i, j, M ) = ( silk_float )( ( ptr1[ i ] - temp ) * Dinv[ j ] );
-                ptr2 += M; /* go to next column*/
-            }
-        }
-    }
-    silk_assert( err == 0 );
-}
-
--- a/media/libopus/silk/float/structs_FLP.h
+++ b/media/libopus/silk/float/structs_FLP.h
@@ -37,42 +37,26 @@ extern "C"
 {
 #endif
 
 /********************************/
 /* Noise shaping analysis state */
 /********************************/
 typedef struct {
     opus_int8                   LastGainIndex;
-    silk_float                  HarmBoost_smth;
     silk_float                  HarmShapeGain_smth;
     silk_float                  Tilt_smth;
 } silk_shape_state_FLP;
 
 /********************************/
-/* Prefilter state              */
-/********************************/
-typedef struct {
-    silk_float                  sLTP_shp[ LTP_BUF_LENGTH ];
-    silk_float                  sAR_shp[ MAX_SHAPE_LPC_ORDER + 1 ];
-    opus_int                    sLTP_shp_buf_idx;
-    silk_float                  sLF_AR_shp;
-    silk_float                  sLF_MA_shp;
-    silk_float                  sHarmHP;
-    opus_int32                  rand_seed;
-    opus_int                    lagPrev;
-} silk_prefilter_state_FLP;
-
-/********************************/
 /* Encoder state FLP            */
 /********************************/
 typedef struct {
     silk_encoder_state          sCmn;                               /* Common struct, shared with fixed-point code */
     silk_shape_state_FLP        sShape;                             /* Noise shaping state */
-    silk_prefilter_state_FLP    sPrefilt;                           /* Prefilter State */
 
     /* Buffer for find pitch and noise shape analysis */
     silk_float                  x_buf[ 2 * MAX_FRAME_LENGTH + LA_SHAPE_MAX ];/* Buffer for find pitch and noise shape analysis */
     silk_float                  LTPCorr;                            /* Normalized correlation from pitch lag estimator */
 } silk_encoder_state_FLP;
 
 /************************/
 /* Encoder control FLP  */
@@ -81,30 +65,26 @@ typedef struct {
     /* Prediction and coding parameters */
     silk_float                  Gains[ MAX_NB_SUBFR ];
     silk_float                  PredCoef[ 2 ][ MAX_LPC_ORDER ];     /* holds interpolated and final coefficients */
     silk_float                  LTPCoef[LTP_ORDER * MAX_NB_SUBFR];
     silk_float                  LTP_scale;
     opus_int                    pitchL[ MAX_NB_SUBFR ];
 
     /* Noise shaping parameters */
-    silk_float                  AR1[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
-    silk_float                  AR2[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+    silk_float                  AR[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
     silk_float                  LF_MA_shp[     MAX_NB_SUBFR ];
     silk_float                  LF_AR_shp[     MAX_NB_SUBFR ];
-    silk_float                  GainsPre[      MAX_NB_SUBFR ];
-    silk_float                  HarmBoost[     MAX_NB_SUBFR ];
     silk_float                  Tilt[          MAX_NB_SUBFR ];
     silk_float                  HarmShapeGain[ MAX_NB_SUBFR ];
     silk_float                  Lambda;
     silk_float                  input_quality;
     silk_float                  coding_quality;
 
     /* Measures */
-    silk_float                  sparseness;
     silk_float                  predGain;
     silk_float                  LTPredCodGain;
     silk_float                  ResNrg[ MAX_NB_SUBFR ];             /* Residual energy per subframe */
 
     /* Parameters for CBR mode */
     opus_int32                  GainsUnq_Q16[ MAX_NB_SUBFR ];
     opus_int8                   lastGainIndexPrev;
 } silk_encoder_control_FLP;
--- a/media/libopus/silk/float/wrappers_FLP.c
+++ b/media/libopus/silk/float/wrappers_FLP.c
@@ -49,23 +49,24 @@ void silk_A2NLSF_FLP(
 
     silk_A2NLSF( NLSF_Q15, a_fix_Q16, LPC_order );
 }
 
 /* Convert LSF parameters to AR prediction filter coefficients */
 void silk_NLSF2A_FLP(
     silk_float                      *pAR,                               /* O    LPC coefficients [ LPC_order ]              */
     const opus_int16                *NLSF_Q15,                          /* I    NLSF vector      [ LPC_order ]              */
-    const opus_int                  LPC_order                           /* I    LPC order                                   */
+    const opus_int                  LPC_order,                          /* I    LPC order                                   */
+    int                             arch                                /* I    Run-time architecture                       */
 )
 {
     opus_int   i;
     opus_int16 a_fix_Q12[ MAX_LPC_ORDER ];
 
-    silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order );
+    silk_NLSF2A( a_fix_Q12, NLSF_Q15, LPC_order, arch );
 
     for( i = 0; i < LPC_order; i++ ) {
         pAR[ i ] = ( silk_float )a_fix_Q12[ i ] * ( 1.0f / 4096.0f );
     }
 }
 
 /******************************************/
 /* Floating-point NLSF processing wrapper */
@@ -97,34 +98,34 @@ void silk_NSQ_wrapper_FLP(
     silk_encoder_control_FLP        *psEncCtrl,                         /* I/O  Encoder control FLP                         */
     SideInfoIndices                 *psIndices,                         /* I/O  Quantization indices                        */
     silk_nsq_state                  *psNSQ,                             /* I/O  Noise Shaping Quantzation state             */
     opus_int8                       pulses[],                           /* O    Quantized pulse signal                      */
     const silk_float                x[]                                 /* I    Prefiltered input signal                    */
 )
 {
     opus_int     i, j;
-    opus_int32   x_Q3[ MAX_FRAME_LENGTH ];
+    opus_int16   x16[ MAX_FRAME_LENGTH ];
     opus_int32   Gains_Q16[ MAX_NB_SUBFR ];
     silk_DWORD_ALIGN opus_int16 PredCoef_Q12[ 2 ][ MAX_LPC_ORDER ];
     opus_int16   LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ];
     opus_int     LTP_scale_Q14;
 
     /* Noise shaping parameters */
-    opus_int16   AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
+    opus_int16   AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ];
     opus_int32   LF_shp_Q14[ MAX_NB_SUBFR ];         /* Packs two int16 coefficients per int32 value             */
     opus_int     Lambda_Q10;
     opus_int     Tilt_Q14[ MAX_NB_SUBFR ];
     opus_int     HarmShapeGain_Q14[ MAX_NB_SUBFR ];
 
     /* Convert control struct to fix control struct */
     /* Noise shape parameters */
     for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
         for( j = 0; j < psEnc->sCmn.shapingLPCOrder; j++ ) {
-            AR2_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR2[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f );
+            AR_Q13[ i * MAX_SHAPE_LPC_ORDER + j ] = silk_float2int( psEncCtrl->AR[ i * MAX_SHAPE_LPC_ORDER + j ] * 8192.0f );
         }
     }
 
     for( i = 0; i < psEnc->sCmn.nb_subfr; i++ ) {
         LF_shp_Q14[ i ] =   silk_LSHIFT32( silk_float2int( psEncCtrl->LF_AR_shp[ i ]     * 16384.0f ), 16 ) |
                               (opus_uint16)silk_float2int( psEncCtrl->LF_MA_shp[ i ]     * 16384.0f );
         Tilt_Q14[ i ]   =        (opus_int)silk_float2int( psEncCtrl->Tilt[ i ]          * 16384.0f );
         HarmShapeGain_Q14[ i ] = (opus_int)silk_float2int( psEncCtrl->HarmShapeGain[ i ] * 16384.0f );
@@ -150,53 +151,57 @@ void silk_NSQ_wrapper_FLP(
     if( psIndices->signalType == TYPE_VOICED ) {
         LTP_scale_Q14 = silk_LTPScales_table_Q14[ psIndices->LTP_scaleIndex ];
     } else {
         LTP_scale_Q14 = 0;
     }
 
     /* Convert input to fix */
     for( i = 0; i < psEnc->sCmn.frame_length; i++ ) {
-        x_Q3[ i ] = silk_float2int( 8.0f * x[ i ] );
+        x16[ i ] = silk_float2int( x[ i ] );
     }
 
     /* Call NSQ */
     if( psEnc->sCmn.nStatesDelayedDecision > 1 || psEnc->sCmn.warping_Q16 > 0 ) {
-        silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
-            AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+        silk_NSQ_del_dec( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+            AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
     } else {
-        silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x_Q3, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
-            AR2_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
+        silk_NSQ( &psEnc->sCmn, psNSQ, psIndices, x16, pulses, PredCoef_Q12[ 0 ], LTPCoef_Q14,
+            AR_Q13, HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, psEncCtrl->pitchL, Lambda_Q10, LTP_scale_Q14, psEnc->sCmn.arch );
     }
 }
 
 /***********************************************/
 /* Floating-point Silk LTP quantiation wrapper */
 /***********************************************/
 void silk_quant_LTP_gains_FLP(
-    silk_float                      B[ MAX_NB_SUBFR * LTP_ORDER ],      /* I/O  (Un-)quantized LTP gains                    */
+    silk_float                      B[ MAX_NB_SUBFR * LTP_ORDER ],      /* O    Quantized LTP gains                            */
     opus_int8                       cbk_index[ MAX_NB_SUBFR ],          /* O    Codebook index                              */
     opus_int8                       *periodicity_index,                 /* O    Periodicity index                           */
     opus_int32                      *sum_log_gain_Q7,                   /* I/O  Cumulative max prediction gain  */
-    const silk_float                W[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I    Error weights                        */
-    const opus_int                  mu_Q10,                             /* I    Mu value (R/D tradeoff)                     */
-    const opus_int                  lowComplexity,                      /* I    Flag for low complexity                     */
-    const opus_int                  nb_subfr,                           /* I    number of subframes                         */
+    silk_float                      *pred_gain_dB,                        /* O    LTP prediction gain                            */
+    const silk_float                XX[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ], /* I    Correlation matrix                    */
+    const silk_float                xX[ MAX_NB_SUBFR * LTP_ORDER ],        /* I    Correlation vector                            */
+    const opus_int                    subfr_len,                            /* I    Number of samples per subframe                */
+    const opus_int                    nb_subfr,                           /* I    Number of subframes                            */
     int                             arch                                /* I    Run-time architecture                       */
 )
 {
-    opus_int   i;
+    opus_int   i, pred_gain_dB_Q7;
     opus_int16 B_Q14[ MAX_NB_SUBFR * LTP_ORDER ];
-    opus_int32 W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ];
+    opus_int32 XX_Q17[ MAX_NB_SUBFR * LTP_ORDER * LTP_ORDER ];
+    opus_int32 xX_Q17[ MAX_NB_SUBFR * LTP_ORDER ];
 
+    for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) {
+        XX_Q17[ i ] = (opus_int32)silk_float2int( XX[ i ] * 131072.0f );
+    }
     for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
-        B_Q14[ i ] = (opus_int16)silk_float2int( B[ i ] * 16384.0f );
-    }
-    for( i = 0; i < nb_subfr * LTP_ORDER * LTP_ORDER; i++ ) {
-        W_Q18[ i ] = (opus_int32)silk_float2int( W[ i ] * 262144.0f );
+        xX_Q17[ i ] = (opus_int32)silk_float2int( xX[ i ] * 131072.0f );
     }
 
-    silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, W_Q18, mu_Q10, lowComplexity, nb_subfr, arch );
+    silk_quant_LTP_gains( B_Q14, cbk_index, periodicity_index, sum_log_gain_Q7, &pred_gain_dB_Q7, XX_Q17, xX_Q17, subfr_len, nb_subfr, arch );
 
     for( i = 0; i < nb_subfr * LTP_ORDER; i++ ) {
         B[ i ] = (silk_float)B_Q14[ i ] * ( 1.0f / 16384.0f );
     }
+
+    *pred_gain_dB = (silk_float)pred_gain_dB_Q7 * ( 1.0f / 128.0f );
 }
--- a/media/libopus/silk/gain_quant.c
+++ b/media/libopus/silk/gain_quant.c
@@ -71,16 +71,17 @@ void silk_gains_quant(
                 ind[ k ] = double_step_size_threshold + silk_RSHIFT( ind[ k ] - double_step_size_threshold + 1, 1 );
             }
 
             ind[ k ] = silk_LIMIT_int( ind[ k ], MIN_DELTA_GAIN_QUANT, MAX_DELTA_GAIN_QUANT );
 
             /* Accumulate deltas */
             if( ind[ k ] > double_step_size_threshold ) {
                 *prev_ind += silk_LSHIFT( ind[ k ], 1 ) - double_step_size_threshold;
+                *prev_ind = silk_min_int( *prev_ind, N_LEVELS_QGAIN - 1 );
             } else {
                 *prev_ind += ind[ k ];
             }
 
             /* Shift to make non-negative */
             ind[ k ] -= MIN_DELTA_GAIN_QUANT;
         }
 
--- a/media/libopus/silk/init_decoder.c
+++ b/media/libopus/silk/init_decoder.c
@@ -39,16 +39,17 @@ opus_int silk_init_decoder(
 )
 {
     /* Clear the entire encoder state, except anything copied */
     silk_memset( psDec, 0, sizeof( silk_decoder_state ) );
 
     /* Used to deactivate LSF interpolation */
     psDec->first_frame_after_reset = 1;
     psDec->prev_gain_Q16 = 65536;
+    psDec->arch = opus_select_arch();
 
     /* Reset CNG state */
     silk_CNG_Reset( psDec );
 
     /* Reset PLC state */
     silk_PLC_Reset( psDec );
 
     return(0);
--- a/media/libopus/silk/lin2log.c
+++ b/media/libopus/silk/lin2log.c
@@ -36,11 +36,11 @@ opus_int32 silk_lin2log(
     const opus_int32            inLin               /* I  input in linear scale                                         */
 )
 {
     opus_int32 lz, frac_Q7;
 
     silk_CLZ_FRAC( inLin, &lz, &frac_Q7 );
 
     /* Piece-wise parabolic approximation */
-    return silk_LSHIFT( 31 - lz, 7 ) + silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 );
+    return silk_ADD_LSHIFT32( silk_SMLAWB( frac_Q7, silk_MUL( frac_Q7, 128 - frac_Q7 ), 179 ), 31 - lz, 7 );
 }
 
--- a/media/libopus/silk/macros.h
+++ b/media/libopus/silk/macros.h
@@ -31,24 +31,16 @@ POSSIBILITY OF SUCH DAMAGE.
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "opus_types.h"
 #include "opus_defines.h"
 #include "arch.h"
 
-#if OPUS_GNUC_PREREQ(3, 0)
-#define opus_likely(x)       (__builtin_expect(!!(x), 1))
-#define opus_unlikely(x)     (__builtin_expect(!!(x), 0))
-#else
-#define opus_likely(x)       (!!(x))
-#define opus_unlikely(x)     (!!(x))
-#endif
-
 /* This is an OPUS_INLINE header file for general platform. */
 
 /* (a32 * (opus_int32)((opus_int16)(b32))) >> 16 output have to be 32bit int */
 #if OPUS_FAST_INT64
 #define silk_SMULWB(a32, b32)            ((opus_int32)(((a32) * (opus_int64)((opus_int16)(b32))) >> 16))
 #else
 #define silk_SMULWB(a32, b32)            ((((a32) >> 16) * (opus_int32)((opus_int16)(b32))) + ((((a32) & 0x0000FFFF) * (opus_int32)((opus_int16)(b32))) >> 16))
 #endif
--- a/media/libopus/silk/main.h
+++ b/media/libopus/silk/main.h
@@ -37,16 +37,20 @@ POSSIBILITY OF SUCH DAMAGE.
 #include "debug.h"
 #include "entenc.h"
 #include "entdec.h"
 
 #if defined(OPUS_X86_MAY_HAVE_SSE4_1)
 #include "x86/main_sse.h"
 #endif
 
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#include "arm/NSQ_del_dec_arm.h"
+#endif
+
 /* Convert Left/Right stereo signal to adaptive Mid/Side representation */
 void silk_stereo_LR_to_MS(
     stereo_enc_state            *state,                         /* I/O  State                                       */
     opus_int16                  x1[],                           /* I/O  Left input signal, becomes mid signal       */
     opus_int16                  x2[],                           /* I/O  Right input signal, becomes side signal     */
     opus_int8                   ix[ 2 ][ 3 ],                   /* O    Quantization indices                        */
     opus_int8                   *mid_only_flag,                 /* O    Flag: only mid signal coded                 */
     opus_int32                  mid_side_rates_bps[],           /* O    Bitrates for mid and side signals           */
@@ -104,32 +108,32 @@ void silk_stereo_decode_pred(
 /* Decode mid-only flag */
 void silk_stereo_decode_mid_only(
     ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
     opus_int                    *decode_only_mid                /* O    Flag that only mid channel has been coded   */
 );
 
 /* 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            */
+    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        */
 );
 
 /* Decodes signs of excitation */
 void silk_decode_signs(
-    ec_dec                      *psRangeDec,                        /* I/O  Compressor data structure                   */
-    opus_int16                  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            */
+    ec_dec                      *psRangeDec,                        /* I/O  Compressor data structure               */
+    opus_int16                  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        */
 );
 
 /* Check encoder control struct */
 opus_int check_control_input(
     silk_EncControlStruct        *encControl                    /* I    Control structure                           */
 );
 
 /* Control internal sampling rate */
@@ -200,101 +204,101 @@ void silk_interpolate(
     const opus_int16            x0[ MAX_LPC_ORDER ],            /* I    first vector                                */
     const opus_int16            x1[ MAX_LPC_ORDER ],            /* I    second vector                               */
     const opus_int              ifact_Q2,                       /* I    interp. factor, weight on 2nd vector        */
     const opus_int              d                               /* I    number of parameters                        */
 );
 
 /* LTP tap quantizer */
 void silk_quant_LTP_gains(
-    opus_int16                  B_Q14[ MAX_NB_SUBFR * LTP_ORDER ],          /* I/O  (un)quantized LTP gains         */
+    opus_int16                  B_Q14[ MAX_NB_SUBFR * LTP_ORDER ],          /* O    Quantized LTP gains             */
     opus_int8                   cbk_index[ MAX_NB_SUBFR ],                  /* O    Codebook Index                  */
     opus_int8                   *periodicity_index,                         /* O    Periodicity Index               */
     opus_int32                  *sum_gain_dB_Q7,                            /* I/O  Cumulative max prediction gain  */
-    const opus_int32            W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ],  /* I    Error Weights in Q18            */
-    opus_int                    mu_Q9,                                      /* I    Mu value (R/D tradeoff)         */
-    opus_int                    lowComplexity,                              /* I    Flag for low complexity         */
-    const opus_int              nb_subfr,                                   /* I    number of subframes             */
+    opus_int                    *pred_gain_dB_Q7,                           /* O    LTP prediction gain             */
+    const opus_int32            XX_Q17[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I    Correlation matrix in Q18       */
+    const opus_int32            xX_Q17[ MAX_NB_SUBFR*LTP_ORDER ],           /* I    Correlation vector in Q18       */
+    const opus_int              subfr_len,                                  /* I    Number of samples per subframe  */
+    const opus_int              nb_subfr,                                   /* I    Number of subframes             */
     int                         arch                                        /* I    Run-time architecture           */
 );
 
 /* Entropy constrained matrix-weighted VQ, for a single input data vector */
 void silk_VQ_WMat_EC_c(
     opus_int8                   *ind,                           /* O    index of best codebook vector               */
-    opus_int32                  *rate_dist_Q14,                 /* O    best weighted quant error + mu * rate       */
+    opus_int32                  *res_nrg_Q15,                   /* O    best residual energy                        */
+    opus_int32                  *rate_dist_Q8,                  /* O    best total bitrate                          */
     opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
-    const opus_int16            *in_Q14,                        /* I    input vector to be quantized                */
-    const opus_int32            *W_Q18,                         /* I    weighting matrix                            */
+    const opus_int32            *XX_Q17,                        /* I    correlation matrix                          */
+    const opus_int32            *xX_Q17,                        /* I    correlation vector                          */
     const opus_int8             *cb_Q7,                         /* I    codebook                                    */
     const opus_uint8            *cb_gain_Q7,                    /* I    codebook effective gain                     */
     const opus_uint8            *cl_Q5,                         /* I    code length for each codebook vector        */
-    const opus_int              mu_Q9,                          /* I    tradeoff betw. weighted error and rate      */
+    const opus_int              subfr_len,                      /* I    number of samples per subframe              */
     const opus_int32            max_gain_Q7,                    /* I    maximum sum of absolute LTP coefficients    */
-    opus_int                    L                               /* I    number of vectors in codebook               */
+    const opus_int              L                               /* I    number of vectors in codebook               */
 );
 
 #if !defined(OVERRIDE_silk_VQ_WMat_EC)
-#define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
-                          mu_Q9, max_gain_Q7, L, arch) \
-    ((void)(arch),silk_VQ_WMat_EC_c(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
-                          mu_Q9, max_gain_Q7, L))
+#define silk_VQ_WMat_EC(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L, arch) \
+    ((void)(arch),silk_VQ_WMat_EC_c(ind, res_nrg_Q15, rate_dist_Q8, gain_Q7, XX_Q17, xX_Q17, cb_Q7, cb_gain_Q7, cl_Q5, subfr_len, max_gain_Q7, L))
 #endif
 
 /************************************/
 /* Noise shaping quantization (NSQ) */
 /************************************/
 
 void silk_NSQ_c(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
-    const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
+    const opus_int16            x16[],                                      /* I    Input                           */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
-    const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I  Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
     const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                   /* I    Spectral tilt                   */
     const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                 /* I    Low frequency shaping coefs     */
     const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                  /* I    Quantization step sizes         */
     const opus_int              pitchL[ MAX_NB_SUBFR ],                     /* I    Pitch lags                      */
     const opus_int              Lambda_Q10,                                 /* I    Rate/distortion tradeoff        */
     const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
 );
 
 #if !defined(OVERRIDE_silk_NSQ)
-#define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+#define silk_NSQ(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
-    ((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+    ((void)(arch),silk_NSQ_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
 #endif
 
 /* Noise shaping using delayed decision */
 void silk_NSQ_del_dec_c(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
-    const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
+    const opus_int16            x16[],                                      /* I    Input                           */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
-    const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
+    const opus_int16            AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I  Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
     const opus_int              Tilt_Q14[ MAX_NB_SUBFR ],                   /* I    Spectral tilt                   */
     const opus_int32            LF_shp_Q14[ MAX_NB_SUBFR ],                 /* I    Low frequency shaping coefs     */
     const opus_int32            Gains_Q16[ MAX_NB_SUBFR ],                  /* I    Quantization step sizes         */
     const opus_int              pitchL[ MAX_NB_SUBFR ],                     /* I    Pitch lags                      */
     const opus_int              Lambda_Q10,                                 /* I    Rate/distortion tradeoff        */
     const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
 );
 
 #if !defined(OVERRIDE_silk_NSQ_del_dec)
-#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+#define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
-    ((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
+    ((void)(arch),silk_NSQ_del_dec_c(psEncC, NSQ, psIndices, x16, pulses, PredCoef_Q12, LTPCoef_Q14, AR_Q13, \
                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
 #endif
 
 /************/
 /* Silk VAD */
 /************/
 /* Initialize the Silk VAD */
 opus_int silk_VAD_Init(                                         /* O    Return value, 0 if success                  */
@@ -341,16 +345,17 @@ opus_int32 silk_NLSF_encode(            
     const opus_int              signalType                      /* I    Signal type: 0/1/2                          */
 );
 
 /* 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_int16            pWght_Q9[],                     /* I    Codebook weights [K*LPC_order]              */
     const opus_int              K,                              /* I    Number of codebook vectors                  */
     const opus_int              LPC_order                       /* I    Number of LPCs                              */
 );
 
 /* 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 ]                             */
--- a/media/libopus/silk/mips/NSQ_del_dec_mipsr1.h
+++ b/media/libopus/silk/mips/NSQ_del_dec_mipsr1.h
@@ -56,17 +56,17 @@ static inline void silk_noise_shape_quan
     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            *smpl_buf_idx,          /* I/O  Index to newest samples in buffers  */
     opus_int            decisionDelay,          /* I                                        */
     int                 arch                    /* 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_Q14, n_AR_Q14, n_LTP_Q14;
     opus_int32   n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
@@ -318,18 +318,19 @@ static inline void silk_noise_shape_quan
             /* Update states */
             sLF_AR_shp_Q14         = silk_SUB32( xq_Q14, n_AR_Q14 );
             psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
             psSS[ 1 ].LF_AR_Q14    = sLF_AR_shp_Q14;
             psSS[ 1 ].LPC_exc_Q14  = LPC_exc_Q14;
             psSS[ 1 ].xq_Q14       = xq_Q14;
         }
 
-        *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   */
+        *smpl_buf_idx  = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
+        if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
+        last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
 
         /* 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;
--- a/media/libopus/silk/mips/sigproc_fix_mipsr1.h
+++ b/media/libopus/silk/mips/sigproc_fix_mipsr1.h
@@ -23,21 +23,16 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY 
 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_MIPSR1_H
 #define SILK_SIGPROC_FIX_MIPSR1_H
 
-#ifdef  __cplusplus
-extern "C"
-{
-#endif
-
 #undef silk_SAT16
 static inline short int silk_SAT16(int a)
 {
     int c;
     c = __builtin_mips_shll_s_w(a, 16);
     c = c>>16;
 
     return c;
--- a/media/libopus/silk/process_NLSFs.c
+++ b/media/libopus/silk/process_NLSFs.c
@@ -84,24 +84,24 @@ void silk_process_NLSFs(
             silk_assert( pNLSFW_QW[ i ] >= 1 );
         }
     }
 
     silk_NLSF_encode( psEncC->indices.NLSFIndices, pNLSF_Q15, psEncC->psNLSF_CB, pNLSFW_QW,
         NLSF_mu_Q20, psEncC->NLSF_MSVQ_Survivors, psEncC->indices.signalType );
 
     /* Convert quantized NLSFs back to LPC coefficients */
-    silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder );
+    silk_NLSF2A( PredCoef_Q12[ 1 ], pNLSF_Q15, psEncC->predictLPCOrder, psEncC->arch );
 
     if( doInterpolate ) {
         /* Calculate the interpolated, quantized LSF vector for the first half */
         silk_interpolate( pNLSF0_temp_Q15, prev_NLSFq_Q15, pNLSF_Q15,
             psEncC->indices.NLSFInterpCoef_Q2, psEncC->predictLPCOrder );
 
         /* Convert back to LPC coefficients */
-        silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder );
+        silk_NLSF2A( PredCoef_Q12[ 0 ], pNLSF0_temp_Q15, psEncC->predictLPCOrder, psEncC->arch );
 
     } else {
         /* Copy LPC coefficients for first half from second half */
         silk_assert( psEncC->predictLPCOrder <= MAX_LPC_ORDER );
         silk_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) );
     }
 }
--- a/media/libopus/silk/quant_LTP_gains.c
+++ b/media/libopus/silk/quant_LTP_gains.c
@@ -28,102 +28,105 @@ POSSIBILITY OF SUCH DAMAGE.
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "main.h"
 #include "tuning_parameters.h"
 
 void silk_quant_LTP_gains(
-    opus_int16                  B_Q14[ MAX_NB_SUBFR * LTP_ORDER ],          /* I/O  (un)quantized LTP gains         */
+    opus_int16                  B_Q14[ MAX_NB_SUBFR * LTP_ORDER ],          /* O    Quantized LTP gains             */
     opus_int8                   cbk_index[ MAX_NB_SUBFR ],                  /* O    Codebook Index                  */
     opus_int8                   *periodicity_index,                         /* O    Periodicity Index               */
     opus_int32                  *sum_log_gain_Q7,                           /* I/O  Cumulative max prediction gain  */
-    const opus_int32            W_Q18[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ],  /* I    Error Weights in Q18            */
-    opus_int                    mu_Q9,                                      /* I    Mu value (R/D tradeoff)         */
-    opus_int                    lowComplexity,                              /* I    Flag for low complexity         */
-    const opus_int              nb_subfr,                                   /* I    number of subframes             */
+    opus_int                    *pred_gain_dB_Q7,                           /* O    LTP prediction gain             */
+    const opus_int32            XX_Q17[ MAX_NB_SUBFR*LTP_ORDER*LTP_ORDER ], /* I    Correlation matrix in Q18       */
+    const opus_int32            xX_Q17[ MAX_NB_SUBFR*LTP_ORDER ],           /* I    Correlation vector in Q18       */
+    const opus_int              subfr_len,                                  /* I    Number of samples per subframe  */
+    const opus_int              nb_subfr,                                   /* I    Number of subframes             */
     int                         arch                                        /* I    Run-time architecture           */
 )
 {
     opus_int             j, k, cbk_size;
     opus_int8            temp_idx[ MAX_NB_SUBFR ];
     const opus_uint8     *cl_ptr_Q5;
     const opus_int8      *cbk_ptr_Q7;
     const opus_uint8     *cbk_gain_ptr_Q7;
-    const opus_int16     *b_Q14_ptr;
-    const opus_int32     *W_Q18_ptr;
-    opus_int32           rate_dist_Q14_subfr, rate_dist_Q14, min_rate_dist_Q14;
-    opus_int32           sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7, gain_Q7;
+    const opus_int32     *XX_Q17_ptr, *xX_Q17_ptr;
+    opus_int32           res_nrg_Q15_subfr, res_nrg_Q15, rate_dist_Q7_subfr, rate_dist_Q7, min_rate_dist_Q7;
+    opus_int32           sum_log_gain_tmp_Q7, best_sum_log_gain_Q7, max_gain_Q7;
+    opus_int             gain_Q7;
 
     /***************************************************/
     /* iterate over different codebooks with different */
     /* rates/distortions, and choose best */
     /***************************************************/
-    min_rate_dist_Q14 = silk_int32_MAX;
+    min_rate_dist_Q7 = silk_int32_MAX;
     best_sum_log_gain_Q7 = 0;
     for( k = 0; k < 3; k++ ) {
         /* Safety margin for pitch gain control, to take into account factors
            such as state rescaling/rewhitening. */
         opus_int32 gain_safety = SILK_FIX_CONST( 0.4, 7 );
 
         cl_ptr_Q5  = silk_LTP_gain_BITS_Q5_ptrs[ k ];
         cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[        k ];
         cbk_gain_ptr_Q7 = silk_LTP_vq_gain_ptrs_Q7[ k ];
         cbk_size   = silk_LTP_vq_sizes[          k ];
 
-        /* Set up pointer to first subframe */
-        W_Q18_ptr = W_Q18;
-        b_Q14_ptr = B_Q14;
+        /* Set up pointers to first subframe */
+        XX_Q17_ptr = XX_Q17;
+        xX_Q17_ptr = xX_Q17;
 
-        rate_dist_Q14 = 0;
+        res_nrg_Q15 = 0;
+        rate_dist_Q7 = 0;
         sum_log_gain_tmp_Q7 = *sum_log_gain_Q7;
         for( j = 0; j < nb_subfr; j++ ) {
             max_gain_Q7 = silk_log2lin( ( SILK_FIX_CONST( MAX_SUM_LOG_GAIN_DB / 6.0, 7 ) - sum_log_gain_tmp_Q7 )
                                         + SILK_FIX_CONST( 7, 7 ) ) - gain_safety;
-
             silk_VQ_WMat_EC(
                 &temp_idx[ j ],         /* O    index of best codebook vector                           */
-                &rate_dist_Q14_subfr,   /* O    best weighted quantization error + mu * rate            */
+                &res_nrg_Q15_subfr,     /* O    residual energy                                         */
+                &rate_dist_Q7_subfr,    /* O    best weighted quantization error + mu * rate            */
                 &gain_Q7,               /* O    sum of absolute LTP coefficients                        */
-                b_Q14_ptr,              /* I    input vector to be quantized                            */
-                W_Q18_ptr,              /* I    weighting matrix                                        */
+                XX_Q17_ptr,             /* I    correlation matrix                                      */
+                xX_Q17_ptr,             /* I    correlation vector                                      */
                 cbk_ptr_Q7,             /* I    codebook                                                */
                 cbk_gain_ptr_Q7,        /* I    codebook effective gains                                */
                 cl_ptr_Q5,              /* I    code length for each codebook vector                    */
-                mu_Q9,                  /* I    tradeoff between weighted error and rate                */
+                subfr_len,              /* I    number of samples per subframe                          */
                 max_gain_Q7,            /* I    maximum sum of absolute LTP coefficients                */
                 cbk_size,               /* I    number of vectors in codebook                           */
                 arch                    /* I    Run-time architecture                                   */
             );
 
-            rate_dist_Q14 = silk_ADD_POS_SAT32( rate_dist_Q14, rate_dist_Q14_subfr );
+            res_nrg_Q15  = silk_ADD_POS_SAT32( res_nrg_Q15, res_nrg_Q15_subfr );
+            rate_dist_Q7 = silk_ADD_POS_SAT32( rate_dist_Q7, rate_dist_Q7_subfr );
             sum_log_gain_tmp_Q7 = silk_max(0, sum_log_gain_tmp_Q7
                                 + silk_lin2log( gain_safety + gain_Q7 ) - SILK_FIX_CONST( 7, 7 ));
 
-            b_Q14_ptr += LTP_ORDER;
-            W_Q18_ptr += LTP_ORDER * LTP_ORDER;
+            XX_Q17_ptr += LTP_ORDER * LTP_ORDER;
+            xX_Q17_ptr += LTP_ORDER;
         }
 
-        /* Avoid never finding a codebook */
-        rate_dist_Q14 = silk_min( silk_int32_MAX - 1, rate_dist_Q14 );
-
-        if( rate_dist_Q14 < min_rate_dist_Q14 ) {
-            min_rate_dist_Q14 = rate_dist_Q14;
+        if( rate_dist_Q7 <= min_rate_dist_Q7 ) {
+            min_rate_dist_Q7 = rate_dist_Q7;
             *periodicity_index = (opus_int8)k;
             silk_memcpy( cbk_index, temp_idx, nb_subfr * sizeof( opus_int8 ) );
             best_sum_log_gain_Q7 = sum_log_gain_tmp_Q7;
         }
-
-        /* Break early in low-complexity mode if rate distortion is below threshold */
-        if( lowComplexity && ( rate_dist_Q14 < silk_LTP_gain_middle_avg_RD_Q14 ) ) {
-            break;
-        }
     }
 
     cbk_ptr_Q7 = silk_LTP_vq_ptrs_Q7[ *periodicity_index ];
     for( j = 0; j < nb_subfr; j++ ) {
         for( k = 0; k < LTP_ORDER; k++ ) {
             B_Q14[ j * LTP_ORDER + k ] = silk_LSHIFT( cbk_ptr_Q7[ cbk_index[ j ] * LTP_ORDER + k ], 7 );
         }
     }
+
+    if( nb_subfr == 2 ) {
+        res_nrg_Q15 = silk_RSHIFT32( res_nrg_Q15, 1 );
+    } else {
+        res_nrg_Q15 = silk_RSHIFT32( res_nrg_Q15, 2 );
+    }
+
     *sum_log_gain_Q7 = best_sum_log_gain_Q7;
+    *pred_gain_dB_Q7 = (opus_int)silk_SMULBB( -3, silk_lin2log( res_nrg_Q15 ) - ( 15 << 7 ) );
 }
--- a/media/libopus/silk/structs.h
+++ b/media/libopus/silk/structs.h
@@ -43,16 +43,17 @@ extern "C"
 /* Noise shaping quantization state */
 /************************************/
 typedef struct {
     opus_int16                  xq[           2 * MAX_FRAME_LENGTH ]; /* Buffer for quantized output signal                             */
     opus_int32                  sLTP_shp_Q14[ 2 * MAX_FRAME_LENGTH ];
     opus_int32                  sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
     opus_int32                  sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
     opus_int32                  sLF_AR_shp_Q14;
+    opus_int32                  sDiff_shp_Q14;
     opus_int                    lagPrev;
     opus_int                    sLTP_buf_idx;
     opus_int                    sLTP_shp_buf_idx;
     opus_int32                  rand_seed;
     opus_int32                  prev_gain_Q16;
     opus_int                    rewhite_flag;
 } silk_nsq_state;
 
@@ -81,16 +82,17 @@ typedef struct {
 
 /* Structure containing NLSF codebook */
 typedef struct {
     const opus_int16             nVectors;
     const opus_int16             order;
     const opus_int16             quantStepSize_Q16;
     const opus_int16             invQuantStepSize_Q6;
     const opus_uint8             *CB1_NLSF_Q8;
+    const opus_int16             *CB1_Wght_Q9;
     const opus_uint8             *CB1_iCDF;
     const opus_uint8             *pred_Q8;
     const opus_uint8             *ec_sel;
     const opus_uint8             *ec_iCDF;
     const opus_uint8             *ec_Rates_Q5;
     const opus_int16             *deltaMin_Q15;
 } silk_NLSF_CB_struct;
 
@@ -164,18 +166,16 @@ typedef struct {
     opus_int                     Complexity;                        /* Complexity setting                                               */
     opus_int                     nStatesDelayedDecision;            /* Number of states in delayed decision quantization                */
     opus_int                     useInterpolatedNLSFs;              /* Flag for using NLSF interpolation                                */
     opus_int                     shapingLPCOrder;                   /* Filter order for noise shaping filters                           */
     opus_int                     predictLPCOrder;                   /* Filter order for prediction filters                              */
     opus_int                     pitchEstimationComplexity;         /* Complexity level for pitch estimator                             */
     opus_int                     pitchEstimationLPCOrder;           /* Whitening filter order for pitch estimator                       */
     opus_int32                   pitchEstimationThreshold_Q16;      /* Threshold for pitch estimator                                    */
-    opus_int                     LTPQuantLowComplexity;             /* Flag for low complexity LTP quantization                         */
-    opus_int                     mu_LTP_Q9;                         /* Rate-distortion tradeoff in LTP quantization                     */
     opus_int32                   sum_log_gain_Q7;                   /* Cumulative max prediction gain                                   */
     opus_int                     NLSF_MSVQ_Survivors;               /* Number of survivors in NLSF MSVQ                                 */
     opus_int                     first_frame_after_reset;           /* Flag for deactivating NLSF interpolation, pitch prediction       */
     opus_int                     controlled_since_last_payload;     /* Flag for ensuring codec_control only runs once per packet        */
     opus_int                     warping_Q16;                       /* Warping parameter for warped noise shaping                       */
     opus_int                     useCBR;                            /* Flag to enable constant bitrate                                  */
     opus_int                     prefillFlag;                       /* Flag to indicate that only buffers are prefilled, no coding      */
     const opus_uint8             *pitch_lag_low_bits_iCDF;          /* Pointer to iCDF table for low bits of pitch lag index            */
@@ -296,16 +296,17 @@ typedef struct {
     SideInfoIndices             indices;
 
     /* CNG state */
     silk_CNG_struct             sCNG;
 
     /* Stuff used for PLC */
     opus_int                    lossCnt;
     opus_int                    prevSignalType;
+    int                         arch;
 
     silk_PLC_struct sPLC;
 
 } silk_decoder_state;
 
 /************************/
 /* Decoder control      */
 /************************/
--- a/media/libopus/silk/sum_sqr_shift.c
+++ b/media/libopus/silk/sum_sqr_shift.c
@@ -36,51 +36,48 @@ POSSIBILITY OF SUCH DAMAGE.
 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                                       */
 )
 {
     opus_int   i, shft;
-    opus_int32 nrg_tmp, nrg;
+    opus_uint32 nrg_tmp;
+    opus_int32 nrg;
 
-    nrg  = 0;
-    shft = 0;
-    len--;
-    for( i = 0; i < len; i += 2 ) {
-        nrg = silk_SMLABB_ovflw( nrg, x[ i ], x[ i ] );
-        nrg = silk_SMLABB_ovflw( nrg, x[ i + 1 ], x[ i + 1 ] );
-        if( nrg < 0 ) {
-            /* Scale down */
-            nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
-            shft = 2;
-            i+=2;
-            break;
-        }
-    }
-    for( ; i < len; i += 2 ) {
+    /* Do a first run with the maximum shift we could have. */
+    shft = 31-silk_CLZ32(len);
+    /* Let's be conservative with rounding and start with nrg=len. */
+    nrg  = len;
+    for( i = 0; i < len - 1; i += 2 ) {
         nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
         nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
-        nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, (opus_uint32)nrg_tmp, shft );
-        if( nrg < 0 ) {
-            /* Scale down */
-            nrg = (opus_int32)silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
-            shft += 2;
-        }
+        nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+    }
+    if( i < len ) {
+        /* One sample left to process */
+        nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+        nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
     }
-    if( i == len ) {
+    silk_assert( nrg >= 0 );
+    /* Make sure the result will fit in a 32-bit signed integer with two bits
+       of headroom. */
+    shft = silk_max_32(0, shft+3 - silk_CLZ32(nrg));
+    nrg = 0;
+    for( i = 0 ; i < len - 1; i += 2 ) {
+        nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
+        nrg_tmp = silk_SMLABB_ovflw( nrg_tmp, x[ i + 1 ], x[ i + 1 ] );
+        nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
+    }
+    if( i < len ) {
         /* One sample left to process */
         nrg_tmp = silk_SMULBB( x[ i ], x[ i ] );
         nrg = (opus_int32)silk_ADD_RSHIFT_uint( nrg, nrg_tmp, shft );
     }
 
-    /* Make sure to have at least one extra leading zero (two leading zeros in total) */
-    if( nrg & 0xC0000000 ) {
-        nrg = silk_RSHIFT_uint( (opus_uint32)nrg, 2 );
-        shft += 2;
-    }
+    silk_assert( nrg >= 0 );
 
     /* Output arguments */
     *shift  = shft;
     *energy = nrg;
 }
 
--- a/media/libopus/silk/tables.h
+++ b/media/libopus/silk/tables.h
@@ -71,20 +71,18 @@ extern const opus_uint8  silk_uniform5_i
 extern const opus_uint8  silk_uniform6_iCDF[ 6 ];                                                   /*   6 */
 extern const opus_uint8  silk_uniform8_iCDF[ 8 ];                                                   /*   8 */
 
 extern const opus_uint8  silk_NLSF_EXT_iCDF[ 7 ];                                                   /*   7 */
 
 extern const opus_uint8  silk_LTP_per_index_iCDF[ 3 ];                                              /*   3 */
 extern const opus_uint8  * const silk_LTP_gain_iCDF_ptrs[ NB_LTP_CBKS ];                            /*   3 */
 extern const opus_uint8  * const silk_LTP_gain_BITS_Q5_ptrs[ NB_LTP_CBKS ];                         /*   3 */
-extern const opus_int16  silk_LTP_gain_middle_avg_RD_Q14;
 extern const opus_int8   * const silk_LTP_vq_ptrs_Q7[ NB_LTP_CBKS ];                                /* 168 */
 extern const opus_uint8  * const silk_LTP_vq_gain_ptrs_Q7[NB_LTP_CBKS];
-
 extern const opus_int8   silk_LTP_vq_sizes[ NB_LTP_CBKS ];                                          /*   3 */
 
 extern const opus_uint8  silk_LTPscale_iCDF[ 3 ];                                                   /*   4 */
 extern const opus_int16  silk_LTPScales_table_Q14[ 3 ];                                             /*   6 */
 
 extern const opus_uint8  silk_type_offset_VAD_iCDF[ 4 ];                                            /*   4 */
 extern const opus_uint8  silk_type_offset_no_VAD_iCDF[ 2 ];                                         /*   2 */
 
--- a/media/libopus/silk/tables_LTP.c
+++ b/media/libopus/silk/tables_LTP.c
@@ -46,18 +46,16 @@ static const opus_uint8 silk_LTP_gain_iC
 
 static const opus_uint8 silk_LTP_gain_iCDF_2[32] = {
        241,    225,    211,    199,    187,    175,    164,    153,
        142,    132,    123,    114,    105,     96,     88,     80,
         72,     64,     57,     50,     44,     38,     33,     29,
         24,     20,     16,     12,      9,      5,      2,      0
 };
 
-const opus_int16 silk_LTP_gain_middle_avg_RD_Q14 = 12304;
-
 static const opus_uint8 silk_LTP_gain_BITS_Q5_0[8] = {
         15,    131,    138,    138,    155,    155,    173,    173
 };
 
 static const opus_uint8 silk_LTP_gain_BITS_Q5_1[16] = {
         69,     93,    115,    118,    131,    138,    141,    138,
        150,    150,    155,    150,    155,    160,    166,    160
 };
--- a/media/libopus/silk/tables_NLSF_CB_NB_MB.c
+++ b/media/libopus/silk/tables_NLSF_CB_NB_MB.c
@@ -69,16 +69,51 @@ static const opus_uint8 silk_NLSF_CB1_NB
         74,     99,    124,    151,    176,    198,    220,    237,
         33,     42,     61,     76,     93,    121,    155,    174,
        207,    225,     29,     53,     87,    112,    136,    154,
        170,    188,    208,    227,     24,     30,     52,     84,
        131,    150,    166,    186,    203,    229,     37,     48,
         64,     84,    104,    118,    156,    177,    201,    230
 };
 
+static const opus_int16 silk_NLSF_CB1_Wght_Q9[ 320 ] = {
+     2897, 2314, 2314, 2314, 2287, 2287, 2314, 2300, 2327, 2287,
+     2888, 2580, 2394, 2367, 2314, 2274, 2274, 2274, 2274, 2194,
+     2487, 2340, 2340, 2314, 2314, 2314, 2340, 2340, 2367, 2354,
+     3216, 2766, 2340, 2340, 2314, 2274, 2221, 2207, 2261, 2194,
+     2460, 2474, 2367, 2394, 2394, 2394, 2394, 2367, 2407, 2314,
+     3479, 3056, 2127, 2207, 2274, 2274, 2274, 2287, 2314, 2261,
+     3282, 3141, 2580, 2394, 2247, 2221, 2207, 2194, 2194, 2114,
+     4096, 3845, 2221, 2620, 2620, 2407, 2314, 2394, 2367, 2074,
+     3178, 3244, 2367, 2221, 2553, 2434, 2340, 2314, 2167, 2221,
+     3338, 3488, 2726, 2194, 2261, 2460, 2354, 2367, 2207, 2101,
+     2354, 2420, 2327, 2367, 2394, 2420, 2420, 2420, 2460, 2367,
+     3779, 3629, 2434, 2527, 2367, 2274, 2274, 2300, 2207, 2048,
+     3254, 3225, 2713, 2846, 2447, 2327, 2300, 2300, 2274, 2127,
+     3263, 3300, 2753, 2806, 2447, 2261, 2261, 2247, 2127, 2101,
+     2873, 2981, 2633, 2367, 2407, 2354, 2194, 2247, 2247, 2114,
+     3225, 3197, 2633, 2580, 2274, 2181, 2247, 2221, 2221, 2141,
+     3178, 3310, 2740, 2407, 2274, 2274, 2274, 2287, 2194, 2114,
+     3141, 3272, 2460, 2061, 2287, 2500, 2367, 2487, 2434, 2181,
+     3507, 3282, 2314, 2700, 2647, 2474, 2367, 2394, 2340, 2127,
+     3423, 3535, 3038, 3056, 2300, 1950, 2221, 2274, 2274, 2274,
+     3404, 3366, 2087, 2687, 2873, 2354, 2420, 2274, 2474, 2540,
+     3760, 3488, 1950, 2660, 2897, 2527, 2394, 2367, 2460, 2261,
+     3028, 3272, 2740, 2888, 2740, 2154, 2127, 2287, 2234, 2247,
+     3695, 3657, 2025, 1969, 2660, 2700, 2580, 2500, 2327, 2367,
+     3207, 3413, 2354, 2074, 2888, 2888, 2340, 2487, 2247, 2167,
+     3338, 3366, 2846, 2780, 2327, 2154, 2274, 2287, 2114, 2061,
+     2327, 2300, 2181, 2167, 2181, 2367, 2633, 2700, 2700, 2553,
+     2407, 2434, 2221, 2261, 2221, 2221, 2340, 2420, 2607, 2700,
+     3038, 3244, 2806, 2888, 2474, 2074, 2300, 2314, 2354, 2380,
+     2221, 2154, 2127, 2287, 2500, 2793, 2793, 2620, 2580, 2367,
+     3676, 3713, 2234, 1838, 2181, 2753, 2726, 2673, 2513, 2207,
+     2793, 3160, 2726, 2553, 2846, 2513, 2181, 2394, 2221, 2181
+};
+
 static const opus_uint8 silk_NLSF_CB1_iCDF_NB_MB[ 64 ] = {
        212,    178,    148,    129,    108,     96,     85,     82,
         79,     77,     61,     59,     57,     56,     51,     49,
         48,     45,     42,     41,     40,     38,     36,     34,
         31,     30,     21,     12,     10,      3,      1,      0,
        255,    245,    244,    236,    233,    225,    217,    203,
        190,    176,    175,    161,    149,    136,    125,    114,
        102,     91,     81,     71,     60,     52,     43,     35,
@@ -145,15 +180,16 @@ static const opus_int16 silk_NLSF_DELTA_
 
 const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB =
 {
     32,
     10,
     SILK_FIX_CONST( 0.18, 16 ),
     SILK_FIX_CONST( 1.0 / 0.18, 6 ),
     silk_NLSF_CB1_NB_MB_Q8,
+    silk_NLSF_CB1_Wght_Q9,
     silk_NLSF_CB1_iCDF_NB_MB,
     silk_NLSF_PRED_NB_MB_Q8,
     silk_NLSF_CB2_SELECT_NB_MB,
     silk_NLSF_CB2_iCDF_NB_MB,
     silk_NLSF_CB2_BITS_NB_MB_Q5,
     silk_NLSF_DELTA_MIN_NB_MB_Q15,
 };
--- a/media/libopus/silk/tables_NLSF_CB_WB.c
+++ b/media/libopus/silk/tables_NLSF_CB_WB.c
@@ -93,16 +93,51 @@ static const opus_uint8 silk_NLSF_CB1_WB
         18,     31,     52,     68,     88,    103,    117,    126,
        138,    149,    163,    177,    192,    207,    223,    239,
         16,     29,     47,     61,     76,     90,    106,    119,
        133,    147,    161,    176,    193,    209,    224,    240,
         15,     21,     35,     50,     61,     73,     86,     97,
        110,    119,    129,    141,    175,    198,    218,    237
 };
 
+static const opus_int16 silk_NLSF_CB1_Wght_Q9[ 512 ] = {
+     3657, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2925, 2963, 2963, 2925, 2846,
+     3216, 3085, 2972, 3056, 3056, 3010, 3010, 3010, 2963, 2963, 3010, 2972, 2888, 2846, 2846, 2726,
+     3920, 4014, 2981, 3207, 3207, 2934, 3056, 2846, 3122, 3244, 2925, 2846, 2620, 2553, 2780, 2925,
+     3516, 3197, 3010, 3103, 3019, 2888, 2925, 2925, 2925, 2925, 2888, 2888, 2888, 2888, 2888, 2753,
+     5054, 5054, 2934, 3573, 3385, 3056, 3085, 2793, 3160, 3160, 2972, 2846, 2513, 2540, 2753, 2888,
+     4428, 4149, 2700, 2753, 2972, 3010, 2925, 2846, 2981, 3019, 2925, 2925, 2925, 2925, 2888, 2726,
+     3620, 3019, 2972, 3056, 3056, 2873, 2806, 3056, 3216, 3047, 2981, 3291, 3291, 2981, 3310, 2991,
+     5227, 5014, 2540, 3338, 3526, 3385, 3197, 3094, 3376, 2981, 2700, 2647, 2687, 2793, 2846, 2673,
+     5081, 5174, 4615, 4428, 2460, 2897, 3047, 3207, 3169, 2687, 2740, 2888, 2846, 2793, 2846, 2700,
+     3122, 2888, 2963, 2925, 2925, 2925, 2925, 2963, 2963, 2963, 2963, 2925, 2925, 2963, 2963, 2963,
+     4202, 3207, 2981, 3103, 3010, 2888, 2888, 2925, 2972, 2873, 2916, 3019, 2972, 3010, 3197, 2873,
+     3760, 3760, 3244, 3103, 2981, 2888, 2925, 2888, 2972, 2934, 2793, 2793, 2846, 2888, 2888, 2660,
+     3854, 4014, 3207, 3122, 3244, 2934, 3047, 2963, 2963, 3085, 2846, 2793, 2793, 2793, 2793, 2580,
+     3845, 4080, 3357, 3516, 3094, 2740, 3010, 2934, 3122, 3085, 2846, 2846, 2647, 2647, 2846, 2806,
+     5147, 4894, 3225, 3845, 3441, 3169, 2897, 3413, 3451, 2700, 2580, 2673, 2740, 2846, 2806, 2753,
+     4109, 3789, 3291, 3160, 2925, 2888, 2888, 2925, 2793, 2740, 2793, 2740, 2793, 2846, 2888, 2806,
+     5081, 5054, 3047, 3545, 3244, 3056, 3085, 2944, 3103, 2897, 2740, 2740, 2740, 2846, 2793, 2620,
+     4309, 4309, 2860, 2527, 3207, 3376, 3376, 3075, 3075, 3376, 3056, 2846, 2647, 2580, 2726, 2753,
+     3056, 2916, 2806, 2888, 2740, 2687, 2897, 3103, 3150, 3150, 3216, 3169, 3056, 3010, 2963, 2846,
+     4375, 3882, 2925, 2888, 2846, 2888, 2846, 2846, 2888, 2888, 2888, 2846, 2888, 2925, 2888, 2846,
+     2981, 2916, 2916, 2981, 2981, 3056, 3122, 3216, 3150, 3056, 3010, 2972, 2972, 2972, 2925, 2740,
+     4229, 4149, 3310, 3347, 2925, 2963, 2888, 2981, 2981, 2846, 2793, 2740, 2846, 2846, 2846, 2793,
+     4080, 4014, 3103, 3010, 2925, 2925, 2925, 2888, 2925, 2925, 2846, 2846, 2846, 2793, 2888, 2780,
+     4615, 4575, 3169, 3441, 3207, 2981, 2897, 3038, 3122, 2740, 2687, 2687, 2687, 2740, 2793, 2700,
+     4149, 4269, 3789, 3657, 2726, 2780, 2888, 2888, 3010, 2972, 2925, 2846, 2687, 2687, 2793, 2888,
+     4215, 3554, 2753, 2846, 2846, 2888, 2888, 2888, 2925, 2925, 2888, 2925, 2925, 2925, 2963, 2888,
+     5174, 4921, 2261, 3432, 3789, 3479, 3347, 2846, 3310, 3479, 3150, 2897, 2460, 2487, 2753, 2925,
+     3451, 3685, 3122, 3197, 3357, 3047, 3207, 3207, 2981, 3216, 3085, 2925, 2925, 2687, 2540, 2434,
+     2981, 3010, 2793, 2793, 2740, 2793, 2846, 2972, 3056, 3103, 3150, 3150, 3150, 3103, 3010, 3010,
+     2944, 2873, 2687, 2726, 2780, 3010, 3432, 3545, 3357, 3244, 3056, 3010, 2963, 2925, 2888, 2846,
+     3019, 2944, 2897, 3010, 3010, 2972, 3019, 3103, 3056, 3056, 3010, 2888, 2846, 2925, 2925, 2888,
+     3920, 3967, 3010, 3197, 3357, 3216, 3291, 3291, 3479, 3704, 3441, 2726, 2181, 2460, 2580, 2607
+};
+
 static const opus_uint8 silk_NLSF_CB1_iCDF_WB[ 64 ] = {
        225,    204,    201,    184,    183,    175,    158,    154,
        153,    135,    119,    115,    113,    110,    109,     99,
         98,     95,     79,     68,     52,     50,     48,     45,
         43,     32,     31,     27,     18,     10,      3,      0,
        255,    251,    235,    230,    212,    201,    196,    182,
        167,    166,    163,    151,    138,    124,    110,    104,
         90,     78,     76,     70,     69,     57,     45,     34,
@@ -183,16 +218,17 @@ static const opus_int16 silk_NLSF_DELTA_
 
 const silk_NLSF_CB_struct silk_NLSF_CB_WB =
 {
     32,
     16,
     SILK_FIX_CONST( 0.15, 16 ),
     SILK_FIX_CONST( 1.0 / 0.15, 6 ),
     silk_NLSF_CB1_WB_Q8,
+    silk_NLSF_CB1_Wght_Q9,
     silk_NLSF_CB1_iCDF_WB,
     silk_NLSF_PRED_WB_Q8,
     silk_NLSF_CB2_SELECT_WB,
     silk_NLSF_CB2_iCDF_WB,
     silk_NLSF_CB2_BITS_WB_Q5,
     silk_NLSF_DELTA_MIN_WB_Q15,
 };
 
--- a/media/libopus/silk/tuning_parameters.h
+++ b/media/libopus/silk/tuning_parameters.h
@@ -48,29 +48,22 @@ extern "C"
 
 /*********************/
 /* Linear prediction */
 /*********************/
 
 /* LPC analysis regularization */
 #define FIND_LPC_COND_FAC                               1e-5f
 
-/* LTP analysis defines */
-#define FIND_LTP_COND_FAC                               1e-5f
-#define LTP_DAMPING                                     0.05f
-#define LTP_SMOOTHING                                   0.1f
-
-/* LTP quantization settings */
-#define MU_LTP_QUANT_NB                                 0.03f
-#define MU_LTP_QUANT_MB                                 0.025f
-#define MU_LTP_QUANT_WB                                 0.02f
-
 /* Max cumulative LTP gain */
 #define MAX_SUM_LOG_GAIN_DB                             250.0f
 
+/* LTP analysis defines */
+#define LTP_CORR_INV_MAX                                0.03f
+
 /***********************/
 /* High pass filtering */
 /***********************/
 
 /* Smoothing parameters for low end of pitch frequency range estimation */
 #define VARIABLE_HP_SMTH_COEF1                          0.1f
 #define VARIABLE_HP_SMTH_COEF2                          0.015f
 #define VARIABLE_HP_MAX_DELTA_FREQ                      0.4f
@@ -98,35 +91,26 @@ extern "C"
 
 /* factor for reducing quantization noise during voiced speech */
 #define HARM_SNR_INCR_dB                                2.0f
 
 /* factor for reducing quantization noise for unvoiced sparse signals */
 #define SPARSE_SNR_INCR_dB                              2.0f
 
 /* threshold for sparseness measure above which to use lower quantization offset during unvoiced */
-#define SPARSENESS_THRESHOLD_QNT_OFFSET                 0.75f
+#define ENERGY_VARIATION_THRESHOLD_QNT_OFFSET           0.6f
 
 /* warping control */
 #define WARPING_MULTIPLIER                              0.015f
 
 /* fraction added to first autocorrelation value */
-#define SHAPE_WHITE_NOISE_FRACTION                      5e-5f
+#define SHAPE_WHITE_NOISE_FRACTION                      3e-5f
 
 /* noise shaping filter chirp factor */
-#define BANDWIDTH_EXPANSION                             0.95f
-
-/* difference between chirp factors for analysis and synthesis noise shaping filters at low bitrates */
-#define LOW_RATE_BANDWIDTH_EXPANSION_DELTA              0.01f
-
-/* extra harmonic boosting (signal shaping) at low bitrates */
-#define LOW_RATE_HARMONIC_BOOST                         0.1f
-
-/* extra harmonic boosting (signal shaping) for noisy input signals */
-#define LOW_INPUT_QUALITY_HARMONIC_BOOST                0.1f
+#define BANDWIDTH_EXPANSION                             0.94f
 
 /* harmonic noise shaping */
 #define HARMONIC_SHAPING                                0.3f
 
 /* extra harmonic noise shaping for high bitrates or noisy input */
 #define HIGH_RATE_OR_LOW_QUALITY_HARMONIC_SHAPING       0.2f
 
 /* parameter for shaping noise towards higher frequencies */
--- a/media/libopus/silk/x86/NSQ_del_dec_sse.c
+++ b/media/libopus/silk/x86/NSQ_del_dec_sse.c
@@ -102,22 +102,22 @@ static OPUS_INLINE void silk_noise_shape
     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            *smpl_buf_idx,          /* I/O  Index to newest samples in buffers  */
     opus_int            decisionDelay           /* I                                        */
 );
 
 void silk_NSQ_del_dec_sse4_1(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
     const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
     const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
@@ -229,17 +229,18 @@ void silk_NSQ_del_dec_sse4_1(
                             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;
+                        last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
+                        if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
                         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_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
                         NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ];
                     }
 
                     subfr = 0;
                 }
@@ -280,31 +281,31 @@ void silk_NSQ_del_dec_sse4_1(
     }
 
     /* 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;
     Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
     for( i = 0; i < decisionDelay; i++ ) {
-        last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
+        last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
+        if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
         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_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
         NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ 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_Q14 = psDD->LF_AR_Q14;
     NSQ->lagPrev        = pitchL[ psEncC->nb_subfr - 1 ];
 
     /* Save quantized speech signal */
-    /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[psEncC->ltp_mem_length], psEncC->frame_length * sizeof( opus_int16 ) ) */
     silk_memmove( NSQ->xq,           &NSQ->xq[           psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
     silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
     RESTORE_STACK;
 }
 
 /******************************************/
 /* Noise shape quantizer for one subframe */
 /******************************************/
@@ -328,17 +329,17 @@ static OPUS_INLINE void silk_noise_shape
     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            *smpl_buf_idx,          /* I/O  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_Q14, n_AR_Q14, n_LTP_Q14;
     opus_int32   n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
     opus_int32   q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
@@ -633,18 +634,19 @@ static OPUS_INLINE void silk_noise_shape
                 /* Update states */
                 sLF_AR_shp_Q14         = silk_SUB32( xq_Q14, n_AR_Q14 );
                 psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
                 psSS[ 1 ].LF_AR_Q14    = sLF_AR_shp_Q14;
                 psSS[ 1 ].LPC_exc_Q14  = LPC_exc_Q14;
                 psSS[ 1 ].xq_Q14       = xq_Q14;
             }
         }
-        *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   */
+        *smpl_buf_idx  = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
+        if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
+        last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
 
         /* 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;
--- a/media/libopus/silk/x86/NSQ_sse.c
+++ b/media/libopus/silk/x86/NSQ_sse.c
@@ -66,17 +66,17 @@ static OPUS_INLINE void silk_noise_shape
     opus_int32          LF_shp_Q14,             /* I                                    */
     opus_int32          Gain_Q16,               /* I                                    */
     opus_int            offset_Q10,             /* I                                    */
     opus_int            length,                 /* I    Input length                    */
     opus_int32          table[][4]              /* I                                    */
 );
 
 void silk_NSQ_sse4_1(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
     const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
     const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
@@ -228,17 +228,16 @@ void silk_NSQ_sse4_1(
         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 */
-    /* DEBUG_STORE_DATA( enc.pcm, &NSQ->xq[ psEncC->ltp_mem_length ], psEncC->frame_length * sizeof( opus_int16 ) ) */
     silk_memmove( NSQ->xq,           &NSQ->xq[           psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
     silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
     RESTORE_STACK;
 }
 
 /***********************************/
 /* silk_noise_shape_quantizer_10_16  */
 /***********************************/
--- a/media/libopus/silk/x86/main_sse.h
+++ b/media/libopus/silk/x86/main_sse.h
@@ -29,16 +29,17 @@
 #define MAIN_SSE_H
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 # if defined(OPUS_X86_MAY_HAVE_SSE4_1)
 
+#if 0 /* FIXME: SSE disabled until silk_VQ_WMat_EC_sse4_1() gets updated. */
 #  define OVERRIDE_silk_VQ_WMat_EC
 
 void silk_VQ_WMat_EC_sse4_1(
     opus_int8                   *ind,                           /* O    index of best codebook vector               */
     opus_int32                  *rate_dist_Q14,                 /* O    best weighted quant error + mu * rate       */
     opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
     const opus_int16            *in_Q14,                        /* I    input vector to be quantized                */
     const opus_int32            *W_Q18,                         /* I    weighting matrix                            */
@@ -74,21 +75,23 @@ extern void (*const SILK_VQ_WMAT_EC_IMPL
 );
 
 #  define silk_VQ_WMat_EC(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
                           mu_Q9, max_gain_Q7, L, arch) \
     ((*SILK_VQ_WMAT_EC_IMPL[(arch) & OPUS_ARCHMASK])(ind, rate_dist_Q14, gain_Q7, in_Q14, W_Q18, cb_Q7, cb_gain_Q7, cl_Q5, \
                           mu_Q9, max_gain_Q7, L))
 
 #endif
+#endif
 
+#if 0 /* FIXME: SSE disabled until the NSQ code gets updated. */
 #  define OVERRIDE_silk_NSQ
 
 void silk_NSQ_sse4_1(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
     const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
     const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
@@ -105,17 +108,17 @@ void silk_NSQ_sse4_1(
 #define silk_NSQ(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
     ((void)(arch),silk_NSQ_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
 
 #else
 
 extern void (*const SILK_NSQ_IMPL[OPUS_ARCHMASK + 1])(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
     const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
     const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
@@ -132,17 +135,17 @@ extern void (*const SILK_NSQ_IMPL[OPUS_A
     ((*SILK_NSQ_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
                    HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
 
 #endif
 
 #  define OVERRIDE_silk_NSQ_del_dec
 
 void silk_NSQ_del_dec_sse4_1(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
     const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
     const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
@@ -159,17 +162,17 @@ void silk_NSQ_del_dec_sse4_1(
 #define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
     ((void)(arch),silk_NSQ_del_dec_sse4_1(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
 
 #else
 
 extern void (*const SILK_NSQ_DEL_DEC_IMPL[OPUS_ARCHMASK + 1])(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
     const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
     const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
@@ -182,16 +185,17 @@ extern void (*const SILK_NSQ_DEL_DEC_IMP
 );
 
 #  define silk_NSQ_del_dec(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14, arch) \
     ((*SILK_NSQ_DEL_DEC_IMPL[(arch) & OPUS_ARCHMASK])(psEncC, NSQ, psIndices, x_Q3, pulses, PredCoef_Q12, LTPCoef_Q14, AR2_Q13, \
                            HarmShapeGain_Q14, Tilt_Q14, LF_shp_Q14, Gains_Q16, pitchL, Lambda_Q10, LTP_scale_Q14))
 
 #endif
+#endif
 
 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_Q15[],             /* I/O  LTP state                       */
@@ -233,45 +237,12 @@ opus_int silk_VAD_GetSA_Q8_sse4_1(
 
 #  define silk_VAD_GetSA_Q8(psEnC, pIn, arch) \
      ((*SILK_VAD_GETSA_Q8_IMPL[(arch) & OPUS_ARCHMASK])(psEnC, pIn))
 
 extern opus_int (*const SILK_VAD_GETSA_Q8_IMPL[OPUS_ARCHMASK + 1])(
      silk_encoder_state *psEnC,
      const opus_int16   pIn[]);
 
-#  define OVERRIDE_silk_warped_LPC_analysis_filter_FIX
-
-#endif
-
-void silk_warped_LPC_analysis_filter_FIX_sse4_1(
-          opus_int32            state[],                    /* I/O  State [order + 1]                   */
-          opus_int32            res_Q2[],                   /* O    Residual signal [length]            */
-    const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
-    const opus_int16            input[],                    /* I    Input signal [length]               */
-    const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
-    const opus_int              length,                     /* I    Length of input signal              */
-    const opus_int              order                       /* I    Filter order (even)                 */
-);
-
-#if defined(OPUS_X86_PRESUME_SSE4_1)
-#define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
-    ((void)(arch),silk_warped_LPC_analysis_filter_FIX_c(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
-
-#else
-
-extern void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[OPUS_ARCHMASK + 1])(
-          opus_int32            state[],                    /* I/O  State [order + 1]                   */
-          opus_int32            res_Q2[],                   /* O    Residual signal [length]            */
-    const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
-    const opus_int16            input[],                    /* I    Input signal [length]               */
-    const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
-    const opus_int              length,                     /* I    Length of input signal              */
-    const opus_int              order                       /* I    Filter order (even)                 */
-);
-
-#  define silk_warped_LPC_analysis_filter_FIX(state, res_Q2, coef_Q13, input, lambda_Q16, length, order, arch) \
-    ((*SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[(arch) & OPUS_ARCHMASK])(state, res_Q2, coef_Q13, input, lambda_Q16, length, order))
-
 #endif
 
 # endif
 #endif
--- a/media/libopus/silk/x86/x86_silk_map.c
+++ b/media/libopus/silk/x86/x86_silk_map.c
@@ -61,18 +61,19 @@ opus_int (*const SILK_VAD_GETSA_Q8_IMPL[
 ) = {
   silk_VAD_GetSA_Q8_c,                  /* non-sse */
   silk_VAD_GetSA_Q8_c,
   silk_VAD_GetSA_Q8_c,
   MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 ), /* sse4.1 */
   MAY_HAVE_SSE4_1( silk_VAD_GetSA_Q8 )  /* avx */
 };
 
+#if 0 /* FIXME: SSE disabled until the NSQ code gets updated. */
 void (*const SILK_NSQ_IMPL[ OPUS_ARCHMASK + 1 ] )(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
     const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
     const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
@@ -84,17 +85,19 @@ void (*const SILK_NSQ_IMPL[ OPUS_ARCHMAS
     const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
 ) = {
   silk_NSQ_c,                  /* non-sse */
   silk_NSQ_c,
   silk_NSQ_c,
   MAY_HAVE_SSE4_1( silk_NSQ ), /* sse4.1 */
   MAY_HAVE_SSE4_1( silk_NSQ )  /* avx */
 };
+#endif
 
+#if 0 /* FIXME: SSE disabled until silk_VQ_WMat_EC_sse4_1() gets updated. */
 void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_ARCHMASK + 1 ] )(
     opus_int8                   *ind,                           /* O    index of best codebook vector               */
     opus_int32                  *rate_dist_Q14,                 /* O    best weighted quant error + mu * rate       */
     opus_int                    *gain_Q7,                       /* O    sum of absolute LTP coefficients            */
     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            *cb_gain_Q7,                    /* I    codebook effective gain                     */
@@ -104,19 +107,21 @@ void (*const SILK_VQ_WMAT_EC_IMPL[ OPUS_
     opus_int                    L                               /* I    number of vectors in codebook               */
 ) = {
   silk_VQ_WMat_EC_c,                  /* non-sse */
   silk_VQ_WMat_EC_c,
   silk_VQ_WMat_EC_c,
   MAY_HAVE_SSE4_1( silk_VQ_WMat_EC ), /* sse4.1 */
   MAY_HAVE_SSE4_1( silk_VQ_WMat_EC )  /* avx */
 };
+#endif
 
+#if 0 /* FIXME: SSE disabled until the NSQ code gets updated. */
 void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS_ARCHMASK + 1 ] )(
-    const silk_encoder_state    *psEncC,                                    /* I/O  Encoder State                   */
+    const silk_encoder_state    *psEncC,                                    /* I    Encoder State                   */
     silk_nsq_state              *NSQ,                                       /* I/O  NSQ state                       */
     SideInfoIndices             *psIndices,                                 /* I/O  Quantization Indices            */
     const opus_int32            x_Q3[],                                     /* I    Prefiltered input signal        */
     opus_int8                   pulses[],                                   /* O    Quantized pulse signal          */
     const opus_int16            PredCoef_Q12[ 2 * MAX_LPC_ORDER ],          /* I    Short term prediction coefs     */
     const opus_int16            LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ],    /* I    Long term prediction coefs      */
     const opus_int16            AR2_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs             */
     const opus_int              HarmShapeGain_Q14[ MAX_NB_SUBFR ],          /* I    Long term shaping coefs         */
@@ -128,35 +133,20 @@ void (*const SILK_NSQ_DEL_DEC_IMPL[ OPUS
     const opus_int              LTP_scale_Q14                               /* I    LTP state scaling               */
 ) = {
   silk_NSQ_del_dec_c,                  /* non-sse */
   silk_NSQ_del_dec_c,
   silk_NSQ_del_dec_c,
   MAY_HAVE_SSE4_1( silk_NSQ_del_dec ), /* sse4.1 */
   MAY_HAVE_SSE4_1( silk_NSQ_del_dec )  /* avx */
 };
+#endif
 
 #if defined(FIXED_POINT)
 
-void (*const SILK_WARPED_LPC_ANALYSIS_FILTER_FIX_IMPL[ OPUS_ARCHMASK + 1 ] )(
-    opus_int32                  state[],                    /* I/O  State [order + 1]                   */
-    opus_int32                  res_Q2[],                   /* O    Residual signal [length]            */
-    const opus_int16            coef_Q13[],                 /* I    Coefficients [order]                */
-    const opus_int16            input[],                    /* I    Input signal [length]               */
-    const opus_int16            lambda_Q16,                 /* I    Warping factor                      */
-    const opus_int              length,                     /* I    Length of input signal              */
-    const opus_int              order                       /* I    Filter order (even)                 */
-) = {
-  silk_warped_LPC_analysis_filter_FIX_c,                  /* non-sse */
-  silk_warped_LPC_analysis_filter_FIX_c,
-  silk_warped_LPC_analysis_filter_FIX_c,
-  MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX ), /* sse4.1 */
-  MAY_HAVE_SSE4_1( silk_warped_LPC_analysis_filter_FIX )  /* avx */
-};
-
 void (*const SILK_BURG_MODIFIED_IMPL[ OPUS_ARCHMASK + 1 ] )(
     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_int32            minInvGain_Q30,     /* I    Inverse of max prediction gain                              */
     const opus_int              subfr_length,       /* I    Input signal subframe length (incl. D preceding samples)    */
     const opus_int              nb_subfr,           /* I    Number of subframes stacked in x                            */
--- a/media/libopus/sources.mozbuild
+++ b/media/libopus/sources.mozbuild
@@ -30,16 +30,17 @@ opus_nonunified_sources = [
 celt_sources_sse = [
     'celt/x86/pitch_sse.c',
     'celt/x86/x86_celt_map.c',
     'celt/x86/x86cpu.c',
 ]
 
 celt_sources_sse2 = [
     'celt/x86/pitch_sse2.c',
+    'celt/x86/vq_sse2.c',
 ]
 
 celt_sources_sse4_1 = [
     'celt/x86/celt_lpc_sse.c',
     'celt/x86/pitch_sse4_1.c',
 ]
 
 celt_sources_arm = [
@@ -54,16 +55,17 @@ celt_sources_arm_asm = [
 celt_am_sources_arm_asm = [
     'celt/arm/armopts.s.in',
 ]
 
 celt_sources_arm_neon_intr = [
     'celt/arm/celt_ne10_fft.c',
     'celt/arm/celt_ne10_mdct.c',
     'celt/arm/celt_neon_intr.c',
+    'celt/arm/pitch_neon_intr.c',
     'CELT_SOURCES_ARM_NE10=',
 ]
 
 opus_sources = [
     'src/opus.c',
     'src/opus_decoder.c',
     'src/opus_encoder.c',
     'src/opus_multistream.c',
@@ -107,16 +109,17 @@ silk_sources = [
     'silk/init_decoder.c',
     'silk/init_encoder.c',
     'silk/inner_prod_aligned.c',
     'silk/interpolate.c',
     'silk/lin2log.c',
     'silk/log2lin.c',
     'silk/LP_variable_cutoff.c',
     'silk/LPC_analysis_filter.c',
+    'silk/LPC_fit.c',
     'silk/NLSF_decode.c',
     'silk/NLSF_del_dec_quant.c',
     'silk/NLSF_encode.c',
     'silk/NLSF_stabilize.c',
     'silk/NLSF_unpack.c',
     'silk/NLSF_VQ.c',
     'silk/NLSF_VQ_weights_laroia.c',
     'silk/NSQ.c',
@@ -160,16 +163,19 @@ silk_sources_sse4_1 = [
     'silk/x86/NSQ_sse.c',
     'silk/x86/VAD_sse.c',
     'silk/x86/VQ_WMat_EC_sse.c',
     'silk/x86/x86_silk_map.c',
 ]
 
 silk_sources_arm_neon_intr = [
     'silk/arm/arm_silk_map.c',
+    'silk/arm/biquad_alt_neon_intr.c',
+    'silk/arm/LPC_inv_pred_gain_neon_intr.c',
+    'silk/arm/NSQ_del_dec_neon_intr.c',
     'silk/arm/NSQ_neon.c',
 ]
 
 silk_sources_fixed = [
     'silk/fixed/apply_sine_window_FIX.c',
     'silk/fixed/autocorr_FIX.c',
     'silk/fixed/burg_modified_FIX.c',
     'silk/fixed/corrMatrix_FIX.c',
@@ -179,60 +185,58 @@ silk_sources_fixed = [
     'silk/fixed/find_pitch_lags_FIX.c',
     'silk/fixed/find_pred_coefs_FIX.c',
     'silk/fixed/k2a_FIX.c',
     'silk/fixed/k2a_Q16_FIX.c',
     'silk/fixed/LTP_analysis_filter_FIX.c',
     'silk/fixed/LTP_scale_ctrl_FIX.c',
     'silk/fixed/noise_shape_analysis_FIX.c',
     'silk/fixed/pitch_analysis_core_FIX.c',
-    'silk/fixed/prefilter_FIX.c',
     'silk/fixed/process_gains_FIX.c',
     'silk/fixed/regularize_correlations_FIX.c',
     'silk/fixed/residual_energy16_FIX.c',
     'silk/fixed/residual_energy_FIX.c',
     'silk/fixed/schur64_FIX.c',
     'silk/fixed/schur_FIX.c',
-    'silk/fixed/solve_LS_FIX.c',
     'silk/fixed/vector_ops_FIX.c',
     'silk/fixed/warped_autocorrelation_FIX.c',
 ]
 
 silk_sources_fixed_sse4_1 = [
     'silk/fixed/x86/burg_modified_FIX_sse.c',
-    'silk/fixed/x86/prefilter_FIX_sse.c',
     'silk/fixed/x86/vector_ops_FIX_sse.c',
 ]
 
+silk_sources_fixed_arm_neon_intr = [
+    'silk/fixed/arm/warped_autocorrelation_FIX_neon_intr.c',
+]
+
 silk_sources_float = [
     'silk/float/apply_sine_window_FLP.c',
     'silk/float/autocorrelation_FLP.c',
     'silk/float/burg_modified_FLP.c',
     'silk/float/bwexpander_FLP.c',
     'silk/float/corrMatrix_FLP.c',
     'silk/float/encode_frame_FLP.c',
     'silk/float/energy_FLP.c',
     'silk/float/find_LPC_FLP.c',
     'silk/float/find_LTP_FLP.c',
     'silk/float/find_pitch_lags_FLP.c',
     'silk/float/find_pred_coefs_FLP.c',
     'silk/float/inner_product_FLP.c',
     'silk/float/k2a_FLP.c',
-    'silk/float/levinsondurbin_FLP.c',
     'silk/float/LPC_analysis_filter_FLP.c',
     'silk/float/LPC_inv_pred_gain_FLP.c',
     'silk/float/LTP_analysis_filter_FLP.c',
     'silk/float/LTP_scale_ctrl_FLP.c',
     'silk/float/noise_shape_analysis_FLP.c',
     'silk/float/pitch_analysis_core_FLP.c',
-    'silk/float/prefilter_FLP.c',
     'silk/float/process_gains_FLP.c',
     'silk/float/regularize_correlations_FLP.c',
     'silk/float/residual_energy_FLP.c',
     'silk/float/scale_copy_vector_FLP.c',
     'silk/float/scale_vector_FLP.c',
     'silk/float/schur_FLP.c',
-    'silk/float/solve_LS_FLP.c',
     'silk/float/sort_FLP.c',
     'silk/float/warped_autocorrelation_FLP.c',
     'silk/float/wrappers_FLP.c',
 ]
 
--- a/media/libopus/src/analysis.c
+++ b/media/libopus/src/analysis.c
@@ -24,30 +24,37 @@
    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
 
+#define ANALYSIS_C
+
+#include <stdio.h>
+
+#include "mathops.h"
 #include "kiss_fft.h"
 #include "celt.h"
 #include "modes.h"
 #include "arch.h"
 #include "quant_bands.h"
-#include <stdio.h>
 #include "analysis.h"
 #include "mlp.h"
 #include "stack_alloc.h"
+#include "float_cast.h"
 
 #ifndef M_PI
 #define M_PI 3.141592653
 #endif
 
+#ifndef DISABLE_FLOAT_API
+
 static const float dct_table[128] = {
         0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
         0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
         0.351851f, 0.338330f, 0.311806f, 0.273300f, 0.224292f, 0.166664f, 0.102631f, 0.034654f,
        -0.034654f,-0.102631f,-0.166664f,-0.224292f,-0.273300f,-0.311806f,-0.338330f,-0.351851f,
         0.346760f, 0.293969f, 0.196424f, 0.068975f,-0.068975f,-0.196424f,-0.293969f,-0.346760f,
        -0.346760f,-0.293969f,-0.196424f,-0.068975f, 0.068975f, 0.196424f, 0.293969f, 0.346760f,
         0.338330f, 0.224292f, 0.034654f,-0.166664f,-0.311806f,-0.351851f,-0.273300f,-0.102631f,
@@ -91,122 +98,217 @@ static const float analysis_window[240] 
       0.936248f, 0.939409f, 0.942494f, 0.945503f, 0.948436f, 0.951293f, 0.954072f, 0.956773f,
       0.959396f, 0.961940f, 0.964405f, 0.966790f, 0.969096f, 0.971321f, 0.973465f, 0.975528f,
       0.977510f, 0.979410f, 0.981228f, 0.982963f, 0.984615f, 0.986185f, 0.987671f, 0.989074f,
       0.990393f, 0.991627f, 0.992778f, 0.993844f, 0.994826f, 0.995722f, 0.996534f, 0.997261f,
       0.997902f, 0.998459f, 0.998929f, 0.999315f, 0.999615f, 0.999829f, 0.999957f, 1.000000f,
 };
 
 static const int tbands[NB_TBANDS+1] = {
-       2,  4,  6,  8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120
+      4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 136, 160, 192, 240
 };
 
-static const int extra_bands[NB_TOT_BANDS+1] = {
-      1, 2,  4,  6,  8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120, 160, 200
-};
-
-/*static const float tweight[NB_TBANDS+1] = {
-      .3, .4, .5, .6, .7, .8, .9, 1., 1., 1., 1., 1., 1., 1., .8, .7, .6, .5
-};*/
-
 #define NB_TONAL_SKIP_BANDS 9
 
-#define cA 0.43157974f
-#define cB 0.67848403f
-#define cC 0.08595542f
-#define cE ((float)M_PI/2)
-static OPUS_INLINE float fast_atan2f(float y, float x) {
-   float x2, y2;
-   /* Should avoid underflow on the values we'll get */
-   if (ABS16(x)+ABS16(y)<1e-9f)
-   {
-      x*=1e12f;
-      y*=1e12f;
-   }
-   x2 = x*x;
-   y2 = y*y;
-   if(x2<y2){
-      float den = (y2 + cB*x2) * (y2 + cC*x2);
-      if (den!=0)
-         return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
-      else
-         return (y<0 ? -cE : cE);
-   }else{
-      float den = (x2 + cB*y2) * (x2 + cC*y2);
-      if (den!=0)
-         return  x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
-      else
-         return (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
-   }
+static opus_val32 silk_resampler_down2_hp(
+    opus_val32                  *S,                 /* I/O  State vector [ 2 ]                                          */
+    opus_val32                  *out,               /* O    Output signal [ floor(len/2) ]                              */
+    const opus_val32            *in,                /* I    Input signal [ len ]                                        */
+    int                         inLen               /* I    Number of input samples                                     */
+)
+{
+    int k, len2 = inLen/2;
+    opus_val32 in32, out32, out32_hp, Y, X;
+    opus_val64 hp_ener = 0;
+    /* Internal variables and state are in Q10 format */
+    for( k = 0; k < len2; k++ ) {
+        /* Convert to Q10 */
+        in32 = in[ 2 * k ];
+
+        /* All-pass section for even input sample */
+        Y      = SUB32( in32, S[ 0 ] );
+        X      = MULT16_32_Q15(QCONST16(0.6074371f, 15), Y);
+        out32  = ADD32( S[ 0 ], X );
+        S[ 0 ] = ADD32( in32, X );
+        out32_hp = out32;
+        /* Convert to Q10 */
+        in32 = in[ 2 * k + 1 ];
+
+        /* All-pass section for odd input sample, and add to output of previous section */
+        Y      = SUB32( in32, S[ 1 ] );
+        X      = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
+        out32  = ADD32( out32, S[ 1 ] );
+        out32  = ADD32( out32, X );
+        S[ 1 ] = ADD32( in32, X );
+
+        Y      = SUB32( -in32, S[ 2 ] );
+        X      = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
+        out32_hp  = ADD32( out32_hp, S[ 2 ] );
+        out32_hp  = ADD32( out32_hp, X );
+        S[ 2 ] = ADD32( -in32, X );
+
+        hp_ener += out32_hp*(opus_val64)out32_hp;
+        /* Add, convert back to int16 and store to output */
+        out[ k ] = HALF32(out32);
+    }
+#ifdef FIXED_POINT
+    /* len2 can be up to 480, so we shift by 8 more to make it fit. */
+    hp_ener = hp_ener >> (2*SIG_SHIFT + 8);
+#endif
+    return (opus_val32)hp_ener;
 }
 
-void tonality_analysis_init(TonalityAnalysisState *tonal)
+static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opus_val32 *y, opus_val32 S[3], int subframe, int offset, int c1, int c2, int C, int Fs)
+{
+   VARDECL(opus_val32, tmp);
+   opus_val32 scale;
+   int j;
+   opus_val32 ret = 0;
+   SAVE_STACK;
+
+   if (subframe==0) return 0;
+   if (Fs == 48000)
+   {
+      subframe *= 2;
+      offset *= 2;
+   } else if (Fs == 16000) {
+      subframe = subframe*2/3;
+      offset = offset*2/3;
+   }
+   ALLOC(tmp, subframe, opus_val32);
+
+   downmix(_x, tmp, subframe, offset, c1, c2, C);
+#ifdef FIXED_POINT
+   scale = (1<<SIG_SHIFT);
+#else
+   scale = 1.f/32768;
+#endif
+   if (c2==-2)
+      scale /= C;
+   else if (c2>-1)
+      scale /= 2;
+   for (j=0;j<subframe;j++)
+      tmp[j] *= scale;
+   if (Fs == 48000)
+   {
+      ret = silk_resampler_down2_hp(S, y, tmp, subframe);
+   } else if (Fs == 24000) {
+      OPUS_COPY(y, tmp, subframe);
+   } else if (Fs == 16000) {
+      VARDECL(opus_val32, tmp3x);
+      ALLOC(tmp3x, 3*subframe, opus_val32);
+      /* Don't do this at home! This resampler is horrible and it's only (barely)
+         usable for the purpose of the analysis because we don't care about all
+         the aliasing between 8 kHz and 12 kHz. */
+      for (j=0;j<subframe;j++)
+      {
+         tmp3x[3*j] = tmp[j];
+         tmp3x[3*j+1] = tmp[j];
+         tmp3x[3*j+2] = tmp[j];
+      }
+      silk_resampler_down2_hp(S, y, tmp3x, 3*subframe);
+   }
+   RESTORE_STACK;
+   return ret;
+}
+
+void tonality_analysis_init(TonalityAnalysisState *tonal, opus_int32 Fs)
 {
   /* Initialize reusable fields. */
   tonal->arch = opus_select_arch();
+  tonal->Fs = Fs;
   /* Clear remaining fields. */
   tonality_analysis_reset(tonal);
 }
 
 void tonality_analysis_reset(TonalityAnalysisState *tonal)
 {
   /* Clear non-reusable fields. */
   char *start = (char*)&tonal->TONALITY_ANALYSIS_RESET_START;
   OPUS_CLEAR(start, sizeof(TonalityAnalysisState) - (start - (char*)tonal));
+  tonal->music_confidence = .9f;
+  tonal->speech_confidence = .1f;
 }
 
 void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len)
 {
    int pos;
    int curr_lookahead;
    float psum;
    int i;
 
    pos = tonal->read_pos;
    curr_lookahead = tonal->write_pos-tonal->read_pos;
    if (curr_lookahead<0)
       curr_lookahead += DETECT_SIZE;
 
-   if (len > 480 && pos != tonal->write_pos)
+   /* On long frames, look at the second analysis window rather than the first. */
+   if (len > tonal->Fs/50 && pos != tonal->write_pos)
    {
       pos++;
       if (pos==DETECT_SIZE)
          pos=0;
    }
    if (pos == tonal->write_pos)
       pos--;
    if (pos<0)
       pos = DETECT_SIZE-1;
    OPUS_COPY(info_out, &tonal->info[pos], 1);
-   tonal->read_subframe += len/120;
-   while (tonal->read_subframe>=4)
+   /* If possible, look ahead for a tone to compensate for the delay in the tone detector. */
+   for (i=0;i<3;i++)
    {
-      tonal->read_subframe -= 4;
+      pos++;
+      if (pos==DETECT_SIZE)
+         pos = 0;
+      if (pos == tonal->write_pos)
+         break;
+      info_out->tonality = MAX32(0, -.03f + MAX32(info_out->tonality, tonal->info[pos].tonality-.05f));
+   }
+   tonal->read_subframe += len/(tonal->Fs/400);
+   while (tonal->read_subframe>=8)
+   {
+      tonal->read_subframe -= 8;
       tonal->read_pos++;
    }
    if (tonal->read_pos>=DETECT_SIZE)
       tonal->read_pos-=DETECT_SIZE;
 
-   /* Compensate for the delay in the features themselves.
-      FIXME: Need a better estimate the 10 I just made up */
-   curr_lookahead = IMAX(curr_lookahead-10, 0);
+   /* The -1 is to compensate for the delay in the features themselves. */
+   curr_lookahead = IMAX(curr_lookahead-1, 0);
 
    psum=0;
    /* Summing the probability of transition patterns that involve music at
       time (DETECT_SIZE-curr_lookahead-1) */
    for (i=0;i<DETECT_SIZE-curr_lookahead;i++)
       psum += tonal->pmusic[i];
    for (;i<DETECT_SIZE;i++)
       psum += tonal->pspeech[i];
    psum = psum*tonal->music_confidence + (1-psum)*tonal->speech_confidence;
-   /*printf("%f %f %f\n", psum, info_out->music_prob, info_out->tonality);*/
+   /*printf("%f %f %f %f %f\n", psum, info_out->music_prob, info_out->vad_prob, info_out->activity_probability, info_out->tonality);*/
 
    info_out->music_prob = psum;
 }
 
+static const float std_feature_bias[9] = {
+      5.684947f, 3.475288f, 1.770634f, 1.599784f, 3.773215f,
+      2.163313f, 1.260756f, 1.116868f, 1.918795f
+};
+
+#define LEAKAGE_OFFSET 2.5f
+#define LEAKAGE_SLOPE 2.f
+
+#ifdef FIXED_POINT
+/* For fixed-point, the input is +/-2^15 shifted up by SIG_SHIFT, so we need to
+   compensate for that in the energy. */
+#define SCALE_COMPENS (1.f/((opus_int32)1<<(15+SIG_SHIFT)))
+#define SCALE_ENER(e) ((SCALE_COMPENS*SCALE_COMPENS)*(e))
+#else
+#define SCALE_ENER(e) (e)
+#endif
+
 static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix)
 {
     int i, b;
     const kiss_fft_state *kfft;
     VARDECL(kiss_fft_cpx, in);
     VARDECL(kiss_fft_cpx, out);
     int N = 480, N2=240;
     float * OPUS_RESTRICT A = tonal->angle;
@@ -230,36 +332,59 @@ static void tonality_analysis(TonalityAn
     float alpha, alphaE, alphaE2;
     float frame_loudness;
     float bandwidth_mask;
     int bandwidth=0;
     float maxE = 0;
     float noise_floor;
     int remaining;
     AnalysisInfo *info;
+    float hp_ener;
+    float tonality2[240];
+    float midE[8];
+    float spec_variability=0;
+    float band_log2[NB_TBANDS+1];
+    float leakage_from[NB_TBANDS+1];
+    float leakage_to[NB_TBANDS+1];
     SAVE_STACK;
 
-    tonal->last_transition++;
-    alpha = 1.f/IMIN(20, 1+tonal->count);
-    alphaE = 1.f/IMIN(50, 1+tonal->count);
-    alphaE2 = 1.f/IMIN(1000, 1+tonal->count);
+    alpha = 1.f/IMIN(10, 1+tonal->count);
+    alphaE = 1.f/IMIN(25, 1+tonal->count);
+    alphaE2 = 1.f/IMIN(500, 1+tonal->count);
 
-    if (tonal->count<4)
-       tonal->music_prob = .5;
+    if (tonal->Fs == 48000)
+    {
+       /* len and offset are now at 24 kHz. */
+       len/= 2;
+       offset /= 2;
+    } else if (tonal->Fs == 16000) {
+       len = 3*len/2;
+       offset = 3*offset/2;
+    }
+
+    if (tonal->count<4) {
+       if (tonal->application == OPUS_APPLICATION_VOIP)
+          tonal->music_prob = .1;
+       else
+          tonal->music_prob = .625;
+    }
     kfft = celt_mode->mdct.kfft[0];
     if (tonal->count==0)
        tonal->mem_fill = 240;
-    downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C);
+    tonal->hp_ener_accum += (float)downmix_and_resample(downmix, x,
+          &tonal->inmem[tonal->mem_fill], tonal->downmix_state,
+          IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C, tonal->Fs);
     if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE)
     {
        tonal->mem_fill += len;
        /* Don't have enough to update the analysis */
        RESTORE_STACK;
        return;
     }
+    hp_ener = tonal->hp_ener_accum;
     info = &tonal->info[tonal->write_pos++];
     if (tonal->write_pos>=DETECT_SIZE)
        tonal->write_pos-=DETECT_SIZE;
 
     ALLOC(in, 480, kiss_fft_cpx);
     ALLOC(out, 480, kiss_fft_cpx);
     ALLOC(tonality, 240, float);
     ALLOC(noisiness, 240, float);
@@ -268,17 +393,19 @@ static void tonality_analysis(TonalityAn
        float w = analysis_window[i];
        in[i].r = (kiss_fft_scalar)(w*tonal->inmem[i]);
        in[i].i = (kiss_fft_scalar)(w*tonal->inmem[N2+i]);
        in[N-i-1].r = (kiss_fft_scalar)(w*tonal->inmem[N-i-1]);
        in[N-i-1].i = (kiss_fft_scalar)(w*tonal->inmem[N+N2-i-1]);
     }
     OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240);
     remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill);
-    downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C);
+    tonal->hp_ener_accum = (float)downmix_and_resample(downmix, x,
+          &tonal->inmem[240], tonal->downmix_state, remaining,
+          offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C, tonal->Fs);
     tonal->mem_fill = 240 + remaining;
     opus_fft(kfft, in, out, tonal->arch);
 #ifndef FIXED_POINT
     /* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */
     if (celt_isnan(out[0].r))
     {
        info->valid = 0;
        RESTORE_STACK;
@@ -300,65 +427,85 @@ static void tonality_analysis(TonalityAn
        angle = (float)(.5f/M_PI)*fast_atan2f(X1i, X1r);
        d_angle = angle - A[i];
        d2_angle = d_angle - dA[i];
 
        angle2 = (float)(.5f/M_PI)*fast_atan2f(X2i, X2r);
        d_angle2 = angle2 - angle;
        d2_angle2 = d_angle2 - d_angle;
 
-       mod1 = d2_angle - (float)floor(.5+d2_angle);
+       mod1 = d2_angle - (float)float2int(d2_angle);
        noisiness[i] = ABS16(mod1);
        mod1 *= mod1;
        mod1 *= mod1;
 
-       mod2 = d2_angle2 - (float)floor(.5+d2_angle2);
+       mod2 = d2_angle2 - (float)float2int(d2_angle2);
        noisiness[i] += ABS16(mod2);
        mod2 *= mod2;
        mod2 *= mod2;
 
-       avg_mod = .25f*(d2A[i]+2.f*mod1+mod2);
+       avg_mod = .25f*(d2A[i]+mod1+2*mod2);
+       /* This introduces an extra delay of 2 frames in the detection. */
        tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f;
+       /* No delay on this detection, but it's less reliable. */
+       tonality2[i] = 1.f/(1.f+40.f*16.f*pi4*mod2)-.015f;
 
        A[i] = angle2;
        dA[i] = d_angle2;
        d2A[i] = mod2;
     }
-
+    for (i=2;i<N2-1;i++)
+    {
+       float tt = MIN32(tonality2[i], MAX32(tonality2[i-1], tonality2[i+1]));
+       tonality[i] = .9f*MAX32(tonality[i], tt-.1f);
+    }
     frame_tonality = 0;
     max_frame_tonality = 0;
     /*tw_sum = 0;*/
     info->activity = 0;
     frame_noisiness = 0;
     frame_stationarity = 0;
     if (!tonal->count)
     {
        for (b=0;b<NB_TBANDS;b++)
        {
           tonal->lowE[b] = 1e10;
           tonal->highE[b] = -1e10;
        }
     }
     relativeE = 0;
     frame_loudness = 0;
+    /* The energy of the very first band is special because of DC. */
+    {
+       float E = 0;
+       float X1r, X2r;
+       X1r = 2*(float)out[0].r;
+       X2r = 2*(float)out[0].i;
+       E = X1r*X1r + X2r*X2r;
+       for (i=1;i<4;i++)
+       {
+          float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
+                     + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
+          E += binE;
+       }
+       E = SCALE_ENER(E);
+       band_log2[0] = .5f*1.442695f*(float)log(E+1e-10f);
+    }
     for (b=0;b<NB_TBANDS;b++)
     {
        float E=0, tE=0, nE=0;
        float L1, L2;
        float stationarity;
        for (i=tbands[b];i<tbands[b+1];i++)
        {
           float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
                      + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
-#ifdef FIXED_POINT
-          /* FIXME: It's probably best to change the BFCC filter initial state instead */
-          binE *= 5.55e-17f;
-#endif
+          binE = SCALE_ENER(binE);
           E += binE;
-          tE += binE*tonality[i];
+          tE += binE*MAX32(0, tonality[i]);
           nE += binE*2.f*(.5f-noisiness[i]);
        }
 #ifndef FIXED_POINT
        /* Check for extreme band energies that could cause NaNs later. */
        if (!(E<1e9f) || celt_isnan(E))
        {
           info->valid = 0;
           RESTORE_STACK;
@@ -366,24 +513,37 @@ static void tonality_analysis(TonalityAn
        }
 #endif
 
        tonal->E[tonal->E_count][b] = E;
        frame_noisiness += nE/(1e-15f+E);
 
        frame_loudness += (float)sqrt(E+1e-10f);
        logE[b] = (float)log(E+1e-10f);
-       tonal->lowE[b] = MIN32(logE[b], tonal->lowE[b]+.01f);
-       tonal->highE[b] = MAX32(logE[b], tonal->highE[b]-.1f);
-       if (tonal->highE[b] < tonal->lowE[b]+1.f)
+       band_log2[b+1] = .5f*1.442695f*(float)log(E+1e-10f);
+       tonal->logE[tonal->E_count][b] = logE[b];
+       if (tonal->count==0)
+          tonal->highE[b] = tonal->lowE[b] = logE[b];
+       if (tonal->highE[b] > tonal->lowE[b] + 7.5)
        {
-          tonal->highE[b]+=.5f;
-          tonal->lowE[b]-=.5f;
+          if (tonal->highE[b] - logE[b] > logE[b] - tonal->lowE[b])
+             tonal->highE[b] -= .01f;
+          else
+             tonal->lowE[b] += .01f;
        }
-       relativeE += (logE[b]-tonal->lowE[b])/(1e-15f+tonal->highE[b]-tonal->lowE[b]);
+       if (logE[b] > tonal->highE[b])
+       {
+          tonal->highE[b] = logE[b];
+          tonal->lowE[b] = MAX32(tonal->highE[b]-15, tonal->lowE[b]);
+       } else if (logE[b] < tonal->lowE[b])
+       {
+          tonal->lowE[b] = logE[b];
+          tonal->highE[b] = MIN32(tonal->lowE[b]+15, tonal->highE[b]);
+       }
+       relativeE += (logE[b]-tonal->lowE[b])/(1e-15f + (tonal->highE[b]-tonal->lowE[b]));
 
        L1=L2=0;
        for (i=0;i<NB_FRAMES;i++)
        {
           L1 += (float)sqrt(tonal->E[i][b]);
           L2 += tonal->E[i][b];
        }
 
@@ -405,66 +565,137 @@ static void tonality_analysis(TonalityAn
           frame_tonality -= band_tonality[b-NB_TBANDS+NB_TONAL_SKIP_BANDS];
 #endif
        max_frame_tonality = MAX16(max_frame_tonality, (1.f+.03f*(b-NB_TBANDS))*frame_tonality);
        slope += band_tonality[b]*(b-8);
        /*printf("%f %f ", band_tonality[b], stationarity);*/
        tonal->prev_band_tonality[b] = band_tonality[b];
     }
 
+    leakage_from[0] = band_log2[0];
+    leakage_to[0] = band_log2[0] - LEAKAGE_OFFSET;
+    for (b=1;b<NB_TBANDS+1;b++)
+    {
+       float leak_slope = LEAKAGE_SLOPE*(tbands[b]-tbands[b-1])/4;
+       leakage_from[b] = MIN16(leakage_from[b-1]+leak_slope, band_log2[b]);
+       leakage_to[b] = MAX16(leakage_to[b-1]-leak_slope, band_log2[b]-LEAKAGE_OFFSET);
+    }
+    for (b=NB_TBANDS-2;b>=0;b--)
+    {
+       float leak_slope = LEAKAGE_SLOPE*(tbands[b+1]-tbands[b])/4;
+       leakage_from[b] = MIN16(leakage_from[b+1]+leak_slope, leakage_from[b]);
+       leakage_to[b] = MAX16(leakage_to[b+1]-leak_slope, leakage_to[b]);
+    }
+    celt_assert(NB_TBANDS+1 <= LEAK_BANDS);
+    for (b=0;b<NB_TBANDS+1;b++)
+    {
+       /* leak_boost[] is made up of two terms. The first, based on leakage_to[],
+          represents the boost needed to overcome the amount of analysis leakage
+          cause in a weaker band b by louder neighbouring bands.
+          The second, based on leakage_from[], applies to a loud band b for
+          which the quantization noise causes synthesis leakage to the weaker
+          neighbouring bands. */
+       float boost = MAX16(0, leakage_to[b] - band_log2[b]) +
+             MAX16(0, band_log2[b] - (leakage_from[b]+LEAKAGE_OFFSET));
+       info->leak_boost[b] = IMIN(255, (int)floor(.5 + 64.f*boost));
+    }
+    for (;b<LEAK_BANDS;b++) info->leak_boost[b] = 0;
+
+    for (i=0;i<NB_FRAMES;i++)
+    {
+       int j;
+       float mindist = 1e15f;
+       for (j=0;j<NB_FRAMES;j++)
+       {
+          int k;
+          float dist=0;
+          for (k=0;k<NB_TBANDS;k++)
+          {
+             float tmp;
+             tmp = tonal->logE[i][k] - tonal->logE[j][k];
+             dist += tmp*tmp;
+          }
+          if (j!=i)
+             mindist = MIN32(mindist, dist);
+       }
+       spec_variability += mindist;
+    }
+    spec_variability = (float)sqrt(spec_variability/NB_FRAMES/NB_TBANDS);
     bandwidth_mask = 0;
     bandwidth = 0;
     maxE = 0;
     noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8)));
-#ifdef FIXED_POINT
-    noise_floor *= 1<<(15+SIG_SHIFT);
-#endif
     noise_floor *= noise_floor;
-    for (b=0;b<NB_TOT_BANDS;b++)
+    for (b=0;b<NB_TBANDS;b++)
     {
        float E=0;
        int band_start, band_end;
        /* Keep a margin of 300 Hz for aliasing */
-       band_start = extra_bands[b];
-       band_end = extra_bands[b+1];
+       band_start = tbands[b];
+       band_end = tbands[b+1];
        for (i=band_start;i<band_end;i++)
        {
           float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
                      + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
           E += binE;
        }
+       E = SCALE_ENER(E);
        maxE = MAX32(maxE, E);
        tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
        E = MAX32(E, tonal->meanE[b]);
        /* Use a simple follower with 13 dB/Bark slope for spreading function */
        bandwidth_mask = MAX32(.05f*bandwidth_mask, E);
        /* Consider the band "active" only if all these conditions are met:
           1) less than 10 dB below the simple follower
           2) less than 90 dB below the peak band (maximal masking possible considering
              both the ATH and the loudness-dependent slope of the spreading function)
           3) above the PCM quantization noise floor
+          We use b+1 because the first CELT band isn't included in tbands[]
        */
        if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start))
-          bandwidth = b;
+          bandwidth = b+1;
+    }
+    /* Special case for the last two bands, for which we don't have spectrum but only
+       the energy above 12 kHz. */
+    {
+       float E = hp_ener*(1.f/(240*240));
+#ifdef FIXED_POINT
+       /* silk_resampler_down2_hp() shifted right by an extra 8 bits. */
+       E *= 256.f*(1.f/Q15ONE)*(1.f/Q15ONE);
+#endif
+       maxE = MAX32(maxE, E);
+       tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
+       E = MAX32(E, tonal->meanE[b]);
+       /* Use a simple follower with 13 dB/Bark slope for spreading function */
+       bandwidth_mask = MAX32(.05f*bandwidth_mask, E);
+       if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*160)
+          bandwidth = 20;
     }
     if (tonal->count<=2)
        bandwidth = 20;
     frame_loudness = 20*(float)log10(frame_loudness);
-    tonal->Etracker = MAX32(tonal->Etracker-.03f, frame_loudness);
+    tonal->Etracker = MAX32(tonal->Etracker-.003f, frame_loudness);
     tonal->lowECount *= (1-alphaE);
     if (frame_loudness < tonal->Etracker-30)
        tonal->lowECount += alphaE;
 
     for (i=0;i<8;i++)
     {
        float sum=0;
        for (b=0;b<16;b++)
           sum += dct_table[i*16+b]*logE[b];
        BFCC[i] = sum;
     }
+    for (i=0;i<8;i++)
+    {
+       float sum=0;
+       for (b=0;b<16;b++)
+          sum += dct_table[i*16+b]*.5f*(tonal->highE[b]+tonal->lowE[b]);
+       midE[i] = sum;
+    }
 
     frame_stationarity /= NB_TBANDS;
     relativeE /= NB_TBANDS;
     if (tonal->count<10)
        relativeE = .5;
     frame_noisiness /= NB_TBANDS;
 #if 1
     info->activity = frame_noisiness + (1-frame_noisiness)*relativeE;
@@ -474,17 +705,17 @@ static void tonality_analysis(TonalityAn
     frame_tonality = (max_frame_tonality/(NB_TBANDS-NB_TONAL_SKIP_BANDS));
     frame_tonality = MAX16(frame_tonality, tonal->prev_tonality*.8f);
     tonal->prev_tonality = frame_tonality;
 
     slope /= 8*8;
     info->tonality_slope = slope;
 
     tonal->E_count = (tonal->E_count+1)%NB_FRAMES;
-    tonal->count++;
+    tonal->count = IMIN(tonal->count+1, ANALYSIS_COUNT_MAX);
     info->tonality = frame_tonality;
 
     for (i=0;i<4;i++)
        features[i] = -0.12299f*(BFCC[i]+tonal->mem[i+24]) + 0.49195f*(tonal->mem[i]+tonal->mem[i+16]) + 0.69693f*tonal->mem[i+8] - 1.4349f*tonal->cmean[i];
 
     for (i=0;i<4;i++)
        tonal->cmean[i] = (1-alpha)*tonal->cmean[i] + alpha*BFCC[i];
 
@@ -493,43 +724,47 @@ static void tonality_analysis(TonalityAn
     for (i=0;i<3;i++)
         features[8+i] = 0.53452f*(BFCC[i]+tonal->mem[i+24]) - 0.26726f*(tonal->mem[i]+tonal->mem[i+16]) -0.53452f*tonal->mem[i+8];
 
     if (tonal->count > 5)
     {
        for (i=0;i<9;i++)
           tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i];
     }
+    for (i=0;i<4;i++)
+       features[i] = BFCC[i]-midE[i];
 
     for (i=0;i<8;i++)
     {
        tonal->mem[i+24] = tonal->mem[i+16];
        tonal->mem[i+16] = tonal->mem[i+8];
        tonal->mem[i+8] = tonal->mem[i];
        tonal->mem[i] = BFCC[i];
     }
     for (i=0;i<9;i++)
-       features[11+i] = (float)sqrt(tonal->std[i]);
-    features[20] = info->tonality;
-    features[21] = info->activity;
-    features[22] = frame_stationarity;
-    features[23] = info->tonality_slope;
-    features[24] = tonal->lowECount;
+       features[11+i] = (float)sqrt(tonal->std[i]) - std_feature_bias[i];
+    features[18] = spec_variability - 0.78f;
+    features[20] = info->tonality - 0.154723f;
+    features[21] = info->activity - 0.724643f;
+    features[22] = frame_stationarity - 0.743717f;
+    features[23] = info->tonality_slope + 0.069216f;
+    features[24] = tonal->lowECount - 0.067930f;
 
-#ifndef DISABLE_FLOAT_API
     mlp_process(&net, features, frame_probs);
     frame_probs[0] = .5f*(frame_probs[0]+1);
     /* Curve fitting between the MLP probability and the actual probability */
-    frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10);
+    /*frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10);*/
     /* Probability of active audio (as opposed to silence) */
     frame_probs[1] = .5f*frame_probs[1]+.5f;
-    /* Consider that silence has a 50-50 probability. */
-    frame_probs[0] = frame_probs[1]*frame_probs[0] + (1-frame_probs[1])*.5f;
+    frame_probs[1] *= frame_probs[1];
 
-    /*printf("%f %f ", frame_probs[0], frame_probs[1]);*/
+    /* Probability of speech or music vs noise */
+    info->activity_probability = frame_probs[1];
+
+    /*printf("%f %f\n", frame_probs[0], frame_probs[1]);*/
     {
        /* Probability of state transition */
        float tau;
        /* Represents independence of the MLP probabilities, where
           beta=1 means fully independent. */
        float beta;
        /* Denormalized probability of speech (p0) and music (p1) after update */
        float p0, p1;
@@ -537,44 +772,68 @@ static void tonality_analysis(TonalityAn
        float s0, m0;
        /* Probability sum for renormalisation */
        float psum;
        /* Instantaneous probability of speech and music, with beta pre-applied. */
        float speech0;
        float music0;
        float p, q;
 
+       /* More silence transitions for speech than for music. */
+       tau = .001f*tonal->music_prob + .01f*(1-tonal->music_prob);
+       p = MAX16(.05f,MIN16(.95f,frame_probs[1]));
+       q = MAX16(.05f,MIN16(.95f,tonal->vad_prob));
+       beta = .02f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p));
+       /* p0 and p1 are the probabilities of speech and music at this frame
+          using only information from previous frame and applying the
+          state transition model */
+       p0 = (1-tonal->vad_prob)*(1-tau) +    tonal->vad_prob *tau;
+       p1 =    tonal->vad_prob *(1-tau) + (1-tonal->vad_prob)*tau;
+       /* We apply the current probability with exponent beta to work around
+          the fact that the probability estimates aren't independent. */
+       p0 *= (float)pow(1-frame_probs[1], beta);
+       p1 *= (float)pow(frame_probs[1], beta);
+       /* Normalise the probabilities to get the Marokv probability of music. */
+       tonal->vad_prob = p1/(p0+p1);
+       info->vad_prob = tonal->vad_prob;
+       /* Consider that silence has a 50-50 probability of being speech or music. */
+       frame_probs[0] = tonal->vad_prob*frame_probs[0] + (1-tonal->vad_prob)*.5f;
+
        /* One transition every 3 minutes of active audio */
-       tau = .00005f*frame_probs[1];
+       tau = .0001f;
        /* Adapt beta based on how "unexpected" the new prob is */
        p = MAX16(.05f,MIN16(.95f,frame_probs[0]));
        q = MAX16(.05f,MIN16(.95f,tonal->music_prob));
-       beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p));
+       beta = .02f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p));
        /* p0 and p1 are the probabilities of speech and music at this frame
           using only information from previous frame and applying the
           state transition model */
        p0 = (1-tonal->music_prob)*(1-tau) +    tonal->music_prob *tau;
        p1 =    tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau;
        /* We apply the current probability with exponent beta to work around
           the fact that the probability estimates aren't independent. */
        p0 *= (float)pow(1-frame_probs[0], beta);
        p1 *= (float)pow(frame_probs[0], beta);
        /* Normalise the probabilities to get the Marokv probability of music. */
        tonal->music_prob = p1/(p0+p1);
        info->music_prob = tonal->music_prob;
 
+       /*printf("%f %f %f %f\n", frame_probs[0], frame_probs[1], tonal->music_prob, tonal->vad_prob);*/
        /* This chunk of code deals with delayed decision. */
        psum=1e-20f;
        /* Instantaneous probability of speech and music, with beta pre-applied. */
        speech0 = (float)pow(1-frame_probs[0], beta);
        music0  = (float)pow(frame_probs[0], beta);
        if (tonal->count==1)
        {
-          tonal->pspeech[0]=.5;
-          tonal->pmusic [0]=.5;
+          if (tonal->application == OPUS_APPLICATION_VOIP)
+             tonal->pmusic[0] = .1;
+          else
+             tonal->pmusic[0] = .625;
+          tonal->pspeech[0] = 1-tonal->pmusic[0];
        }
        /* Updated probability of having only speech (s0) or only music (m0),
           before considering the new observation. */
        s0 = tonal->pspeech[0] + tonal->pspeech[1];
        m0 = tonal->pmusic [0] + tonal->pmusic [1];
        /* Updates s0 and m0 with instantaneous probability. */
        tonal->pspeech[0] = s0*(1-tau)*speech0;
        tonal->pmusic [0] = m0*(1-tau)*music0;
@@ -614,59 +873,54 @@ static void tonality_analysis(TonalityAn
           }
           if (tonal->music_prob<.1)
           {
              float adapt;
              adapt = 1.f/(++tonal->speech_confidence_count);
              tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500);
              tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence);
           }
-       } else {
-          if (tonal->music_confidence_count==0)
-             tonal->music_confidence = .9f;
-          if (tonal->speech_confidence_count==0)
-             tonal->speech_confidence = .1f;
        }
     }
-    if (tonal->last_music != (tonal->music_prob>.5f))
-       tonal->last_transition=0;
     tonal->last_music = tonal->music_prob>.5f;
-#else
-    info->music_prob = 0;
+#ifdef MLP_TRAINING
+    for (i=0;i<25;i++)
+       printf("%f ", features[i]);
+    printf("\n");
 #endif
-    /*for (i=0;i<25;i++)
-       printf("%f ", features[i]);
-    printf("\n");*/
 
     info->bandwidth = bandwidth;
     /*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/
     info->noisiness = frame_noisiness;
     info->valid = 1;
     RESTORE_STACK;
 }
 
 void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
                  int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
                  int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info)
 {
    int offset;
    int pcm_len;
 
+   analysis_frame_size -= analysis_frame_size&1;
    if (analysis_pcm != NULL)
    {
       /* Avoid overflow/wrap-around of the analysis buffer */
-      analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size);
+      analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/50, analysis_frame_size);
 
       pcm_len = analysis_frame_size - analysis->analysis_offset;
       offset = analysis->analysis_offset;
-      do {
-         tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
-         offset += 480;
-         pcm_len -= 480;
-      } while (pcm_len>0);
+      while (pcm_len>0) {
+         tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(Fs/50, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
+         offset += Fs/50;
+         pcm_len -= Fs/50;
+      }
       analysis->analysis_offset = analysis_frame_size;
 
       analysis->analysis_offset -= frame_size;
    }
 
    analysis_info->valid = 0;
    tonality_get_info(analysis, analysis_info, frame_size);
 }
+
+#endif /* DISABLE_FLOAT_API */
--- a/media/libopus/src/analysis.h
+++ b/media/libopus/src/analysis.h
@@ -28,70 +28,79 @@
 #ifndef ANALYSIS_H
 #define ANALYSIS_H
 
 #include "celt.h"
 #include "opus_private.h"
 
 #define NB_FRAMES 8
 #define NB_TBANDS 18
-#define NB_TOT_BANDS 21
-#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */
+#define ANALYSIS_BUF_SIZE 720 /* 30 ms at 24 kHz */
+
+/* At that point we can stop counting frames because it no longer matters. */
+#define ANALYSIS_COUNT_MAX 10000
 
-#define DETECT_SIZE 200
+#define DETECT_SIZE 100
+
+/* Uncomment this to print the MLP features on stdout. */
+/*#define MLP_TRAINING*/
 
 typedef struct {
    int arch;
+   int application;
+   opus_int32 Fs;
 #define TONALITY_ANALYSIS_RESET_START angle
    float angle[240];
    float d_angle[240];
    float d2_angle[240];
    opus_val32 inmem[ANALYSIS_BUF_SIZE];
    int   mem_fill;                      /* number of usable samples in the buffer */
    float prev_band_tonality[NB_TBANDS];
    float prev_tonality;
    float E[NB_FRAMES][NB_TBANDS];
+   float logE[NB_FRAMES][NB_TBANDS];
    float lowE[NB_TBANDS];
    float highE[NB_TBANDS];
-   float meanE[NB_TOT_BANDS];
+   float meanE[NB_TBANDS+1];
    float mem[32];
    float cmean[8];
    float std[9];
    float music_prob;
+   float vad_prob;
    float Etracker;
    float lowECount;
    int E_count;
    int last_music;
-   int last_transition;
    int count;
-   float subframe_mem[3];
    int analysis_offset;
    /** Probability of having speech for time i to DETECT_SIZE-1 (and music before).
        pspeech[0] is the probability that all frames in the window are speech. */
    float pspeech[DETECT_SIZE];
    /** Probability of having music for time i to DETECT_SIZE-1 (and speech before).
        pmusic[0] is the probability that all frames in the window are music. */
    float pmusic[DETECT_SIZE];
    float speech_confidence;
    float music_confidence;
    int speech_confidence_count;
    int music_confidence_count;
    int write_pos;
    int read_pos;
    int read_subframe;
+   float hp_ener_accum;
+   opus_val32 downmix_state[3];
    AnalysisInfo info[DETECT_SIZE];
 } TonalityAnalysisState;
 
 /** Initialize a TonalityAnalysisState struct.
  *
  * This performs some possibly slow initialization steps which should
  * not be repeated every analysis step. No allocated memory is retained
  * by the state struct, so no cleanup call is required.
  */
-void tonality_analysis_init(TonalityAnalysisState *analysis);
+void tonality_analysis_init(TonalityAnalysisState *analysis, opus_int32 Fs);
 
 /** Reset a TonalityAnalysisState stuct.
  *
  * Call this when there's a discontinuity in the data.
  */
 void tonality_analysis_reset(TonalityAnalysisState *analysis);
 
 void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len);
--- a/media/libopus/src/mlp_data.c
+++ b/media/libopus/src/mlp_data.c
@@ -1,109 +1,112 @@
-/* The contents of this file was automatically generated by mlp_train.c
-   It contains multi-layer perceptron (MLP) weights. */
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include "mlp.h"
 
-/* RMS error was 0.138320, seed was 1361535663 */
+/* RMS error was 0.280492, seed was 1480478173 */
+/* 0.005976 0.031821 (0.280494 0.280492) done */
 
-static const float weights[422] = {
+static const float weights[450] = {
 
 /* hidden layer */
--0.0941125f, -0.302976f, -0.603555f, -0.19393f, -0.185983f,
--0.601617f, -0.0465317f, -0.114563f, -0.103599f, -0.618938f,
--0.317859f, -0.169949f, -0.0702885f, 0.148065f, 0.409524f,
-0.548432f, 0.367649f, -0.494393f, 0.764306f, -1.83957f,
-0.170849f, 12.786f, -1.08848f, -1.27284f, -16.2606f,
-24.1773f, -5.57454f, -0.17276f, -0.163388f, -0.224421f,
--0.0948944f, -0.0728695f, -0.26557f, -0.100283f, -0.0515459f,
--0.146142f, -0.120674f, -0.180655f, 0.12857f, 0.442138f,
--0.493735f, 0.167767f, 0.206699f, -0.197567f, 0.417999f,
-1.50364f, -0.773341f, -10.0401f, 0.401872f, 2.97966f,
-15.2165f, -1.88905f, -1.19254f, 0.0285397f, -0.00405139f,
-0.0707565f, 0.00825699f, -0.0927269f, -0.010393f, -0.00428882f,
--0.00489743f, -0.0709731f, -0.00255992f, 0.0395619f, 0.226424f,
-0.0325231f, 0.162175f, -0.100118f, 0.485789f, 0.12697f,
-0.285937f, 0.0155637f, 0.10546f, 3.05558f, 1.15059f,
--1.00904f, -1.83088f, 3.31766f, -3.42516f, -0.119135f,
--0.0405654f, 0.00690068f, 0.0179877f, -0.0382487f, 0.00597941f,
--0.0183611f, 0.00190395f, -0.144322f, -0.0435671f, 0.000990594f,
-0.221087f, 0.142405f, 0.484066f, 0.404395f, 0.511955f,
--0.237255f, 0.241742f, 0.35045f, -0.699428f, 10.3993f,
-2.6507f, -2.43459f, -4.18838f, 1.05928f, 1.71067f,
-0.00667811f, -0.0721335f, -0.0397346f, 0.0362704f, -0.11496f,
--0.0235776f, 0.0082161f, -0.0141741f, -0.0329699f, -0.0354253f,
-0.00277404f, -0.290654f, -1.14767f, -0.319157f, -0.686544f,
-0.36897f, 0.478899f, 0.182579f, -0.411069f, 0.881104f,
--4.60683f, 1.4697f, 0.335845f, -1.81905f, -30.1699f,
-5.55225f, 0.0019508f, -0.123576f, -0.0727332f, -0.0641597f,
--0.0534458f, -0.108166f, -0.0937368f, -0.0697883f, -0.0275475f,
--0.192309f, -0.110074f, 0.285375f, -0.405597f, 0.0926724f,
--0.287881f, -0.851193f, -0.099493f, -0.233764f, -1.2852f,
-1.13611f, 3.12168f, -0.0699f, -1.86216f, 2.65292f,
--7.31036f, 2.44776f, -0.00111802f, -0.0632786f, -0.0376296f,
--0.149851f, 0.142963f, 0.184368f, 0.123433f, 0.0756158f,
-0.117312f, 0.0933395f, 0.0692163f, 0.0842592f, 0.0704683f,
-0.0589963f, 0.0942205f, -0.448862f, 0.0262677f, 0.270352f,
--0.262317f, 0.172586f, 2.00227f, -0.159216f, 0.038422f,
-10.2073f, 4.15536f, -2.3407f, -0.0550265f, 0.00964792f,
--0.141336f, 0.0274501f, 0.0343921f, -0.0487428f, 0.0950172f,
--0.00775017f, -0.0372492f, -0.00548121f, -0.0663695f, 0.0960506f,
--0.200008f, -0.0412827f, 0.58728f, 0.0515787f, 0.337254f,
-0.855024f, 0.668371f, -0.114904f, -3.62962f, -0.467477f,
--0.215472f, 2.61537f, 0.406117f, -1.36373f, 0.0425394f,
-0.12208f, 0.0934502f, 0.123055f, 0.0340935f, -0.142466f,
-0.035037f, -0.0490666f, 0.0733208f, 0.0576672f, 0.123984f,
--0.0517194f, -0.253018f, 0.590565f, 0.145849f, 0.315185f,
-0.221534f, -0.149081f, 0.216161f, -0.349575f, 24.5664f,
--0.994196f, 0.614289f, -18.7905f, -2.83277f, -0.716801f,
--0.347201f, 0.479515f, -0.246027f, 0.0758683f, 0.137293f,
--0.17781f, 0.118751f, -0.00108329f, -0.237334f, 0.355732f,
--0.12991f, -0.0547627f, -0.318576f, -0.325524f, 0.180494f,
--0.0625604f, 0.141219f, 0.344064f, 0.37658f, -0.591772f,
-5.8427f, -0.38075f, 0.221894f, -1.41934f, -1.87943e+06f,
-1.34114f, 0.0283355f, -0.0447856f, -0.0211466f, -0.0256927f,
-0.0139618f, 0.0207934f, -0.0107666f, 0.0110969f, 0.0586069f,
--0.0253545f, -0.0328433f, 0.11872f, -0.216943f, 0.145748f,
-0.119808f, -0.0915211f, -0.120647f, -0.0787719f, -0.143644f,
--0.595116f, -1.152f, -1.25335f, -1.17092f, 4.34023f,
--975268.f, -1.37033f, -0.0401123f, 0.210602f, -0.136656f,
-0.135962f, -0.0523293f, 0.0444604f, 0.0143928f, 0.00412666f,
--0.0193003f, 0.218452f, -0.110204f, -2.02563f, 0.918238f,
--2.45362f, 1.19542f, -0.061362f, -1.92243f, 0.308111f,
-0.49764f, 0.912356f, 0.209272f, -2.34525f, 2.19326f,
--6.47121f, 1.69771f, -0.725123f, 0.0118929f, 0.0377944f,
-0.0554003f, 0.0226452f, -0.0704421f, -0.0300309f, 0.0122978f,
--0.0041782f, -0.0686612f, 0.0313115f, 0.039111f, 0.364111f,
--0.0945548f, 0.0229876f, -0.17414f, 0.329795f, 0.114714f,
-0.30022f, 0.106997f, 0.132355f, 5.79932f, 0.908058f,
--0.905324f, -3.3561f, 0.190647f, 0.184211f, -0.673648f,
-0.231807f, -0.0586222f, 0.230752f, -0.438277f, 0.245857f,
--0.17215f, 0.0876383f, -0.720512f, 0.162515f, 0.0170571f,
-0.101781f, 0.388477f, 1.32931f, 1.08548f, -0.936301f,
--2.36958f, -6.71988f, -3.44376f, 2.13818f, 14.2318f,
-4.91459f, -3.09052f, -9.69191f, -0.768234f, 1.79604f,
-0.0549653f, 0.163399f, 0.0797025f, 0.0343933f, -0.0555876f,
--0.00505673f, 0.0187258f, 0.0326628f, 0.0231486f, 0.15573f,
-0.0476223f, -0.254824f, 1.60155f, -0.801221f, 2.55496f,
-0.737629f, -1.36249f, -0.695463f, -2.44301f, -1.73188f,
-3.95279f, 1.89068f, 0.486087f, -11.3343f, 3.9416e+06f,
+-0.514624f, 0.0234227f, -0.14329f, -0.0878216f, -0.00187827f,
+-0.0257443f, 0.108524f, 0.00333881f, 0.00585017f, -0.0246132f,
+0.142723f, -0.00436494f, 0.0101354f, -0.11124f, -0.0809367f,
+-0.0750772f, 0.0295524f, 0.00823944f, 0.150392f, 0.0320876f,
+-0.0710564f, -1.43818f, 0.652076f, 0.0650744f, -1.54821f,
+0.168949f, -1.92724f, 0.0517976f, -0.0670737f, -0.0690121f,
+0.00247528f, -0.0522024f, 0.0631368f, 0.0532776f, 0.047751f,
+-0.011715f, 0.142374f, -0.0290885f, -0.279263f, -0.433499f,
+-0.0795174f, -0.380458f, -0.051263f, 0.218537f, -0.322478f,
+1.06667f, -0.104607f, -4.70108f, 0.312037f, 0.277397f,
+-2.71859f, 1.70037f, -0.141845f, 0.0115618f, 0.0629883f,
+0.0403871f, 0.0139428f, -0.00430733f, -0.0429038f, -0.0590318f,
+-0.0501526f, -0.0284802f, -0.0415686f, -0.0438999f, 0.0822666f,
+0.197194f, 0.0363275f, -0.0584307f, 0.0752364f, -0.0799796f,
+-0.146275f, 0.161661f, -0.184585f, 0.145568f, 0.442823f,
+1.61221f, 1.11162f, 2.62177f, -2.482f, -0.112599f,
+-0.110366f, -0.140794f, -0.181694f, 0.0648674f, 0.0842248f,
+0.0933993f, 0.150122f, 0.129171f, 0.176848f, 0.141758f,
+-0.271822f, 0.235113f, 0.0668579f, -0.433957f, 0.113633f,
+-0.169348f, -1.40091f, 0.62861f, -0.134236f, 0.402173f,
+1.86373f, 1.53998f, -4.32084f, 0.735343f, 0.800214f,
+-0.00968415f, 0.0425904f, 0.0196811f, -0.018426f, -0.000343953f,
+-0.00416389f, 0.00111558f, 0.0173069f, -0.00998596f, -0.025898f,
+0.00123764f, -0.00520373f, -0.0565033f, 0.0637394f, 0.0051213f,
+0.0221361f, 0.00819962f, -0.0467061f, -0.0548258f, -0.00314063f,
+-1.18332f, 1.88091f, -0.41148f, -2.95727f, -0.521449f,
+-0.271641f, 0.124946f, -0.0532936f, 0.101515f, 0.000208564f,
+-0.0488748f, 0.0642388f, -0.0383848f, 0.0135046f, -0.0413592f,
+-0.0326402f, -0.0137421f, -0.0225219f, -0.0917294f, -0.277759f,
+-0.185418f, 0.0471128f, -0.125879f, 0.262467f, -0.212794f,
+-0.112931f, -1.99885f, -0.404787f, 0.224402f, 0.637962f,
+-0.27808f, -0.0723953f, -0.0537655f, -0.0336359f, -0.0906601f,
+-0.0641309f, -0.0713542f, 0.0524317f, 0.00608819f, 0.0754101f,
+-0.0488401f, -0.00671865f, 0.0418239f, 0.0536284f, -0.132639f,
+0.0267648f, -0.248432f, -0.0104153f, 0.035544f, -0.212753f,
+-0.302895f, -0.0357854f, 0.376838f, 0.597025f, -0.664647f,
+0.268422f, -0.376772f, -1.05472f, 0.0144178f, 0.179122f,
+0.0360155f, 0.220262f, -0.0056381f, 0.0317197f, 0.0621066f,
+-0.00779298f, 0.00789378f, 0.00350605f, 0.0104809f, 0.0362871f,
+-0.157708f, -0.0659779f, -0.0926278f, 0.00770791f, 0.0631621f,
+0.0817343f, -0.424295f, -0.0437727f, -0.24251f, 0.711217f,
+-0.736455f, -2.194f, -0.107612f, -0.175156f, -0.0366573f,
+-0.0123156f, -0.0628516f, -0.0218977f, -0.00693699f, 0.00695185f,
+0.00507362f, 0.00359334f, 0.0052661f, 0.035561f, 0.0382701f,
+0.0342179f, -0.00790271f, -0.0170925f, 0.047029f, 0.0197362f,
+-0.0153435f, 0.0644152f, -0.36862f, -0.0674876f, -2.82672f,
+1.34122f, -0.0788029f, -3.47792f, 0.507246f, -0.816378f,
+-0.0142383f, -0.127349f, -0.106926f, -0.0359524f, 0.105045f,
+0.291554f, 0.195413f, 0.0866214f, -0.066577f, -0.102188f,
+0.0979466f, -0.12982f, 0.400181f, -0.409336f, -0.0593326f,
+-0.0656203f, -0.204474f, 0.179802f, 0.000509084f, 0.0995954f,
+-2.377f, -0.686359f, 0.934861f, 1.10261f, 1.3901f,
+-4.33616f, -0.00264017f, 0.00713045f, 0.106264f, 0.143726f,
+-0.0685305f, -0.054656f, -0.0176725f, -0.0772669f, -0.0264526f,
+-0.0103824f, -0.0269872f, -0.00687f, 0.225804f, 0.407751f,
+-0.0612611f, -0.0576863f, -0.180131f, -0.222772f, -0.461742f,
+0.335236f, 1.03399f, 4.24112f, -0.345796f, -0.594549f,
+-76.1407f, -0.265276f, 0.0507719f, 0.0643044f, 0.0384832f,
+0.0424459f, -0.0387817f, -0.0235996f, -0.0740556f, -0.0270029f,
+0.00882177f, -0.0552371f, -0.00485851f, 0.314295f, 0.360431f,
+-0.0787085f, 0.110355f, -0.415958f, -0.385088f, -0.272224f,
+-1.55108f, -0.141848f, 0.448877f, -0.563447f, -2.31403f,
+-0.120077f, -1.49918f, -0.817726f, -0.0495854f, -0.0230782f,
+-0.0224014f, 0.117076f, 0.0393216f, 0.051997f, 0.0330763f,
+-0.110796f, 0.0211117f, -0.0197258f, 0.0187461f, 0.0125183f,
+0.14876f, 0.0920565f, -0.342475f, 0.135272f, -0.168155f,
+-0.033423f, -0.0604611f, -0.128835f, 0.664947f, -0.144997f,
+2.27649f, 1.28663f, 0.841217f, -2.42807f, 0.0230471f,
+0.226709f, -0.0374803f, 0.155436f, 0.0400342f, -0.184686f,
+0.128488f, -0.0939518f, -0.0578559f, 0.0265967f, -0.0999322f,
+-0.0322768f, -0.322994f, -0.189371f, -0.738069f, -0.0754914f,
+0.214717f, -0.093728f, -0.695741f, 0.0899298f, -2.06188f,
+-0.273719f, -0.896977f, 0.130553f, 0.134638f, 1.29355f,
+0.00520749f, -0.0324224f, 0.00530451f, 0.0192385f, 0.00328708f,
+0.0250838f, 0.0053365f, -0.0177321f, 0.00618789f, 0.00525364f,
+0.00104596f, -0.0360459f, 0.0402403f, -0.0406351f, 0.0136883f,
+0.0880722f, -0.0197449f, 0.089938f, 0.0100456f, -0.0475638f,
+-0.73267f, 0.037433f, -0.146551f, -0.230221f, -3.06489f,
+-1.40194f, 0.0198483f, 0.0397953f, -0.0190239f, 0.0470715f,
+-0.131363f, -0.191721f, -0.0176224f, -0.0480352f, -0.221799f,
+-0.26794f, -0.0292615f, 0.0612127f, -0.129877f, 0.00628332f,
+-0.085918f, 0.0175379f, 0.0541011f, -0.0810874f, -0.380809f,
+-0.222056f, -0.508859f, -0.473369f, 0.484958f, -2.28411f,
+0.0139516f,
+/* output layer */
+3.90017f, 1.71789f, -1.43372f, -2.70839f, 1.77107f,
+5.48006f, 1.44661f, 2.01134f, -1.88383f, -3.64958f,
+-1.26351f, 0.779421f, 2.11357f, 3.10409f, 1.68846f,
+-4.46197f, -1.61455f, 3.59832f, 2.43531f, -1.26458f,
+0.417941f, 1.47437f, 2.16635f, -1.909f, -0.828869f,
+1.38805f, -2.67975f, -0.110044f, 1.95596f, 0.697931f,
+-0.313226f, -0.889315f, 0.283236f, 0.946102f, };
 
-/* output layer */
--0.381439f, 0.12115f, -0.906927f, 2.93878f, 1.6388f,
-0.882811f, 0.874344f, 1.21726f, -0.874545f, 0.321706f,
-0.785055f, 0.946558f, -0.575066f, -3.46553f, 0.884905f,
-0.0924047f, -9.90712f, 0.391338f, 0.160103f, -2.04954f,
-4.1455f, 0.0684029f, -0.144761f, -0.285282f, 0.379244f,
--1.1584f, -0.0277241f, -9.85f, -4.82386f, 3.71333f,
-3.87308f, 3.52558f};
-
-static const int topo[3] = {25, 15, 2};
+static const int topo[3] = {25, 16, 2};
 
 const MLP net = {
     3,
     topo,
     weights
 };
--- a/media/libopus/src/opus.c
+++ b/media/libopus/src/opus.c
@@ -102,17 +102,17 @@ OPUS_EXPORT void opus_pcm_soft_clip(floa
          /* Detect the special case where we clip before the first zero crossing */
          special = (start==0 && x[i*C]*x[0]>=0);
 
          /* Compute a such that maxval + a*maxval^2 = 1 */
          a=(maxval-1)/(maxval*maxval);
          /* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
             does not cause output values larger than +/-1, but small enough not
             to matter even for 24-bit output.  */
-         a += a*2.4e-7;
+         a += a*2.4e-7f;
          if (x[i*C]>0)
             a = -a;
          /* Apply soft clipping */
          for (i=start;i<end;i++)
             x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
 
          if (special && peak_pos>=2)
          {
--- a/media/libopus/src/opus_decoder.c
+++ b/media/libopus/src/opus_decoder.c
@@ -886,24 +886,44 @@ int opus_decoder_ctl(OpusDecoder *st, in
        {
           goto bad_arg;
        }
        st->decode_gain = value;
    }
    break;
    case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
    {
-      opus_uint32 *value = va_arg(ap, opus_uint32*);
+      opus_int32 *value = va_arg(ap, opus_int32*);
       if (!value)
       {
          goto bad_arg;
       }
       *value = st->last_packet_duration;
    }
    break;
+   case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+   {
+       opus_int32 value = va_arg(ap, opus_int32);
+       if(value<0 || value>1)
+       {
+          goto bad_arg;
+       }
+       celt_decoder_ctl(celt_dec, OPUS_SET_PHASE_INVERSION_DISABLED(value));
+   }
+   break;
+   case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+   {
+       opus_int32 *value = va_arg(ap, opus_int32*);
+       if (!value)
+       {
+          goto bad_arg;
+       }
+       celt_decoder_ctl(celt_dec, OPUS_GET_PHASE_INVERSION_DISABLED(value));
+   }
+   break;
    default:
       /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
       ret = OPUS_UNIMPLEMENTED;
       break;
    }
 
    va_end(ap);
    return ret;
--- a/media/libopus/src/opus_encoder.c
+++ b/media/libopus/src/opus_encoder.c
@@ -48,16 +48,20 @@
 #ifdef FIXED_POINT
 #include "fixed/structs_FIX.h"
 #else
 #include "float/structs_FLP.h"
 #endif
 
 #define MAX_ENCODER_BUFFER 480
 
+#ifndef DISABLE_FLOAT_API
+#define PSEUDO_SNR_THRESHOLD 316.23f    /* 10^(25/10) */
+#endif
+
 typedef struct {
    opus_val32 XX, XY, YY;
    opus_val16 smoothed_width;
    opus_val16 max_follower;
 } StereoWidthState;
 
 struct OpusEncoder {
     int          celt_enc_offset;
@@ -77,81 +81,95 @@ struct OpusEncoder {
     int          vbr_constraint;
     int          variable_duration;
     opus_int32   bitrate_bps;
     opus_int32   user_bitrate_bps;
     int          lsb_depth;
     int          encoder_buffer;
     int          lfe;
     int          arch;
+    int          use_dtx;                 /* general DTX for both SILK and CELT */
 #ifndef DISABLE_FLOAT_API
     TonalityAnalysisState analysis;
 #endif
 
 #define OPUS_ENCODER_RESET_START stream_channels
     int          stream_channels;
     opus_int16   hybrid_stereo_width_Q14;
     opus_int32   variable_HP_smth2_Q15;
     opus_val16   prev_HB_gain;
     opus_val32   hp_mem[4];
     int          mode;
     int          prev_mode;
     int          prev_channels;
     int          prev_framesize;
     int          bandwidth;
+    /* Bandwidth determined automatically from the rate (before any other adjustment) */
+    int          auto_bandwidth;
     int          silk_bw_switch;
     /* Sampling rate (at the API level) */
     int          first;
     opus_val16 * energy_masking;
     StereoWidthState width_mem;
     opus_val16   delay_buffer[MAX_ENCODER_BUFFER*2];
 #ifndef DISABLE_FLOAT_API
     int          detected_bandwidth;
+    int          nb_no_activity_frames;
+    opus_val32   peak_signal_energy;
 #endif
+    int          nonfinal_frame; /* current frame is not the final in a packet */
     opus_uint32  rangeFinal;
 };
 
 /* Transition tables for the voice and music. First column is the
    middle (memoriless) threshold. The second column is the hysteresis
    (difference with the middle) */
 static const opus_int32 mono_voice_bandwidth_thresholds[8] = {
-        11000, 1000, /* NB<->MB */
-        14000, 1000, /* MB<->WB */
-        17000, 1000, /* WB<->SWB */
-        21000, 2000, /* SWB<->FB */
+        10000, 1000, /* NB<->MB */
+        11000, 1000, /* MB<->WB */
+        13500, 1000, /* WB<->SWB */
+        14000, 2000, /* SWB<->FB */
 };
 static const opus_int32 mono_music_bandwidth_thresholds[8] = {
-        12000, 1000, /* NB<->MB */
-        15000, 1000, /* MB<->WB */
-        18000, 2000, /* WB<->SWB */
-        22000, 2000, /* SWB<->FB */
+        10000, 1000, /* NB<->MB */
+        11000, 1000, /* MB<->WB */
+        13500, 1000, /* WB<->SWB */
+        14000, 2000, /* SWB<->FB */
 };
 static const opus_int32 stereo_voice_bandwidth_thresholds[8] = {
-        11000, 1000, /* NB<->MB */
-        14000, 1000, /* MB<->WB */
-        21000, 2000, /* WB<->SWB */
-        28000, 2000, /* SWB<->FB */
+        10000, 1000, /* NB<->MB */
+        11000, 1000, /* MB<->WB */
+        13500, 1000, /* WB<->SWB */
+        14000, 2000, /* SWB<->FB */
 };
 static const opus_int32 stereo_music_bandwidth_thresholds[8] = {
-        12000, 1000, /* NB<->MB */
-        18000, 2000, /* MB<->WB */
-        21000, 2000, /* WB<->SWB */
-        30000, 2000, /* SWB<->FB */
+        10000, 1000, /* NB<->MB */
+        11000, 1000, /* MB<->WB */
+        13500, 1000, /* WB<->SWB */
+        14000, 2000, /* SWB<->FB */
 };
 /* Threshold bit-rates for switching between mono and stereo */
-static const opus_int32 stereo_voice_threshold = 30000;
-static const opus_int32 stereo_music_threshold = 30000;
+static const opus_int32 stereo_voice_threshold = 24000;
+static const opus_int32 stereo_music_threshold = 24000;
 
 /* Threshold bit-rate for switching between SILK/hybrid and CELT-only */
 static const opus_int32 mode_thresholds[2][2] = {
       /* voice */ /* music */
       {  64000,      16000}, /* mono */
       {  36000,      16000}, /* stereo */
 };
 
+static const opus_int32 fec_thresholds[] = {
+        12000, 1000, /* NB */
+        14000, 1000, /* MB */
+        16000, 1000, /* WB */
+        20000, 1000, /* SWB */
+        22000, 1000, /* FB */
+};
+
 int opus_encoder_get_size(int channels)
 {
     int silkEncSizeBytes, celtEncSizeBytes;
     int ret;
     if (channels<1 || channels > 2)
         return 0;
     ret = silk_Get_Encoder_Size( &silkEncSizeBytes );
     if (ret)
@@ -240,17 +258,18 @@ int opus_encoder_init(OpusEncoder* st, o
     st->hybrid_stereo_width_Q14 = 1 << 14;
     st->prev_HB_gain = Q15ONE;
     st->variable_HP_smth2_Q15 = silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 );
     st->first = 1;
     st->mode = MODE_HYBRID;
     st->bandwidth = OPUS_BANDWIDTH_FULLBAND;
 
 #ifndef DISABLE_FLOAT_API
-    tonality_analysis_init(&st->analysis);
+    tonality_analysis_init(&st->analysis, st->Fs);
+    st->analysis.application = st->application;
 #endif
 
     return OPUS_OK;
 }
 
 static unsigned char gen_toc(int mode, int framerate, int bandwidth, int channels)
 {
    int period;
@@ -318,20 +337,21 @@ static void silk_biquad_float(
         S[ 1 ] = - vout*A[1] + B[2]*inval + VERY_SMALL;
 
         /* Scale back to Q0 and saturate */
         out[ k*stride ] = vout;
     }
 }
 #endif
 
-static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
+static void hp_cutoff(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs, int arch)
 {
    opus_int32 B_Q28[ 3 ], A_Q28[ 2 ];
    opus_int32 Fc_Q19, r_Q28, r_Q22;
+   (void)arch;
 
    silk_assert( cutoff_Hz <= silk_int32_MAX / SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ) );
    Fc_Q19 = silk_DIV32_16( silk_SMULBB( SILK_FIX_CONST( 1.5 * 3.14159 / 1000, 19 ), cutoff_Hz ), Fs/1000 );
    silk_assert( Fc_Q19 > 0 && Fc_Q19 < 32768 );
 
    r_Q28 = SILK_FIX_CONST( 1.0, 28 ) - silk_MUL( SILK_FIX_CONST( 0.92, 9 ), Fc_Q19 );
 
    /* b = r * [ 1; -2; 1 ]; */
@@ -341,19 +361,20 @@ static void hp_cutoff(const opus_val16 *
    B_Q28[ 2 ] = r_Q28;
 
    /* -r * ( 2 - Fc * Fc ); */
    r_Q22  = silk_RSHIFT( r_Q28, 6 );
    A_Q28[ 0 ] = silk_SMULWW( r_Q22, silk_SMULWW( Fc_Q19, Fc_Q19 ) - SILK_FIX_CONST( 2.0,  22 ) );
    A_Q28[ 1 ] = silk_SMULWW( r_Q22, r_Q22 );
 
 #ifdef FIXED_POINT
-   silk_biquad_alt( in, B_Q28, A_Q28, hp_mem, out, len, channels );
-   if( channels == 2 ) {
-       silk_biquad_alt( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
+   if( channels == 1 ) {
+      silk_biquad_alt_stride1( in, B_Q28, A_Q28, hp_mem, out, len );
+   } else {
+      silk_biquad_alt_stride2( in, B_Q28, A_Q28, hp_mem, out, len, arch );
    }
 #else
    silk_biquad_float( in, B_Q28, A_Q28, hp_mem, out, len, channels );
    if( channels == 2 ) {
        silk_biquad_float( in+1, B_Q28, A_Q28, hp_mem+2, out+1, len, channels );
    }
 #endif
 }
@@ -366,49 +387,82 @@ static void dc_reject(const opus_val16 *
 
    /* Approximates -round(log2(4.*cutoff_Hz/Fs)) */
    shift=celt_ilog2(Fs/(cutoff_Hz*3));
    for (c=0;c<channels;c++)
    {
       for (i=0;i<len;i++)
       {
          opus_val32 x, tmp, y;
-         x = SHL32(EXTEND32(in[channels*i+c]), 15);
+         x = SHL32(EXTEND32(in[channels*i+c]), 14);
          /* First stage */
          tmp = x-hp_mem[2*c];
          hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift);
          /* Second stage */
          y = tmp - hp_mem[2*c+1];
          hp_mem[2*c+1] = hp_mem[2*c+1] + PSHR32(tmp - hp_mem[2*c+1], shift);
-         out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 15), 32767));
+         out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 14), 32767));
       }
    }
 }
 
 #else
 static void dc_reject(const opus_val16 *in, opus_int32 cutoff_Hz, opus_val16 *out, opus_val32 *hp_mem, int len, int channels, opus_int32 Fs)
 {
-   int c, i;
-   float coef;
-
+   int i;
+   float coef, coef2;
    coef = 4.0f*cutoff_Hz/Fs;
-   for (c=0;c<channels;c++)
+   coef2 = 1-coef;
+   if (channels==2)
    {
+      float m0, m1, m2, m3;
+      m0 = hp_mem[0];
+      m1 = hp_mem[1];
+      m2 = hp_mem[2];
+      m3 = hp_mem[3];
+      for (i=0;i<len;i++)
+      {
+         opus_val32 x0, x1, tmp0, tmp1, out0, out1;
+         x0 = in[2*i+0];
+         x1 = in[2*i+1];
+         /* First stage */
+         tmp0 = x0-m0;
+         tmp1 = x1-m2;
+         m0 = coef*x0 + VERY_SMALL + coef2*m0;
+         m2 = coef*x1 + VERY_SMALL + coef2*m2;
+         /* Second stage */
+         out0 = tmp0 - m1;
+         out1 = tmp1 - m3;
+         m1 = coef*tmp0 + VERY_SMALL + coef2*m1;
+         m3 = coef*tmp1 + VERY_SMALL + coef2*m3;
+         out[2*i+0] = out0;
+         out[2*i+1] = out1;
+      }
+      hp_mem[0] = m0;
+      hp_mem[1] = m1;
+      hp_mem[2] = m2;
+      hp_mem[3] = m3;
+   } else {
+      float m0, m1;
+      m0 = hp_mem[0];
+      m1 = hp_mem[1];
       for (i=0;i<len;i++)
       {
          opus_val32 x, tmp, y;
-         x = in[channels*i+c];
+         x = in[i];
          /* First stage */
-         tmp = x-hp_mem[2*c];
-         hp_mem[2*c] = hp_mem[2*c] + coef*(x - hp_mem[2*c]) + VERY_SMALL;
+         tmp = x-m0;
+         m0 = coef*x + VERY_SMALL + coef2*m0;
          /* Second stage */
-         y = tmp - hp_mem[2*c+1];
-         hp_mem[2*c+1] = hp_mem[2*c+1] + coef*(tmp - hp_mem[2*c+1]) + VERY_SMALL;
-         out[channels*i+c] = y;
+         y = tmp - m1;
+         m1 = coef*tmp + VERY_SMALL + coef2*m1;
+         out[i] = y;
       }
+      hp_mem[0] = m0;
+      hp_mem[1] = m1;
    }
 }
 #endif
 
 static void stereo_fade(const opus_val16 *in, opus_val16 *out, opus_val16 g1, opus_val16 g2,
         int overlap48, int frame_size, int channels, const opus_val16 *window, opus_int32 Fs)
 {
     int i;
@@ -516,353 +570,94 @@ static opus_int32 user_bitrate_to_bitrat
     return 60*st->Fs/frame_size + st->Fs*st->channels;
   else if (st->user_bitrate_bps==OPUS_BITRATE_MAX)
     return max_data_bytes*8*st->Fs/frame_size;
   else
     return st->user_bitrate_bps;
 }
 
 #ifndef DISABLE_FLOAT_API
-/* Don't use more than 60 ms for the frame size analysis */
-#define MAX_DYNAMIC_FRAMESIZE 24
-/* Estimates how much the bitrate will be boosted based on the sub-frame energy */
-static float transient_boost(const float *E, const float *E_1, int LM, int maxM)
-{
-   int i;
-   int M;
-   float sumE=0, sumE_1=0;
-   float metric;
-
-   M = IMIN(maxM, (1<<LM)+1);
-   for (i=0;i<M;i++)
-   {
-      sumE += E[i];
-      sumE_1 += E_1[i];
-   }
-   metric = sumE*sumE_1/(M*M);
-   /*if (LM==3)
-      printf("%f\n", metric);*/
-   /*return metric>10 ? 1 : 0;*/
-   /*return MAX16(0,1-exp(-.25*(metric-2.)));*/
-   return MIN16(1,(float)sqrt(MAX16(0,.05f*(metric-2))));
-}
-
-/* Viterbi decoding trying to find the best frame size combination using look-ahead
-
-   State numbering:
-    0: unused
-    1:  2.5 ms
-    2:  5 ms (#1)
-    3:  5 ms (#2)
-    4: 10 ms (#1)
-    5: 10 ms (#2)
-    6: 10 ms (#3)
-    7: 10 ms (#4)
-    8: 20 ms (#1)
-    9: 20 ms (#2)
-   10: 20 ms (#3)
-   11: 20 ms (#4)
-   12: 20 ms (#5)
-   13: 20 ms (#6)
-   14: 20 ms (#7)
-   15: 20 ms (#8)
-*/
-static int transient_viterbi(const float *E, const float *E_1, int N, int frame_cost, int rate)
-{
-   int i;
-   float cost[MAX_DYNAMIC_FRAMESIZE][16];
-   int states[MAX_DYNAMIC_FRAMESIZE][16];
-   float best_cost;
-   int best_state;
-   float factor;
-   /* Take into account that we damp VBR in the 32 kb/s to 64 kb/s range. */
-   if (rate<80)
-      factor=0;
-   else if (rate>160)
-      factor=1;
-   else
-      factor = (rate-80.f)/80.f;
-   /* Makes variable framesize less aggressive at lower bitrates, but I can't
-      find any valid theoretical justification for this (other than it seems
-      to help) */
-   for (i=0;i<16;i++)
-   {
-      /* Impossible state */
-      states[0][i] = -1;
-      cost[0][i] = 1e10;
-   }
-   for (i=0;i<4;i++)
-   {
-      cost[0][1<<i] = (frame_cost + rate*(1<<i))*(1+factor*transient_boost(E, E_1, i, N+1));
-      states[0][1<<i] = i;
-   }
-   for (i=1;i<N;i++)
-   {
-      int j;
-
-      /* Follow continuations */
-      for (j=2;j<16;j++)
-      {
-         cost[i][j] = cost[i-1][j-1];
-         states[i][j] = j-1;
-      }
-
-      /* New frames */
-      for(j=0;j<4;j++)
-      {
-         int k;
-         float min_cost;
-         float curr_cost;
-         states[i][1<<j] = 1;
-         min_cost = cost[i-1][1];
-         for(k=1;k<4;k++)
-         {
-            float tmp = cost[i-1][(1<<(k+1))-1];
-            if (tmp < min_cost)
-            {
-               states[i][1<<j] = (1<<(k+1))-1;
-               min_cost = tmp;
-            }
-         }
-         curr_cost = (frame_cost + rate*(1<<j))*(1+factor*transient_boost(E+i, E_1+i, j, N-i+1));
-         cost[i][1<<j] = min_cost;
-         /* If part of the frame is outside the analysis window, only count part of the cost */
-         if (N-i < (1<<j))
-            cost[i][1<<j] += curr_cost*(float)(N-i)/(1<<j);
-         else
-            cost[i][1<<j] += curr_cost;
-      }
-   }
-
-   best_state=1;
-   best_cost = cost[N-1][1];
-   /* Find best end state (doesn't force a frame to end at N-1) */
-   for (i=2;i<16;i++)
-   {
-      if (cost[N-1][i]<best_cost)
-      {
-         best_cost = cost[N-1][i];
-         best_state = i;
-      }
-   }
-
-   /* Follow transitions back */
-   for (i=N-1;i>=0;i--)
-   {
-      /*printf("%d ", best_state);*/
-      best_state = states[i][best_state];
-   }
-   /*printf("%d\n", best_state);*/
-   return best_state;
-}
-
-static int optimize_framesize(const void *x, int len, int C, opus_int32 Fs,
-                int bitrate, opus_val16 tonality, float *mem, int buffering,
-                downmix_func downmix)
-{
-   int N;
-   int i;
-   float e[MAX_DYNAMIC_FRAMESIZE+4];
-   float e_1[MAX_DYNAMIC_FRAMESIZE+3];
-   opus_val32 memx;
-   int bestLM=0;
-   int subframe;
-   int pos;
-   int offset;
-   VARDECL(opus_val32, sub);
-
-   subframe = Fs/400;
-   ALLOC(sub, subframe, opus_val32);
-   e[0]=mem[0];
-   e_1[0]=1.f/(EPSILON+mem[0]);
-   if (buffering)
-   {
-      /* Consider the CELT delay when not in restricted-lowdelay */
-      /* We assume the buffering is between 2.5 and 5 ms */
-      offset = 2*subframe - buffering;
-      celt_assert(offset>=0 && offset <= subframe);
-      len -= offset;
-      e[1]=mem[1];
-      e_1[1]=1.f/(EPSILON+mem[1]);
-      e[2]=mem[2];
-      e_1[2]=1.f/(EPSILON+mem[2]);
-      pos = 3;
-   } else {
-      pos=1;
-      offset=0;
-   }
-   N=IMIN(len/subframe, MAX_DYNAMIC_FRAMESIZE);
-   /* Just silencing a warning, it's really initialized later */
-   memx = 0;
-   for (i=0;i<N;i++)
-   {
-      float tmp;
-      opus_val32 tmpx;
-      int j;
-      tmp=EPSILON;
-
-      downmix(x, sub, subframe, i*subframe+offset, 0, -2, C);
-      if (i==0)
-         memx = sub[0];
-      for (j=0;j<subframe;j++)
-      {
-         tmpx = sub[j];
-         tmp += (tmpx-memx)*(float)(tmpx-memx);
-         memx = tmpx;
-      }
-      e[i+pos] = tmp;
-      e_1[i+pos] = 1.f/tmp;
-   }
-   /* Hack to get 20 ms working with APPLICATION_AUDIO
-      The real problem is that the corresponding memory needs to use 1.5 ms
-      from this frame and 1 ms from the next frame */
-   e[i+pos] = e[i+pos-1];
-   if (buffering)
-      N=IMIN(MAX_DYNAMIC_FRAMESIZE, N+2);
-   bestLM = transient_viterbi(e, e_1, N, (int)((1.f+.5f*tonality)*(60*C+40)), bitrate/400);
-   mem[0] = e[1<<bestLM];
-   if (buffering)
-   {
-      mem[1] = e[(1<<bestLM)+1];
-      mem[2] = e[(1<<bestLM)+2];
-   }
-   return bestLM;
-}
-
-#endif
-
-#ifndef DISABLE_FLOAT_API
 #ifdef FIXED_POINT
 #define PCM2VAL(x) FLOAT2INT16(x)
 #else
 #define PCM2VAL(x) SCALEIN(x)
 #endif
-void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C)
+
+void downmix_float(const void *_x, opus_val32 *y, int subframe, int offset, int c1, int c2, int C)
 {
    const float *x;
-   opus_val32 scale;
    int j;
+
    x = (const float *)_x;
    for (j=0;j<subframe;j++)
-      sub[j] = PCM2VAL(x[(j+offset)*C+c1]);
+      y[j] = PCM2VAL(x[(j+offset)*C+c1]);
    if (c2>-1)
    {
       for (j=0;j<subframe;j++)
-         sub[j] += PCM2VAL(x[(j+offset)*C+c2]);
+         y[j] += PCM2VAL(x[(j+offset)*C+c2]);
    } else if (c2==-2)
    {
       int c;
       for (c=1;c<C;c++)
       {
          for (j=0;j<subframe;j++)
-            sub[j] += PCM2VAL(x[(j+offset)*C+c]);
+            y[j] += PCM2VAL(x[(j+offset)*C+c]);
       }
    }
-#ifdef FIXED_POINT
-   scale = (1<<SIG_SHIFT);
-#else
-   scale = 1.f;
-#endif
-   if (C==-2)
-      scale /= C;
-   else
-      scale /= 2;
-   for (j=0;j<subframe;j++)
-      sub[j] *= scale;
 }
 #endif
 
-void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C)
+void downmix_int(const void *_x, opus_val32 *y, int subframe, int offset, int c1, int c2, int C)
 {
    const opus_int16 *x;
-   opus_val32 scale;
    int j;
+
    x = (const opus_int16 *)_x;
    for (j=0;j<subframe;j++)
-      sub[j] = x[(j+offset)*C+c1];
+      y[j] = x[(j+offset)*C+c1];
    if (c2>-1)
    {
       for (j=0;j<subframe;j++)
-         sub[j] += x[(j+offset)*C+c2];
+         y[j] += x[(j+offset)*C+c2];
    } else if (c2==-2)
    {
       int c;
       for (c=1;c<C;c++)
       {
          for (j=0;j<subframe;j++)
-            sub[j] += x[(j+offset)*C+c];
+            y[j] += x[(j+offset)*C+c];
       }
    }
-#ifdef FIXED_POINT
-   scale = (1<<SIG_SHIFT);
-#else
-   scale = 1.f/32768;
-#endif
-   if (C==-2)
-      scale /= C;
-   else
-      scale /= 2;
-   for (j=0;j<subframe;j++)
-      sub[j] *= scale;
 }
 
 opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs)
 {
    int new_size;
    if (frame_size<Fs/400)
       return -1;
    if (variable_duration == OPUS_FRAMESIZE_ARG)
       new_size = frame_size;
-   else if (variable_duration == OPUS_FRAMESIZE_VARIABLE)
-      new_size = Fs/50;
-   else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_60_MS)
-      new_size = IMIN(3*Fs/50, (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS));
+   else if (variable_duration >= OPUS_FRAMESIZE_2_5_MS && variable_duration <= OPUS_FRAMESIZE_120_MS)
+   {
+      if (variable_duration <= OPUS_FRAMESIZE_40_MS)
+         new_size = (Fs/400)<<(variable_duration-OPUS_FRAMESIZE_2_5_MS);
+      else
+         new_size = (variable_duration-OPUS_FRAMESIZE_2_5_MS-2)*Fs/50;
+   }
    else
       return -1;
    if (new_size>frame_size)
       return -1;
-   if (400*new_size!=Fs && 200*new_size!=Fs && 100*new_size!=Fs &&
-            50*new_size!=Fs && 25*new_size!=Fs && 50*new_size!=3*Fs)
+   if (400*new_size!=Fs   && 200*new_size!=Fs   && 100*new_size!=Fs   &&
+        50*new_size!=Fs   &&  25*new_size!=Fs   &&  50*new_size!=3*Fs &&
+        50*new_size!=4*Fs &&  50*new_size!=5*Fs &&  50*new_size!=6*Fs)
       return -1;
    return new_size;
 }
 
-opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
-      int variable_duration, int C, opus_int32 Fs, int bitrate_bps,
-      int delay_compensation, downmix_func downmix
-#ifndef DISABLE_FLOAT_API
-      , float *subframe_mem
-#endif
-      )
-{
-#ifndef DISABLE_FLOAT_API
-   if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200)
-   {
-      int LM = 3;
-      LM = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps,
-            0, subframe_mem, delay_compensation, downmix);
-      while ((Fs/400<<LM)>frame_size)
-         LM--;
-      frame_size = (Fs/400<<LM);
-   } else
-#else
-   (void)analysis_pcm;
-   (void)C;
-   (void)bitrate_bps;
-   (void)delay_compensation;
-   (void)downmix;
-#endif
-   {
-      frame_size = frame_size_select(frame_size, variable_duration, Fs);
-   }
-   if (frame_size<0)
-      return -1;
-   return frame_size;
-}
-
 opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
 {
    opus_val32 xx, xy, yy;
    opus_val16 sqrt_xx, sqrt_yy;
    opus_val16 qrrt_xx, qrrt_yy;
    int frame_rate;
    int i;
    opus_val16 short_alpha;
@@ -929,16 +724,358 @@ opus_val16 compute_stereo_width(const op
       mem->smoothed_width += (width-mem->smoothed_width)/frame_rate;
       /* Peak follower */
       mem->max_follower = MAX16(mem->max_follower-QCONST16(.02f,15)/frame_rate, mem->smoothed_width);
    }
    /*printf("%f %f %f %f %f ", corr/(float)Q15ONE, ldiff/(float)Q15ONE, width/(float)Q15ONE, mem->smoothed_width/(float)Q15ONE, mem->max_follower/(float)Q15ONE);*/
    return EXTRACT16(MIN32(Q15ONE, MULT16_16(20, mem->max_follower)));
 }
 
+static int decide_fec(int useInBandFEC, int PacketLoss_perc, int last_fec, int mode, int *bandwidth, opus_int32 rate)
+{
+   int orig_bandwidth;
+   if (!useInBandFEC || PacketLoss_perc == 0 || mode == MODE_CELT_ONLY)
+      return 0;
+   orig_bandwidth = *bandwidth;
+   for (;;)
+   {
+      opus_int32 hysteresis;
+      opus_int32 LBRR_rate_thres_bps;
+      /* Compute threshold for using FEC at the current bandwidth setting */
+      LBRR_rate_thres_bps = fec_thresholds[2*(*bandwidth - OPUS_BANDWIDTH_NARROWBAND)];
+      hysteresis = fec_thresholds[2*(*bandwidth - OPUS_BANDWIDTH_NARROWBAND) + 1];
+      if (last_fec == 1) LBRR_rate_thres_bps -= hysteresis;
+      if (last_fec == 0) LBRR_rate_thres_bps += hysteresis;
+      LBRR_rate_thres_bps = silk_SMULWB( silk_MUL( LBRR_rate_thres_bps,
+            125 - silk_min( PacketLoss_perc, 25 ) ), SILK_FIX_CONST( 0.01, 16 ) );
+      /* If loss <= 5%, we look at whether we have enough rate to enable FEC.
+         If loss > 5%, we decrease the bandwidth until we can enable FEC. */
+      if (rate > LBRR_rate_thres_bps)
+         return 1;
+      else if (PacketLoss_perc <= 5)
+         return 0;
+      else if (*bandwidth > OPUS_BANDWIDTH_NARROWBAND)
+         (*bandwidth)--;
+      else
+         break;
+   }
+   /* Couldn't find any bandwidth to enable FEC, keep original bandwidth. */
+   *bandwidth = orig_bandwidth;
+   return 0;
+}
+
+static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms, int vbr, int fec) {
+   int entry;
+   int i;
+   int N;
+   int silk_rate;
+   static int rate_table[][5] = {
+  /*  |total| |-------- SILK------------|
+              |-- No FEC -| |--- FEC ---|
+               10ms   20ms   10ms   20ms */
+      {    0,     0,     0,     0,     0},
+      {12000, 10000, 10000, 11000, 11000},
+      {16000, 13500, 13500, 15000, 15000},
+      {20000, 16000, 16000, 18000, 18000},
+      {24000, 18000, 18000, 21000, 21000},
+      {32000, 22000, 22000, 28000, 28000},
+      {64000, 38000, 38000, 50000, 50000}
+   };
+   entry = 1 + frame20ms + 2*fec;
+   N = sizeof(rate_table)/sizeof(rate_table[0]);
+   for (i=1;i<N;i++)
+   {
+      if (rate_table[i][0] > rate) break;
+   }
+   if (i == N)
+   {
+      silk_rate = rate_table[i-1][entry];
+      /* For now, just give 50% of the extra bits to SILK. */
+      silk_rate += (rate-rate_table[i-1][0])/2;
+   } else {
+      opus_int32 lo, hi, x0, x1;
+      lo = rate_table[i-1][entry];
+      hi = rate_table[i][entry];
+      x0 = rate_table[i-1][0];
+      x1 = rate_table[i][0];
+      silk_rate = (lo*(x1-rate) + hi*(rate-x0))/(x1-x0);
+   }
+   if (!vbr)
+   {
+      /* Tiny boost to SILK for CBR. We should probably tune this better. */
+      silk_rate += 100;
+   }
+   if (bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND)
+      silk_rate += 300;
+   return silk_rate;
+}
+
+/* Returns the equivalent bitrate corresponding to 20 ms frames,
+   complexity 10 VBR operation. */
+static opus_int32 compute_equiv_rate(opus_int32 bitrate, int channels,
+      int frame_rate, int vbr, int mode, int complexity, int loss)
+{
+   opus_int32 equiv;
+   equiv = bitrate;
+   /* Take into account overhead from smaller frames. */
+   equiv -= (40*channels+20)*(frame_rate - 50);
+   /* CBR is about a 8% penalty for both SILK and CELT. */
+   if (!vbr)
+      equiv -= equiv/12;
+   /* Complexity makes about 10% difference (from 0 to 10) in general. */
+   equiv = equiv * (90+complexity)/100;
+   if (mode == MODE_SILK_ONLY || mode == MODE_HYBRID)
+   {
+      /* SILK complexity 0-1 uses the non-delayed-decision NSQ, which
+         costs about 20%. */
+      if (complexity<2)
+         equiv = equiv*4/5;
+      equiv -= equiv*loss/(6*loss + 10);
+   } else if (mode == MODE_CELT_ONLY) {
+      /* CELT complexity 0-4 doesn't have the pitch filter, which costs
+         about 10%. */
+      if (complexity<5)
+         equiv = equiv*9/10;
+   } else {
+      /* Mode not known yet */
+      /* Half the SILK loss*/
+      equiv -= equiv*loss/(12*loss + 20);
+   }
+   return equiv;
+}
+
+#ifndef DISABLE_FLOAT_API
+
+static int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth)
+{
+   int silence = 0;
+   opus_val32 sample_max = 0;
+#ifdef MLP_TRAINING
+   return 0;
+#endif
+   sample_max = celt_maxabs16(pcm, frame_size*channels);
+
+#ifdef FIXED_POINT
+   silence = (sample_max == 0);
+   (void)lsb_depth;
+#else
+   silence = (sample_max <= (opus_val16) 1 / (1 << lsb_depth));
+#endif
+
+   return silence;
+}
+
+#ifdef FIXED_POINT
+static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
+{
+   int i;
+   opus_val32 sample_max;
+   int max_shift;
+   int shift;
+   opus_val32 energy = 0;
+   int len = frame_size*channels;
+   (void)arch;
+   /* Max amplitude in the signal */
+   sample_max = celt_maxabs16(pcm, len);
+
+   /* Compute the right shift required in the MAC to avoid an overflow */
+   max_shift = celt_ilog2(len);
+   shift = IMAX(0, (celt_ilog2(sample_max) << 1) + max_shift - 28);
+
+   /* Compute the energy */
+   for (i=0; i<len; i++)
+      energy += SHR32(MULT16_16(pcm[i], pcm[i]), shift);
+
+   /* Normalize energy by the frame size and left-shift back to the original position */
+   energy /= len;
+   energy = SHL32(energy, shift);
+
+   return energy;
+}
+#else
+static opus_val32 compute_frame_energy(const opus_val16 *pcm, int frame_size, int channels, int arch)
+{
+   int len = frame_size*channels;
+   return celt_inner_prod(pcm, pcm, len, arch)/len;
+}
+#endif
+
+/* Decides if DTX should be turned on (=1) or off (=0) */
+static int decide_dtx_mode(float activity_probability,    /* probability that current frame contains speech/music */
+                           int *nb_no_activity_frames,    /* number of consecutive frames with no activity */
+                           opus_val32 peak_signal_energy, /* peak energy of desired signal detected so far */
+                           const opus_val16 *pcm,         /* input pcm signal */
+                           int frame_size,                /* frame size */
+                           int channels,
+                           int is_silence,                 /* only digital silence detected in this frame */
+                           int arch
+                          )
+{
+   int is_noise;
+   opus_val32 noise_energy;
+   int is_sufficiently_quiet;
+
+   if (!is_silence)
+   {
+      is_noise = activity_probability < DTX_ACTIVITY_THRESHOLD;
+      if (is_noise)
+      {
+         noise_energy = compute_frame_energy(pcm, frame_size, channels, arch);
+         is_sufficiently_quiet = peak_signal_energy >= (PSEUDO_SNR_THRESHOLD * noise_energy);
+      }
+   }
+
+   if (is_silence || (is_noise && is_sufficiently_quiet))
+   {
+      /* The number of consecutive DTX frames should be within the allowed bounds */
+      (*nb_no_activity_frames)++;
+
+      if (*nb_no_activity_frames > NB_SPEECH_FRAMES_BEFORE_DTX)
+      {
+         if (*nb_no_activity_frames <= (NB_SPEECH_FRAMES_BEFORE_DTX + MAX_CONSECUTIVE_DTX))
+            /* Valid frame for DTX! */
+            return 1;
+         else
+            (*nb_no_activity_frames) = NB_SPEECH_FRAMES_BEFORE_DTX;
+      }
+   } else
+      (*nb_no_activity_frames) = 0;
+
+   return 0;
+}
+
+#endif
+
+static opus_int32 encode_multiframe_packet(OpusEncoder *st,
+                                           const opus_val16 *pcm,
+                                           int nb_frames,
+                                           int frame_size,
+                                           unsigned char *data,
+                                           opus_int32 out_data_bytes,
+                                           int to_celt,
+                                           int lsb_depth,
+                                           int float_api)
+{
+   int i;
+   int ret = 0;
+   VARDECL(unsigned char, tmp_data);
+   int bak_mode, bak_bandwidth, bak_channels, bak_to_mono;
+   VARDECL(OpusRepacketizer, rp);
+   int max_header_bytes;
+   opus_int32 bytes_per_frame;
+   opus_int32 cbr_bytes;
+   opus_int32 repacketize_len;
+   int tmp_len;
+   ALLOC_STACK;
+
+   /* Worst cases:
+    * 2 frames: Code 2 with different compressed sizes
+    * >2 frames: Code 3 VBR */
+   max_header_bytes = nb_frames == 2 ? 3 : (2+(nb_frames-1)*2);
+
+   if (st->use_vbr || st->user_bitrate_bps==OPUS_BITRATE_MAX)
+      repacketize_len = out_data_bytes;
+   else {
+      cbr_bytes = 3*st->bitrate_bps/(3*8*st->Fs/(frame_size*nb_frames));
+      repacketize_len = IMIN(cbr_bytes, out_data_bytes);
+   }
+   bytes_per_frame = IMIN(1276, 1+(repacketize_len-max_header_bytes)/nb_frames);
+
+   ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char);
+   ALLOC(rp, 1, OpusRepacketizer);
+   opus_repacketizer_init(rp);
+
+   bak_mode = st->user_forced_mode;
+   bak_bandwidth = st->user_bandwidth;
+   bak_channels = st->force_channels;
+
+   st->user_forced_mode = st->mode;
+   st->user_bandwidth = st->bandwidth;
+   st->force_channels = st->stream_channels;
+
+   bak_to_mono = st->silk_mode.toMono;
+   if (bak_to_mono)
+      st->force_channels = 1;
+   else
+      st->prev_channels = st->stream_channels;
+
+   for (i=0;i<nb_frames;i++)
+   {
+      st->silk_mode.toMono = 0;
+      st->nonfinal_frame = i<(nb_frames-1);
+
+      /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */
+      if (to_celt && i==nb_frames-1)
+         st->user_forced_mode = MODE_CELT_ONLY;
+
+      tmp_len = opus_encode_native(st, pcm+i*(st->channels*frame_size), frame_size,
+         tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth, NULL, 0, 0, 0, 0,
+         NULL, float_api);
+
+      if (tmp_len<0)
+      {
+         RESTORE_STACK;
+         return OPUS_INTERNAL_ERROR;
+      }
+
+      ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len);
+
+      if (ret<0)
+      {
+         RESTORE_STACK;
+         return OPUS_INTERNAL_ERROR;
+      }
+   }
+
+   ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr);
+
+   if (ret<0)
+   {
+      RESTORE_STACK;
+      return OPUS_INTERNAL_ERROR;
+   }
+
+   /* Discard configs that were forced locally for the purpose of repacketization */
+   st->user_forced_mode = bak_mode;
+   st->user_bandwidth = bak_bandwidth;
+   st->force_channels = bak_channels;
+   st->silk_mode.toMono = bak_to_mono;
+
+   RESTORE_STACK;
+   return ret;
+}
+
+static int compute_redundancy_bytes(opus_int32 max_data_bytes, opus_int32 bitrate_bps, int frame_rate, int channels)
+{
+   int redundancy_bytes_cap;
+   int redundancy_bytes;
+   opus_int32 redundancy_rate;
+   int base_bits;
+   opus_int32 available_bits;
+   base_bits = (40*channels+20);
+
+   /* Equivalent rate for 5 ms frames. */
+   redundancy_rate = bitrate_bps + base_bits*(200 - frame_rate);
+   /* For VBR, further increase the bitrate if we can afford it. It's pretty short
+      and we'll avoid artefacts. */
+   redundancy_rate = 3*redundancy_rate/2;
+   redundancy_bytes = redundancy_rate/1600;
+
+   /* Compute the max rate we can use given CBR or VBR with cap. */
+   available_bits = max_data_bytes*8 - 2*base_bits;
+   redundancy_bytes_cap = (available_bits*240/(240+48000/frame_rate) + base_bits)/8;
+   redundancy_bytes = IMIN(redundancy_bytes, redundancy_bytes_cap);
+   /* It we can't get enough bits for redundancy to be worth it, rely on the decoder PLC. */
+   if (redundancy_bytes > 4 + 8*channels)
+      redundancy_bytes = IMIN(257, redundancy_bytes);
+   else
+      redundancy_bytes = 0;
+   return redundancy_bytes;
+}
+
 opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
                 unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
                 const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
                 int analysis_channels, downmix_func downmix, int float_api)
 {
     void *silk_enc;
     CELTEncoder *celt_enc;
     int i;
@@ -966,65 +1103,87 @@ opus_int32 opus_encode_native(OpusEncode
     opus_int32 max_data_bytes; /* Max number of bytes we're allowed to use */
     int total_buffer;
     opus_val16 stereo_width;
     const CELTMode *celt_mode;
 #ifndef DISABLE_FLOAT_API
     AnalysisInfo analysis_info;
     int analysis_read_pos_bak=-1;
     int analysis_read_subframe_bak=-1;
+    int is_silence = 0;
 #endif
     VARDECL(opus_val16, tmp_prefill);
 
     ALLOC_STACK;
 
     max_data_bytes = IMIN(1276, out_data_bytes);
 
     st->rangeFinal = 0;
-    if ((!st->variable_duration && 400*frame_size != st->Fs && 200*frame_size != st->Fs && 100*frame_size != st->Fs &&
-         50*frame_size != st->Fs &&  25*frame_size != st->Fs &&  50*frame_size != 3*st->Fs)
-         || (400*frame_size < st->Fs)
-         || max_data_bytes<=0
-         )
+    if (frame_size <= 0 || max_data_bytes <= 0)
     {
        RESTORE_STACK;
        return OPUS_BAD_ARG;
     }
+
+    /* Cannot encode 100 ms in 1 byte */
+    if (max_data_bytes==1 && st->Fs==(frame_size*10))
+    {
+      RESTORE_STACK;
+      return OPUS_BUFFER_TOO_SMALL;
+    }
+
     silk_enc = (char*)st+st->silk_enc_offset;
     celt_enc = (CELTEncoder*)((char*)st+st->celt_enc_offset);
     if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
        delay_compensation = 0;
     else
        delay_compensation = st->delay_compensation;
 
     lsb_depth = IMIN(lsb_depth, st->lsb_depth);
 
     celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode));
 #ifndef DISABLE_FLOAT_API
     analysis_info.valid = 0;
 #ifdef FIXED_POINT
-    if (st->silk_mode.complexity >= 10 && st->Fs==48000)
+    if (st->silk_mode.complexity >= 10 && st->Fs>=16000)
 #else
-    if (st->silk_mode.complexity >= 7 && st->Fs==48000)
+    if (st->silk_mode.complexity >= 7 && st->Fs>=16000)
 #endif
     {
-       analysis_read_pos_bak = st->analysis.read_pos;
-       analysis_read_subframe_bak = st->analysis.read_subframe;
-       run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size,
-             c1, c2, analysis_channels, st->Fs,
-             lsb_depth, downmix, &analysis_info);
+       if (is_digital_silence(pcm, frame_size, st->channels, lsb_depth))
+       {
+          is_silence = 1;
+       } else {
+          analysis_read_pos_bak = st->analysis.read_pos;
+          analysis_read_subframe_bak = st->analysis.read_subframe;
+          run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size,
+                c1, c2, analysis_channels, st->Fs,
+                lsb_depth, downmix, &analysis_info);
+       }
+
+       /* Track the peak signal energy */
+       if (!is_silence && analysis_info.activity_probability > DTX_ACTIVITY_THRESHOLD)
+          st->peak_signal_energy = MAX32(MULT16_32_Q15(QCONST16(0.999f, 15), st->peak_signal_energy),
+                compute_frame_energy(pcm, frame_size, st->channels, st->arch));
     }
 #else
     (void)analysis_pcm;
     (void)analysis_size;
+    (void)c1;
+    (void)c2;
+    (void)analysis_channels;
+    (void)downmix;
 #endif
 
-    st->voice_ratio = -1;
+#ifndef DISABLE_FLOAT_API
+    /* Reset voice_ratio if this frame is not silent or if analysis is disabled.
+     * Otherwise, preserve voice_ratio from the last non-silent frame */
+    if (!is_silence)
+      st->voice_ratio = -1;
 
-#ifndef DISABLE_FLOAT_API
     st->detected_bandwidth = 0;
     if (analysis_info.valid)
     {
        int analysis_bandwidth;
        if (st->signal_type == OPUS_AUTO)
           st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob));
 
        analysis_bandwidth = analysis_info.bandwidth;
@@ -1034,69 +1193,111 @@ opus_int32 opus_encode_native(OpusEncode
           st->detected_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
        else if (analysis_bandwidth<=16)
           st->detected_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
        else if (analysis_bandwidth<=18)
           st->detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
        else
           st->detected_bandwidth = OPUS_BANDWIDTH_FULLBAND;
     }
+#else
+    st->voice_ratio = -1;
 #endif
 
     if (st->channels==2 && st->force_channels!=1)
        stereo_width = compute_stereo_width(pcm, frame_size, st->Fs, &st->width_mem);
     else
        stereo_width = 0;
     total_buffer = delay_compensation;
     st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes);
 
     frame_rate = st->Fs/frame_size;
     if (!st->use_vbr)
     {
        int cbrBytes;
-       /* Multiply by 3 to make sure the division is exact. */
-       int frame_rate3 = 3*st->Fs/frame_size;
+       /* Multiply by 12 to make sure the division is exact. */
+       int frame_rate12 = 12*st->Fs/frame_size;
        /* We need to make sure that "int" values always fit in 16 bits. */
-       cbrBytes = IMIN( (3*st->bitrate_bps/8 + frame_rate3/2)/frame_rate3, max_data_bytes);
-       st->bitrate_bps = cbrBytes*(opus_int32)frame_rate3*8/3;
-       max_data_bytes = cbrBytes;
+       cbrBytes = IMIN( (12*st->bitrate_bps/8 + frame_rate12/2)/frame_rate12, max_data_bytes);
+       st->bitrate_bps = cbrBytes*(opus_int32)frame_rate12*8/12;
+       /* Make sure we provide at least one byte to avoid failing. */
+       max_data_bytes = IMAX(1, cbrBytes);
     }
     if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8
        || (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400)))
     {
        /*If the space is too low to do something useful, emit 'PLC' frames.*/
        int tocmode = st->mode;
        int bw = st->bandwidth == 0 ? OPUS_BANDWIDTH_NARROWBAND : st->bandwidth;
+       int packet_code = 0;
+       int num_multiframes = 0;
+
        if (tocmode==0)
           tocmode = MODE_SILK_ONLY;
        if (frame_rate>100)
           tocmode = MODE_CELT_ONLY;
-       if (frame_rate < 50)
-          tocmode = MODE_SILK_ONLY;
+       /* 40 ms -> 2 x 20 ms if in CELT_ONLY or HYBRID mode */
+       if (frame_rate==25 && tocmode!=MODE_SILK_ONLY)
+       {
+          frame_rate = 50;
+          packet_code = 1;
+       }
+
+       /* >= 60 ms frames */
+       if (frame_rate<=16)
+       {
+          /* 1 x 60 ms, 2 x 40 ms, 2 x 60 ms */
+          if (out_data_bytes==1 || (tocmode==MODE_SILK_ONLY && frame_rate!=10))
+          {
+             tocmode = MODE_SILK_ONLY;
+
+             packet_code = frame_rate <= 12;
+             frame_rate = frame_rate == 12 ? 25 : 16;
+          }
+          else
+          {
+             num_multiframes = 50/frame_rate;
+             frame_rate = 50;
+             packet_code = 3;
+          }
+       }
+
        if(tocmode==MODE_SILK_ONLY&&bw>OPUS_BANDWIDTH_WIDEBAND)
           bw=OPUS_BANDWIDTH_WIDEBAND;
        else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND)
           bw=OPUS_BANDWIDTH_NARROWBAND;
        else if (tocmode==MODE_HYBRID&&bw<=OPUS_BANDWIDTH_SUPERWIDEBAND)
           bw=OPUS_BANDWIDTH_SUPERWIDEBAND;
+
        data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels);
-       ret = 1;
+       data[0] |= packet_code;
+
+       ret = packet_code <= 1 ? 1 : 2;
+
+       max_data_bytes = IMAX(max_data_bytes, ret);
+
+       if (packet_code==3)
+          data[1] = num_multiframes;
+
        if (!st->use_vbr)
        {
           ret = opus_packet_pad(data, ret, max_data_bytes);
           if (ret == OPUS_OK)
              ret = max_data_bytes;
+          else
+             ret = OPUS_INTERNAL_ERROR;
        }
        RESTORE_STACK;
        return ret;
     }
     max_rate = frame_rate*max_data_bytes*8;
 
     /* Equivalent 20-ms rate for mode/channel/bandwidth decisions */
-    equiv_rate = st->bitrate_bps - (40*st->channels+20)*(st->Fs/frame_size - 50);
+    equiv_rate = compute_equiv_rate(st->bitrate_bps, st->channels, st->Fs/frame_size,
+          st->use_vbr, 0, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
 
     if (st->signal_type == OPUS_SIGNAL_VOICE)
        voice_est = 127;
     else if (st->signal_type == OPUS_SIGNAL_MUSIC)
        voice_est = 0;
     else if (st->voice_ratio >= 0)
     {
        voice_est = st->voice_ratio*327>>8;
@@ -1127,17 +1328,19 @@ opus_int32 opus_encode_native(OpusEncode
           else
              stereo_threshold += 1000;
           st->stream_channels = (equiv_rate > stereo_threshold) ? 2 : 1;
        } else {
           st->stream_channels = st->channels;
        }
 #endif
     }
-    equiv_rate = st->bitrate_bps - (40*st->stream_channels+20)*(st->Fs/frame_size - 50);
+    /* Update equivalent rate for channels decision. */
+    equiv_rate = compute_equiv_rate(st->bitrate_bps, st->stream_channels, st->Fs/frame_size,
+          st->use_vbr, 0, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
 
     /* Mode selection depending on application and signal type */
     if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
     {
        st->mode = MODE_CELT_ONLY;
     } else if (st->user_forced_mode == OPUS_AUTO)
     {
 #ifdef FUZZING
@@ -1176,42 +1379,40 @@ opus_int32 opus_encode_native(OpusEncode
        else if (st->prev_mode>0)
            threshold += 4000;
 
        st->mode = (equiv_rate >= threshold) ? MODE_CELT_ONLY: MODE_SILK_ONLY;
 
        /* When FEC is enabled and there's enough packet loss, use SILK */
        if (st->silk_mode.useInBandFEC && st->silk_mode.packetLossPercentage > (128-voice_est)>>4)
           st->mode = MODE_SILK_ONLY;
-       /* When encoding voice and DTX is enabled, set the encoder to SILK mode (at least for now) */
+       /* When encoding voice and DTX is enabled but the generalized DTX cannot be used,
+          because of complexity and sampling frequency settings, switch to SILK DTX and
+          set the encoder to SILK mode */
+#ifndef DISABLE_FLOAT_API
+       st->silk_mode.useDTX = st->use_dtx && !(analysis_info.valid || is_silence);
+#else
+       st->silk_mode.useDTX = st->use_dtx;
+#endif
        if (st->silk_mode.useDTX && voice_est > 100)
           st->mode = MODE_SILK_ONLY;
 #endif
+
+       /* If max_data_bytes represents less than 6 kb/s, switch to CELT-only mode */
+       if (max_data_bytes < (frame_rate > 50 ? 9000 : 6000)*frame_size / (st->Fs * 8))
+          st->mode = MODE_CELT_ONLY;
     } else {
        st->mode = st->user_forced_mode;
     }
 
     /* Override the chosen mode to make sure we meet the requested frame size */
     if (st->mode != MODE_CELT_ONLY && frame_size < st->Fs/100)
        st->mode = MODE_CELT_ONLY;
     if (st->lfe)
        st->mode = MODE_CELT_ONLY;
-    /* If max_data_bytes represents less than 8 kb/s, switch to CELT-only mode */
-    if (max_data_bytes < (frame_rate > 50 ? 12000 : 8000)*frame_size / (st->Fs * 8))
-       st->mode = MODE_CELT_ONLY;
-
-    if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0
-          && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)
-    {
-       /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */
-       st->silk_mode.toMono = 1;
-       st->stream_channels = 2;
-    } else {
-       st->silk_mode.toMono = 0;
-    }
 
     if (st->prev_mode > 0 &&
         ((st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ||
     (st->mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)))
     {
         redundancy = 1;
         celt_to_silk = (st->mode != MODE_CELT_ONLY);
         if (!celt_to_silk)
@@ -1221,58 +1422,47 @@ opus_int32 opus_encode_native(OpusEncode
             {
                 st->mode = st->prev_mode;
                 to_celt = 1;
             } else {
                 redundancy=0;
             }
         }
     }
-    /* For the first frame at a new SILK bandwidth */
-    if (st->silk_bw_switch)
+
+    /* When encoding multiframes, we can ask for a switch to CELT only in the last frame. This switch
+     * is processed above as the requested mode shouldn't interrupt stereo->mono transition. */
+    if (st->stream_channels == 1 && st->prev_channels ==2 && st->silk_mode.toMono==0
+          && st->mode != MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY)
     {
-       redundancy = 1;
-       celt_to_silk = 1;
-       st->silk_bw_switch = 0;
-       prefill=1;
+       /* Delay stereo->mono transition by two frames so that SILK can do a smooth downmix */
+       st->silk_mode.toMono = 1;
+       st->stream_channels = 2;
+    } else {
+       st->silk_mode.toMono = 0;
     }
 
-    if (redundancy)
-    {
-       /* Fair share of the max size allowed */
-       redundancy_bytes = IMIN(257, max_data_bytes*(opus_int32)(st->Fs/200)/(frame_size+st->Fs/200));
-       /* For VBR, target the actual bitrate (subject to the limit above) */
-       if (st->use_vbr)
-          redundancy_bytes = IMIN(redundancy_bytes, st->bitrate_bps/1600);
-    }
+    /* Update equivalent rate with mode decision. */
+    equiv_rate = compute_equiv_rate(st->bitrate_bps, st->stream_channels, st->Fs/frame_size,
+          st->use_vbr, st->mode, st->silk_mode.complexity, st->silk_mode.packetLossPercentage);
 
     if (st->mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY)
     {
         silk_EncControlStruct dummy;
         silk_InitEncoder( silk_enc, st->arch, &dummy);
         prefill=1;
     }
 
     /* Automatic (rate-dependent) bandwidth selection */
     if (st->mode == MODE_CELT_ONLY || st->first || st->silk_mode.allowBandwidthSwitch)
     {
         const opus_int32 *voice_bandwidth_thresholds, *music_bandwidth_thresholds;
         opus_int32 bandwidth_thresholds[8];
         int bandwidth = OPUS_BANDWIDTH_FULLBAND;
-        opus_int32 equiv_rate2;
 
-        equiv_rate2 = equiv_rate;
-        if (st->mode != MODE_CELT_ONLY)
-        {
-           /* Adjust the threshold +/- 10% depending on complexity */
-           equiv_rate2 = equiv_rate2 * (45+st->silk_mode.complexity)/50;
-           /* CBR is less efficient by ~1 kb/s */
-           if (!st->use_vbr)
-              equiv_rate2 -= 1000;
-        }
         if (st->channels==2 && st->force_channels!=1)
         {
            voice_bandwidth_thresholds = stereo_voice_bandwidth_thresholds;
            music_bandwidth_thresholds = stereo_music_bandwidth_thresholds;
         } else {
            voice_bandwidth_thresholds = mono_voice_bandwidth_thresholds;
            music_bandwidth_thresholds = mono_music_bandwidth_thresholds;
         }
@@ -1283,25 +1473,25 @@ opus_int32 opus_encode_native(OpusEncode
                     + ((voice_est*voice_est*(voice_bandwidth_thresholds[i]-music_bandwidth_thresholds[i]))>>14);
         }
         do {
             int threshold, hysteresis;
             threshold = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)];
             hysteresis = bandwidth_thresholds[2*(bandwidth-OPUS_BANDWIDTH_MEDIUMBAND)+1];
             if (!st->first)
             {
-                if (st->bandwidth >= bandwidth)
+                if (st->auto_bandwidth >= bandwidth)
                     threshold -= hysteresis;
                 else
                     threshold += hysteresis;
             }
-            if (equiv_rate2 >= threshold)
+            if (equiv_rate >= threshold)
                 break;
         } while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND);
-        st->bandwidth = bandwidth;
+        st->bandwidth = st->auto_bandwidth = bandwidth;
         /* Prevents any transition to SWB/FB until the SILK layer has fully
            switched to WB mode and turned the variable LP filter off */
         if (!st->first && st->mode != MODE_CELT_ONLY && !st->silk_mode.inWBmodeWithoutVariableLP && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)
             st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
     }
 
     if (st->bandwidth>st->max_bandwidth)
        st->bandwidth = st->max_bandwidth;
@@ -1344,110 +1534,90 @@ opus_int32 opus_encode_native(OpusEncode
           min_detected_bandwidth = OPUS_BANDWIDTH_SUPERWIDEBAND;
        else
           min_detected_bandwidth = OPUS_BANDWIDTH_FULLBAND;
 
        st->detected_bandwidth = IMAX(st->detected_bandwidth, min_detected_bandwidth);
        st->bandwidth = IMIN(st->bandwidth, st->detected_bandwidth);
     }
 #endif
+    st->silk_mode.LBRR_coded = decide_fec(st->silk_mode.useInBandFEC, st->silk_mode.packetLossPercentage,
+          st->silk_mode.LBRR_coded, st->mode, &st->bandwidth, equiv_rate);
     celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(lsb_depth));
 
     /* CELT mode doesn't support mediumband, use wideband instead */
     if (st->mode == MODE_CELT_ONLY && st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
         st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
     if (st->lfe)
        st->bandwidth = OPUS_BANDWIDTH_NARROWBAND;
 
-    /* Can't support higher than wideband for >20 ms frames */
-    if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
+    curr_bandwidth = st->bandwidth;
+
+    /* Chooses the appropriate mode for speech
+       *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */
+    if (st->mode == MODE_SILK_ONLY && curr_bandwidth > OPUS_BANDWIDTH_WIDEBAND)
+        st->mode = MODE_HYBRID;
+    if (st->mode == MODE_HYBRID && curr_bandwidth <= OPUS_BANDWIDTH_WIDEBAND)
+        st->mode = MODE_SILK_ONLY;
+
+    /* Can't support higher than >60 ms frames, and >20 ms when in Hybrid or CELT-only modes */
+    if ((frame_size > st->Fs/50 && (st->mode != MODE_SILK_ONLY)) || frame_size > 3*st->Fs/50)
     {
-       VARDECL(unsigned char, tmp_data);
+       int enc_frame_size;
        int nb_frames;
-       int bak_mode, bak_bandwidth, bak_channels, bak_to_mono;
-       VARDECL(OpusRepacketizer, rp);
-       opus_int32 bytes_per_frame;
-       opus_int32 repacketize_len;
+
+       if (st->mode == MODE_SILK_ONLY)
+       {
+         if (frame_size == 2*st->Fs/25)  /* 80 ms -> 2x 40 ms */
+           enc_frame_size = st->Fs/25;
+         else if (frame_size == 3*st->Fs/25)  /* 120 ms -> 2x 60 ms */
+           enc_frame_size = 3*st->Fs/50;
+         else                            /* 100 ms -> 5x 20 ms */
+           enc_frame_size = st->Fs/50;
+       }
+       else
+         enc_frame_size = st->Fs/50;
+
+       nb_frames = frame_size/enc_frame_size;
 
 #ifndef DISABLE_FLOAT_API
        if (analysis_read_pos_bak!= -1)
        {
           st->analysis.read_pos = analysis_read_pos_bak;
           st->analysis.read_subframe = analysis_read_subframe_bak;
        }
 #endif
 
-       nb_frames = frame_size > st->Fs/25 ? 3 : 2;
-       bytes_per_frame = IMIN(1276,(out_data_bytes-3)/nb_frames);
-
-       ALLOC(tmp_data, nb_frames*bytes_per_frame, unsigned char);
-
-       ALLOC(rp, 1, OpusRepacketizer);
-       opus_repacketizer_init(rp);
-
-       bak_mode = st->user_forced_mode;
-       bak_bandwidth = st->user_bandwidth;
-       bak_channels = st->force_channels;
-
-       st->user_forced_mode = st->mode;
-       st->user_bandwidth = st->bandwidth;
-       st->force_channels = st->stream_channels;
-       bak_to_mono = st->silk_mode.toMono;
+       ret = encode_multiframe_packet(st, pcm, nb_frames, enc_frame_size, data,
+                                      out_data_bytes, to_celt, lsb_depth, float_api);
 
-       if (bak_to_mono)
-          st->force_channels = 1;
-       else
-          st->prev_channels = st->stream_channels;
-       for (i=0;i<nb_frames;i++)
-       {
-          int tmp_len;
-          st->silk_mode.toMono = 0;
-          /* When switching from SILK/Hybrid to CELT, only ask for a switch at the last frame */
-          if (to_celt && i==nb_frames-1)
-             st->user_forced_mode = MODE_CELT_ONLY;
-          tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50,
-                tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth,
-                NULL, 0, c1, c2, analysis_channels, downmix, float_api);
-          if (tmp_len<0)
-          {
-             RESTORE_STACK;
-             return OPUS_INTERNAL_ERROR;
-          }
-          ret = opus_repacketizer_cat(rp, tmp_data+i*bytes_per_frame, tmp_len);
-          if (ret<0)
-          {
-             RESTORE_STACK;
-             return OPUS_INTERNAL_ERROR;
-          }
-       }
-       if (st->use_vbr)
-          repacketize_len = out_data_bytes;
-       else
-          repacketize_len = IMIN(3*st->bitrate_bps/(3*8*50/nb_frames), out_data_bytes);
-       ret = opus_repacketizer_out_range_impl(rp, 0, nb_frames, data, repacketize_len, 0, !st->use_vbr);
-       if (ret<0)
-       {
-          RESTORE_STACK;
-          return OPUS_INTERNAL_ERROR;
-       }
-       st->user_forced_mode = bak_mode;
-       st->user_bandwidth = bak_bandwidth;
-       st->force_channels = bak_channels;
-       st->silk_mode.toMono = bak_to_mono;
        RESTORE_STACK;
        return ret;
     }
-    curr_bandwidth = st->bandwidth;
+
+    /* For the first frame at a new SILK bandwidth */
+    if (st->silk_bw_switch)
+    {
+       redundancy = 1;
+       celt_to_silk = 1;
+       st->silk_bw_switch = 0;
+       prefill=1;
+    }
 
-    /* Chooses the appropriate mode for speech
-       *NEVER* switch to/from CELT-only mode here as this will invalidate some assumptions */
-    if (st->mode == MODE_SILK_ONLY && curr_bandwidth > OPUS_BANDWIDTH_WIDEBAND)
-        st->mode = MODE_HYBRID;
-    if (st->mode == MODE_HYBRID && curr_bandwidth <= OPUS_BANDWIDTH_WIDEBAND)
-        st->mode = MODE_SILK_ONLY;
+    /* If we decided to go with CELT, make sure redundancy is off, no matter what
+       we decided earlier. */
+    if (st->mode == MODE_CELT_ONLY)
+        redundancy = 0;
+
+    if (redundancy)
+    {
+       redundancy_bytes = compute_redundancy_bytes(max_data_bytes, st->bitrate_bps, frame_rate, st->stream_channels);
+       if (redundancy_bytes == 0)
+          redundancy = 0;
+    }
 
     /* printf("%d %d %d %d\n", st->bitrate_bps, st->stream_channels, st->mode, curr_bandwidth); */
     bytes_target = IMIN(max_data_bytes-redundancy_bytes, st->bitrate_bps * frame_size / (st->Fs * 8)) - 1;
 
     data += 1;
 
     ec_enc_init(&enc, data, max_data_bytes-1);
 
@@ -1462,17 +1632,17 @@ opus_int32 opus_encode_native(OpusEncode
     st->variable_HP_smth2_Q15 = silk_SMLAWB( st->variable_HP_smth2_Q15,
           hp_freq_smth1 - st->variable_HP_smth2_Q15, SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) );
 
     /* convert from log scale to Hertz */
     cutoff_Hz = silk_log2lin( silk_RSHIFT( st->variable_HP_smth2_Q15, 8 ) );
 
     if (st->application == OPUS_APPLICATION_VOIP)
     {
-       hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs);
+       hp_cutoff(pcm, cutoff_Hz, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs, st->arch);
     } else {
        dc_reject(pcm, 3, &pcm_buf[total_buffer*st->channels], st->hp_mem, frame_size, st->channels, st->Fs);
     }
 #ifndef FIXED_POINT
     if (float_api)
     {
        opus_val32 sum;
        sum = celt_inner_prod(&pcm_buf[total_buffer*st->channels], &pcm_buf[total_buffer*st->channels], frame_size*st->channels, st->arch);
@@ -1497,37 +1667,24 @@ opus_int32 opus_encode_native(OpusEncode
 #else
        VARDECL(opus_int16, pcm_silk);
        ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
 #endif
 
         /* Distribute bits between SILK and CELT */
         total_bitRate = 8 * bytes_target * frame_rate;
         if( st->mode == MODE_HYBRID ) {
-            int HB_gain_ref;
             /* Base rate for SILK */
-            st->silk_mode.bitRate = st->stream_channels * ( 5000 + 1000 * ( st->Fs == 100 * frame_size ) );
-            if( curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND ) {
-                /* SILK gets 2/3 of the remaining bits */
-                st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 2 / 3;
-            } else { /* FULLBAND */
-                /* SILK gets 3/5 of the remaining bits */
-                st->silk_mode.bitRate += ( total_bitRate - st->silk_mode.bitRate ) * 3 / 5;
-            }
-            /* Don't let SILK use more than 80% */
-            if( st->silk_mode.bitRate > total_bitRate * 4/5 ) {
-                st->silk_mode.bitRate = total_bitRate * 4/5;
-            }
+            st->silk_mode.bitRate = compute_silk_rate_for_hybrid(total_bitRate,
+                  curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded);
             if (!st->energy_masking)
             {
                /* Increasingly attenuate high band when it gets allocated fewer bits */
                celt_rate = total_bitRate - st->silk_mode.bitRate;
-               HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600;
-               HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels * HB_gain_ref, 6);
-               HB_gain = HB_gain < (opus_val32)Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE;
+               HB_gain = Q15ONE - SHR32(celt_exp2(-celt_rate * QCONST16(1.f/1024, 10)), 1);
             }
         } else {
             /* SILK gets all bits */
             st->silk_mode.bitRate = total_bitRate;
         }
 
         /* Surround masking for SILK */
         if (st->energy_masking && st->use_vbr && !st->lfe)
@@ -1564,17 +1721,16 @@ opus_int32 opus_encode_native(OpusEncode
            masking_depth += QCONST16(.2f, DB_SHIFT);
            rate_offset = (opus_int32)PSHR32(MULT16_16(srate, masking_depth), DB_SHIFT);
            rate_offset = MAX32(rate_offset, -2*st->silk_mode.bitRate/3);
            /* Split the rate change between the SILK and CELT part for hybrid. */
            if (st->bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND || st->bandwidth==OPUS_BANDWIDTH_FULLBAND)
               st->silk_mode.bitRate += 3*rate_offset/5;
            else
               st->silk_mode.bitRate += rate_offset;
-           bytes_target += rate_offset * frame_size / (8 * st->Fs);
         }
 
         st->silk_mode.payloadSize_ms = 1000 * frame_size / st->Fs;
         st->silk_mode.nChannelsAPI = st->channels;
         st->silk_mode.nChannelsInternal = st->stream_channels;
         if (curr_bandwidth == OPUS_BANDWIDTH_NARROWBAND) {
             st->silk_mode.desiredInternalSampleRate = 8000;
         } else if (curr_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) {
@@ -1585,50 +1741,62 @@ opus_int32 opus_encode_native(OpusEncode
         }
         if( st->mode == MODE_HYBRID ) {
             /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */
             st->silk_mode.minInternalSampleRate = 16000;
         } else {
             st->silk_mode.minInternalSampleRate = 8000;
         }
 
+        st->silk_mode.maxInternalSampleRate = 16000;
         if (st->mode == MODE_SILK_ONLY)
         {
            opus_int32 effective_max_rate = max_rate;
-           st->silk_mode.maxInternalSampleRate = 16000;
            if (frame_rate > 50)
               effective_max_rate = effective_max_rate*2/3;
-           if (effective_max_rate < 13000)
+           if (effective_max_rate < 8000)
            {
               st->silk_mode.maxInternalSampleRate = 12000;
               st->silk_mode.desiredInternalSampleRate = IMIN(12000, st->silk_mode.desiredInternalSampleRate);
            }
-           if (effective_max_rate < 9600)
+           if (effective_max_rate < 7000)
            {
               st->silk_mode.maxInternalSampleRate = 8000;
               st->silk_mode.desiredInternalSampleRate = IMIN(8000, st->silk_mode.desiredInternalSampleRate);
            }
-        } else {
-           st->silk_mode.maxInternalSampleRate = 16000;
         }
 
         st->silk_mode.useCBR = !st->use_vbr;
 
         /* Call SILK encoder for the low band */
-        nBytes = IMIN(1275, max_data_bytes-1-redundancy_bytes);
 
-        st->silk_mode.maxBits = nBytes*8;
-        /* Only allow up to 90% of the bits for hybrid mode*/
-        if (st->mode == MODE_HYBRID)
-           st->silk_mode.maxBits = (opus_int32)st->silk_mode.maxBits*9/10;
+        /* Max bits for SILK, counting ToC, redundancy bytes, and optionally redundancy. */
+        st->silk_mode.maxBits = (max_data_bytes-1)*8;
+        if (redundancy && redundancy_bytes >= 2)
+        {
+           /* Counting 1 bit for redundancy position and 20 bits for flag+size (only for hybrid). */
+           st->silk_mode.maxBits -= redundancy_bytes*8 + 1;
+           if (st->mode == MODE_HYBRID)
+              st->silk_mode.maxBits -= 20;
+        }
         if (st->silk_mode.useCBR)
         {
-           st->silk_mode.maxBits = (st->silk_mode.bitRate * frame_size / (st->Fs * 8))*8;
-           /* Reduce the initial target to make it easier to reach the CBR rate */
-           st->silk_mode.bitRate = IMAX(1, st->silk_mode.bitRate-2000);
+           if (st->mode == MODE_HYBRID)
+           {
+              st->silk_mode.maxBits = IMIN(st->silk_mode.maxBits, st->silk_mode.bitRate * frame_size / st->Fs);
+           }
+        } else {
+           /* Constrained VBR. */
+           if (st->mode == MODE_HYBRID)
+           {
+              /* Compute SILK bitrate corresponding to the max total bits available */
+              opus_int32 maxBitRate = compute_silk_rate_for_hybrid(st->silk_mode.maxBits*st->Fs / frame_size,
+                    curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded);
+              st->silk_mode.maxBits = maxBitRate * frame_size / st->Fs;
+           }
         }
 
         if (prefill)
         {
             opus_int32 zero=0;
             int prefill_offset;
             /* Use a smooth onset for the SILK prefill to avoid the encoder trying to encode
                a discontinuity. The exact location is what we need to avoid leaving any "gap"
@@ -1657,41 +1825,45 @@ opus_int32 opus_encode_native(OpusEncode
 #endif
         ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 );
         if( ret ) {
             /*fprintf (stderr, "SILK encode error: %d\n", ret);*/
             /* Handle error */
            RESTORE_STACK;
            return OPUS_INTERNAL_ERROR;
         }
-        if (nBytes==0)
-        {
-           st->rangeFinal = 0;
-           data[-1] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
-           RESTORE_STACK;
-           return 1;
-        }
+
         /* Extract SILK internal bandwidth for signaling in first byte */
         if( st->mode == MODE_SILK_ONLY ) {
             if( st->silk_mode.internalSampleRate == 8000 ) {
                curr_bandwidth = OPUS_BANDWIDTH_NARROWBAND;
             } else if( st->silk_mode.internalSampleRate == 12000 ) {
                curr_bandwidth = OPUS_BANDWIDTH_MEDIUMBAND;
             } else if( st->silk_mode.internalSampleRate == 16000 ) {
                curr_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
             }
         } else {
             silk_assert( st->silk_mode.internalSampleRate == 16000 );
         }
 
-        st->silk_mode.opusCanSwitch = st->silk_mode.switchReady;
+        st->silk_mode.opusCanSwitch = st->silk_mode.switchReady && !st->nonfinal_frame;
+
+        if (nBytes==0)
+        {
+           st->rangeFinal = 0;
+           data[-1] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
+           RESTORE_STACK;
+           return 1;
+        }
+
         /* FIXME: How do we allocate the redundancy for CBR? */
         if (st->silk_mode.opusCanSwitch)
         {
-           redundancy = 1;
+           redundancy_bytes = compute_redundancy_bytes(max_data_bytes, st->bitrate_bps, frame_rate, st->stream_channels);
+           redundancy = (redundancy_bytes != 0);
            celt_to_silk = 0;
            st->silk_bw_switch = 1;
         }
     }
 
     /* CELT processing */
     {
         int endband=21;
@@ -1722,50 +1894,28 @@ opus_int32 opus_encode_native(OpusEncode
         celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
         /* We may still decide to disable prediction later */
         if (st->silk_mode.reducedDependency)
            celt_pred = 0;
         celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred));
 
         if (st->mode == MODE_HYBRID)
         {
-            int len;
-
-            len = (ec_tell(&enc)+7)>>3;
-            if (redundancy)
-               len += st->mode == MODE_HYBRID ? 3 : 1;
             if( st->use_vbr ) {
-                nb_compr_bytes = len + bytes_target - (st->silk_mode.bitRate * frame_size) / (8 * st->Fs);
-            } else {
-                /* check if SILK used up too much */
-                nb_compr_bytes = len > bytes_target ? len : bytes_target;
+                celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps-st->silk_mode.bitRate));
+                celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(0));
             }
         } else {
             if (st->use_vbr)
             {
-                opus_int32 bonus=0;
-#ifndef DISABLE_FLOAT_API
-                if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != st->Fs/50)
-                {
-                   bonus = (60*st->stream_channels+40)*(st->Fs/frame_size-50);
-                   if (analysis_info.valid)
-                      bonus = (opus_int32)(bonus*(1.f+.5f*analysis_info.tonality));
-                }
-#endif
                 celt_encoder_ctl(celt_enc, OPUS_SET_VBR(1));
                 celt_encoder_ctl(celt_enc, OPUS_SET_VBR_CONSTRAINT(st->vbr_constraint));
-                celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps+bonus));
-                nb_compr_bytes = max_data_bytes-1-redundancy_bytes;
-            } else {
-                nb_compr_bytes = bytes_target;
+                celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps));
             }
         }
-
-    } else {
-        nb_compr_bytes = 0;
     }
 
     ALLOC(tmp_prefill, st->channels*st->Fs/400, opus_val16);
     if (st->mode != MODE_SILK_ONLY && st->mode != st->prev_mode && st->prev_mode > 0)
     {
        OPUS_COPY(tmp_prefill, &st->delay_buffer[(st->encoder_buffer-total_buffer-st->Fs/400)*st->channels], st->channels*st->Fs/400);
     }
 
@@ -1781,17 +1931,17 @@ opus_int32 opus_encode_native(OpusEncode
     /* gain_fade() and stereo_fade() need to be after the buffer copying
        because we don't want any of this to affect the SILK part */
     if( st->prev_HB_gain < Q15ONE || HB_gain < Q15ONE ) {
        gain_fade(pcm_buf, pcm_buf,
              st->prev_HB_gain, HB_gain, celt_mode->overlap, frame_size, st->channels, celt_mode->window, st->Fs);
     }
     st->prev_HB_gain = HB_gain;
     if (st->mode != MODE_HYBRID || st->stream_channels==1)
-       st->silk_mode.stereoWidth_Q14 = IMIN((1<<14),2*IMAX(0,equiv_rate-30000));
+       st->silk_mode.stereoWidth_Q14 = IMIN((1<<14),2*IMAX(0,equiv_rate-24000));
     if( !st->energy_masking && st->channels == 2 ) {
         /* Apply stereo width reduction (at low bitrates) */
         if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) {
             opus_val16 g1, g2;
             g1 = st->hybrid_stereo_width_Q14;
             g2 = (opus_val16)(st->silk_mode.stereoWidth_Q14);
 #ifdef FIXED_POINT
             g1 = g1==16384 ? Q15ONE : SHL16(g1,1);
@@ -1804,29 +1954,33 @@ opus_int32 opus_encode_native(OpusEncode
                   frame_size, st->channels, celt_mode->window, st->Fs);
             st->hybrid_stereo_width_Q14 = st->silk_mode.stereoWidth_Q14;
         }
     }
 
     if ( st->mode != MODE_CELT_ONLY && ec_tell(&enc)+17+20*(st->mode == MODE_HYBRID) <= 8*(max_data_bytes-1))
     {
         /* For SILK mode, the redundancy is inferred from the length */
-        if (st->mode == MODE_HYBRID && (redundancy || ec_tell(&enc)+37 <= 8*nb_compr_bytes))
+        if (st->mode == MODE_HYBRID)
            ec_enc_bit_logp(&enc, redundancy, 12);
         if (redundancy)
         {
             int max_redundancy;
             ec_enc_bit_logp(&enc, celt_to_silk, 1);
             if (st->mode == MODE_HYBRID)
-               max_redundancy = (max_data_bytes-1)-nb_compr_bytes;
+            {
+               /* Reserve the 8 bits needed for the redundancy length,
+                  and at least a few bits for CELT if possible */
+               max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+8+3+7)>>3);
+            }
             else
                max_redundancy = (max_data_bytes-1)-((ec_tell(&enc)+7)>>3);
             /* Target the same bit-rate for redundancy as for the rest,
                up to a max of 257 bytes */
-            redundancy_bytes = IMIN(max_redundancy, st->bitrate_bps/1600);
+            redundancy_bytes = IMIN(max_redundancy, redundancy_bytes);
             redundancy_bytes = IMIN(257, IMAX(2, redundancy_bytes));
             if (st->mode == MODE_HYBRID)
                 ec_enc_uint(&enc, redundancy_bytes-2, 256);
         }
     } else {
         redundancy = 0;
     }
 
@@ -1838,31 +1992,40 @@ opus_int32 opus_encode_native(OpusEncode
     if (st->mode != MODE_CELT_ONLY)start_band=17;
 
     if (st->mode == MODE_SILK_ONLY)
     {
         ret = (ec_tell(&enc)+7)>>3;
         ec_enc_done(&enc);
         nb_compr_bytes = ret;
     } else {
-       nb_compr_bytes = IMIN((max_data_bytes-1)-redundancy_bytes, nb_compr_bytes);
+       nb_compr_bytes = (max_data_bytes-1)-redundancy_bytes;
        ec_enc_shrink(&enc, nb_compr_bytes);
     }
 
 #ifndef DISABLE_FLOAT_API
     if (redundancy || st->mode != MODE_SILK_ONLY)
        celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info));
 #endif
+    if (st->mode == MODE_HYBRID) {
+       SILKInfo info;
+       info.signalType = st->silk_mode.signalType;
+       info.offset = st->silk_mode.offset;
+       celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO(&info));
+    } else {
+       celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO((SILKInfo*)NULL));
+    }
 
     /* 5 ms redundant frame for CELT->SILK */
     if (redundancy && celt_to_silk)
     {
         int err;
         celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
         celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
+        celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
         err = celt_encode_with_ec(celt_enc, pcm_buf, st->Fs/200, data+nb_compr_bytes, redundancy_bytes, NULL);
         if (err < 0)
         {
            RESTORE_STACK;
            return OPUS_INTERNAL_ERROR;
         }
         celt_encoder_ctl(celt_enc, OPUS_GET_FINAL_RANGE(&redundant_rng));
         celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
@@ -1876,41 +2039,59 @@ opus_int32 opus_encode_native(OpusEncode
         {
            unsigned char dummy[2];
            celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
 
            /* Prefilling */
            celt_encode_with_ec(celt_enc, tmp_prefill, st->Fs/400, dummy, 2, NULL);
            celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
         }
-        /* If false, we already busted the budget and we'll end up with a "PLC packet" */
+        /* If false, we already busted the budget and we'll end up with a "PLC frame" */
         if (ec_tell(&enc) <= 8*nb_compr_bytes)
         {
+           /* Set the bitrate again if it was overridden in the redundancy code above*/
+           if (redundancy && celt_to_silk && st->mode==MODE_HYBRID && st->use_vbr)
+              celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(st->bitrate_bps-st->silk_mode.bitRate));
+           celt_encoder_ctl(celt_enc, OPUS_SET_VBR(st->use_vbr));
            ret = celt_encode_with_ec(celt_enc, pcm_buf, frame_size, NULL, nb_compr_bytes, &enc);
            if (ret < 0)
            {
               RESTORE_STACK;
               return OPUS_INTERNAL_ERROR;
            }
+           /* Put CELT->SILK redundancy data in the right place. */
+           if (redundancy && celt_to_silk && st->mode==MODE_HYBRID && st->use_vbr)
+           {
+              OPUS_MOVE(data+ret, data+nb_compr_bytes, redundancy_bytes);
+              nb_compr_bytes = nb_compr_bytes+redundancy_bytes;
+           }
         }
     }
 
     /* 5 ms redundant frame for SILK->CELT */
     if (redundancy && !celt_to_silk)
     {
         int err;
         unsigned char dummy[2];
         int N2, N4;
         N2 = st->Fs/200;
         N4 = st->Fs/400;
 
         celt_encoder_ctl(celt_enc, OPUS_RESET_STATE);
         celt_encoder_ctl(celt_enc, CELT_SET_START_BAND(0));
         celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(0));
+        celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
+        celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
 
+        if (st->mode == MODE_HYBRID)
+        {
+           /* Shrink packet to what the encoder actually used. */
+           nb_compr_bytes = ret;
+           ec_enc_shrink(&enc, nb_compr_bytes);
+        }
         /* NOTE: We could speed this up slightly (at the expense of code size) by just adding a function that prefills the buffer */
         celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2-N4), N4, dummy, 2, NULL);
 
         err = celt_encode_with_ec(celt_enc, pcm_buf+st->channels*(frame_size-N2), N2, data+nb_compr_bytes, redundancy_bytes, NULL);
         if (err < 0)
         {
            RESTORE_STACK;
            return OPUS_INTERNAL_ERROR;
@@ -1930,16 +2111,31 @@ opus_int32 opus_encode_native(OpusEncode
         st->prev_mode = MODE_CELT_ONLY;
     else
         st->prev_mode = st->mode;
     st->prev_channels = st->stream_channels;
     st->prev_framesize = frame_size;
 
     st->first = 0;
 
+    /* DTX decision */
+#ifndef DISABLE_FLOAT_API
+    if (st->use_dtx && (analysis_info.valid || is_silence))
+    {
+       if (decide_dtx_mode(analysis_info.activity_probability, &st->nb_no_activity_frames,
+             st->peak_signal_energy, pcm, frame_size, st->channels, is_silence, st->arch))
+       {
+          st->rangeFinal = 0;
+          data[0] = gen_toc(st->mode, st->Fs/frame_size, curr_bandwidth, st->stream_channels);
+          RESTORE_STACK;
+          return 1;
+       }
+    }
+#endif
+
     /* In the unlikely case that the SILK encoder busted its target, tell
        the decoder to call the PLC */
     if (ec_tell(&enc) > (max_data_bytes-1)*8)
     {
        if (max_data_bytes < 2)
        {
           RESTORE_STACK;
           return OPUS_BUFFER_TOO_SMALL;
@@ -1957,17 +2153,16 @@ opus_int32 opus_encode_native(OpusEncode
          the actual length for allocation purposes.*/
        while(ret>2&&data[ret]==0)ret--;
     }
     /* Count ToC and redundancy */
     ret += 1+redundancy_bytes;
     if (!st->use_vbr)
     {
        if (opus_packet_pad(data, ret, max_data_bytes) != OPUS_OK)
-
        {
           RESTORE_STACK;
           return OPUS_INTERNAL_ERROR;
        }
        ret = max_data_bytes;
     }
     RESTORE_STACK;
     return ret;
@@ -1976,98 +2171,74 @@ opus_int32 opus_encode_native(OpusEncode
 #ifdef FIXED_POINT
 
 #ifndef DISABLE_FLOAT_API
 opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
       unsigned char *data, opus_int32 max_data_bytes)
 {
    int i, ret;
    int frame_size;
-   int delay_compensation;
    VARDECL(opus_int16, in);
    ALLOC_STACK;
 
-   if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
-      delay_compensation = 0;
-   else
-      delay_compensation = st->delay_compensation;
-   frame_size = compute_frame_size(pcm, analysis_frame_size,
-         st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
-         delay_compensation, downmix_float, st->analysis.subframe_mem);
-
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
+   if (frame_size <= 0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
    ALLOC(in, frame_size*st->channels, opus_int16);
 
    for (i=0;i<frame_size*st->channels;i++)
       in[i] = FLOAT2INT16(pcm[i]);
    ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
                             pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
    RESTORE_STACK;
    return ret;
 }
 #endif
 
 opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
                 unsigned char *data, opus_int32 out_data_bytes)
 {
    int frame_size;
-   int delay_compensation;
-   if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
-      delay_compensation = 0;
-   else
-      delay_compensation = st->delay_compensation;
-   frame_size = compute_frame_size(pcm, analysis_frame_size,
-         st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
-         delay_compensation, downmix_int
-#ifndef DISABLE_FLOAT_API
-         , st->analysis.subframe_mem
-#endif
-         );
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
    return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16,
                              pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
 }
 
 #else
 opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
       unsigned char *data, opus_int32 max_data_bytes)
 {
    int i, ret;
    int frame_size;
-   int delay_compensation;
    VARDECL(float, in);
    ALLOC_STACK;
 
-   if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
-      delay_compensation = 0;
-   else
-      delay_compensation = st->delay_compensation;
-   frame_size = compute_frame_size(pcm, analysis_frame_size,
-         st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
-         delay_compensation, downmix_int, st->analysis.subframe_mem);
-
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
+   if (frame_size <= 0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
    ALLOC(in, frame_size*st->channels, float);
 
    for (i=0;i<frame_size*st->channels;i++)
       in[i] = (1.0f/32768)*pcm[i];
    ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
                             pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
    RESTORE_STACK;
    return ret;
 }
 opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
                       unsigned char *data, opus_int32 out_data_bytes)
 {
    int frame_size;
-   int delay_compensation;
-   if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
-      delay_compensation = 0;
-   else
-      delay_compensation = st->delay_compensation;
-   frame_size = compute_frame_size(pcm, analysis_frame_size,
-         st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
-         delay_compensation, downmix_float, st->analysis.subframe_mem);
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
    return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24,
                              pcm, analysis_frame_size, 0, -2, st->channels, downmix_float, 1);
 }
 #endif
 
 
 int opus_encoder_ctl(OpusEncoder *st, int request, ...)
 {
@@ -2088,16 +2259,19 @@ int opus_encoder_ctl(OpusEncoder *st, in
             if (   (value != OPUS_APPLICATION_VOIP && value != OPUS_APPLICATION_AUDIO
                  && value != OPUS_APPLICATION_RESTRICTED_LOWDELAY)
                || (!st->first && st->application != value))
             {
                ret = OPUS_BAD_ARG;
                break;
             }
             st->application = value;
+#ifndef DISABLE_FLOAT_API
+            st->analysis.application = value;
+#endif
         }
         break;
         case OPUS_GET_APPLICATION_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
             if (!value)
             {
                goto bad_arg;
@@ -2206,27 +2380,27 @@ int opus_encoder_ctl(OpusEncoder *st, in
         break;
         case OPUS_SET_DTX_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
             if(value<0 || value>1)
             {
                goto bad_arg;
             }
-            st->silk_mode.useDTX = value;
+            st->use_dtx = value;
         }
         break;
         case OPUS_GET_DTX_REQUEST:
         {
             opus_int32 *value = va_arg(ap, opus_int32*);
             if (!value)
             {
                goto bad_arg;
             }
-            *value = st->silk_mode.useDTX;
+            *value = st->use_dtx;
         }
         break;
         case OPUS_SET_COMPLEXITY_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
             if(value<0 || value>10)
             {
                goto bad_arg;
@@ -2417,20 +2591,21 @@ int opus_encoder_ctl(OpusEncoder *st, in
                goto bad_arg;
             }
             *value = st->lsb_depth;
         }
         break;
         case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
         {
             opus_int32 value = va_arg(ap, opus_int32);
-            if (value != OPUS_FRAMESIZE_ARG   && value != OPUS_FRAMESIZE_2_5_MS &&
-                value != OPUS_FRAMESIZE_5_MS  && value != OPUS_FRAMESIZE_10_MS  &&
-                value != OPUS_FRAMESIZE_20_MS && value != OPUS_FRAMESIZE_40_MS  &&
-                value != OPUS_FRAMESIZE_60_MS && value != OPUS_FRAMESIZE_VARIABLE)
+            if (value != OPUS_FRAMESIZE_ARG    && value != OPUS_FRAMESIZE_2_5_MS &&
+                value != OPUS_FRAMESIZE_5_MS   && value != OPUS_FRAMESIZE_10_MS  &&
+                value != OPUS_FRAMESIZE_20_MS  && value != OPUS_FRAMESIZE_40_MS  &&
+                value != OPUS_FRAMESIZE_60_MS  && value != OPUS_FRAMESIZE_80_MS  &&
+                value != OPUS_FRAMESIZE_100_MS && value != OPUS_FRAMESIZE_120_MS)
             {
                goto bad_arg;
             }
             st->variable_duration = value;
             celt_encoder_ctl(celt_enc, OPUS_SET_EXPERT_FRAME_DURATION(value));
         }
         break;
         case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
@@ -2454,16 +2629,36 @@ int opus_encoder_ctl(OpusEncoder *st, in
         case OPUS_GET_PREDICTION_DISABLED_REQUEST:
         {
            opus_int32 *value = va_arg(ap, opus_int32*);
            if (!value)
               goto bad_arg;
            *value = st->silk_mode.reducedDependency;
         }
         break;
+        case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+        {
+            opus_int32 value = va_arg(ap, opus_int32);
+            if(value<0 || value>1)
+            {
+               goto bad_arg;
+            }
+            celt_encoder_ctl(celt_enc, OPUS_SET_PHASE_INVERSION_DISABLED(value));
+        }
+        break;
+        case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+        {
+            opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value)
+            {
+               goto bad_arg;
+            }
+            celt_encoder_ctl(celt_enc, OPUS_GET_PHASE_INVERSION_DISABLED(value));
+        }
+        break;
         case OPUS_RESET_STATE:
         {
            void *silk_enc;
            silk_EncControlStruct dummy;
            char *start;
            silk_enc = (char*)st+st->silk_enc_offset;
 #ifndef DISABLE_FLOAT_API
            tonality_analysis_reset(&st->analysis);
--- a/media/libopus/src/opus_multistream_decoder.c
+++ b/media/libopus/src/opus_multistream_decoder.c
@@ -232,17 +232,18 @@ static int opus_multistream_decode_nativ
       {
          RESTORE_STACK;
          return OPUS_BUFFER_TOO_SMALL;
       }
    }
    for (s=0;s<st->layout.nb_streams;s++)
    {
       OpusDecoder *dec;
-      int packet_offset, ret;
+      opus_int32 packet_offset;
+      int ret;
 
       dec = (OpusDecoder*)ptr;
       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
 
       if (!do_plc && len<=0)
       {
          RESTORE_STACK;
          return OPUS_INTERNAL_ERROR;
@@ -420,16 +421,17 @@ int opus_multistream_decoder_ctl(OpusMSD
    mono_size = opus_decoder_get_size(1);
    ptr = (char*)st + align(sizeof(OpusMSDecoder));
    switch (request)
    {
        case OPUS_GET_BANDWIDTH_REQUEST:
        case OPUS_GET_SAMPLE_RATE_REQUEST:
        case OPUS_GET_GAIN_REQUEST:
        case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
+       case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
        {
           OpusDecoder *dec;
           /* For int32* GET params, just query the first stream */
           opus_int32 *value = va_arg(ap, opus_int32*);
           dec = (OpusDecoder*)ptr;
           ret = opus_decoder_ctl(dec, request, value);
        }
        break;
@@ -494,16 +496,17 @@ int opus_multistream_decoder_ctl(OpusMSD
                 ptr += align(coupled_size);
              else
                 ptr += align(mono_size);
           }
           *value = (OpusDecoder*)ptr;
        }
        break;
        case OPUS_SET_GAIN_REQUEST:
+       case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
        {
           int s;
           /* This works for int32 params */
           opus_int32 value = va_arg(ap, opus_int32);
           for (s=0;s<st->layout.nb_streams;s++)
           {
              OpusDecoder *dec;
 
--- a/media/libopus/src/opus_multistream_encoder.c
+++ b/media/libopus/src/opus_multistream_encoder.c
@@ -82,17 +82,16 @@ typedef enum {
 struct OpusMSEncoder {
    ChannelLayout layout;
    int arch;
    int lfe_stream;
    int application;
    int variable_duration;
    MappingType mapping_type;
    opus_int32 bitrate_bps;
-   float subframe_mem[3];
    /* Encoder states go here */
    /* then opus_val32 window_mem[channels*120]; */
    /* then opus_val32 preemph_mem[channels]; */
 };
 
 static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
 {
    int s;
@@ -128,16 +127,39 @@ static opus_val32 *ms_get_window_mem(Opu
          ptr += align(coupled_size);
       else
          ptr += align(mono_size);
    }
    /* void* cast avoids clang -Wcast-align warning */
    return (opus_val32*)(void*)ptr;
 }
 
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
+{
+   int order_plus_one;
+   int acn_channels;
+   int nondiegetic_channels;
+
+   order_plus_one = isqrt32(nb_channels);
+   acn_channels = order_plus_one * order_plus_one;
+   nondiegetic_channels = nb_channels - acn_channels;
+
+   if (order_plus_one < 1 || order_plus_one > 15 ||
+       (nondiegetic_channels != 0 && nondiegetic_channels != 2))
+      return 0;
+
+   if (nb_streams)
+      *nb_streams = acn_channels + (nondiegetic_channels != 0);
+   if (nb_coupled_streams)
+      *nb_coupled_streams = nondiegetic_channels != 0;
+   return 1;
+}
+#endif
+
 static int validate_encoder_layout(const ChannelLayout *layout)
 {
    int s;
    for (s=0;s<layout->nb_streams;s++)
    {
       if (s < layout->nb_coupled_streams)
       {
          if (get_left_channel(layout, s, -1)==-1)
@@ -235,72 +257,85 @@ void surround_analysis(const CELTMode *c
 )
 {
    int c;
    int i;
    int LM;
    int pos[8] = {0};
    int upsample;
    int frame_size;
+   int freq_size;
    opus_val16 channel_offset;
    opus_val32 bandE[21];
    opus_val16 maskLogE[3][21];
    VARDECL(opus_val32, in);
    VARDECL(opus_val16, x);
    VARDECL(opus_val32, freq);
    SAVE_STACK;
 
    upsample = resampling_factor(rate);
    frame_size = len*upsample;
+   freq_size = IMIN(960, frame_size);
 
    /* LM = log2(frame_size / 120) */
    for (LM=0;LM<celt_mode->maxLM;LM++)
       if (celt_mode->shortMdctSize<<LM==frame_size)
          break;
 
    ALLOC(in, frame_size+overlap, opus_val32);
    ALLOC(x, len, opus_val16);
-   ALLOC(freq, frame_size, opus_val32);
+   ALLOC(freq, freq_size, opus_val32);
 
    channel_pos(channels, pos);
 
    for (c=0;c<3;c++)
       for (i=0;i<21;i++)
          maskLogE[c][i] = -QCONST16(28.f, DB_SHIFT);
 
    for (c=0;c<channels;c++)
    {
+      int frame;
+      int nb_frames = frame_size/freq_size;
+      celt_assert(nb_frames*freq_size == frame_size);
       OPUS_COPY(in, mem+c*overlap, overlap);
       (*copy_channel_in)(x, 1, pcm, channels, c, len);
       celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
 #ifndef FIXED_POINT
       {
          opus_val32 sum;
          sum = celt_inner_prod(in, in, frame_size+overlap, 0);
          /* This should filter out both NaNs and ridiculous signals that could
             cause NaNs further down. */
          if (!(sum < 1e18f) || celt_isnan(sum))
          {
             OPUS_CLEAR(in, frame_size+overlap);
             preemph_mem[c] = 0;
          }
       }
 #endif
-      clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window,
-            overlap, celt_mode->maxLM-LM, 1, arch);
-      if (upsample != 1)
+      OPUS_CLEAR(bandE, 21);
+      for (frame=0;frame<nb_frames;frame++)
       {
-         int bound = len;
-         for (i=0;i<bound;i++)
-            freq[i] *= upsample;
-         for (;i<frame_size;i++)
-            freq[i] = 0;
+         opus_val32 tmpE[21];
+         clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
+               overlap, celt_mode->maxLM-LM, 1, arch);
+         if (upsample != 1)
+         {
+            int bound = freq_size/upsample;
+            for (i=0;i<bound;i++)
+               freq[i] *= upsample;
+            for (;i<freq_size;i++)
+               freq[i] = 0;
+         }
+
+         compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch);
+         /* If we have multiple frames, take the max energy. */
+         for (i=0;i<21;i++)
+            bandE[i] = MAX32(bandE[i], tmpE[i]);
       }
-
-      compute_band_energies(celt_mode, freq, bandE, 21, 1, LM);
       amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
       /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
       for (i=1;i<21;i++)
          bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i-1]-QCONST16(1.f, DB_SHIFT));
       for (i=19;i>=0;i--)
          bandLogE[21*c+i] = MAX16(bandLogE[21*c+i], bandLogE[21*c+i+1]-QCONST16(2.f, DB_SHIFT));
       if (pos[c]==1)
       {
@@ -406,18 +441,18 @@ opus_int32 opus_multistream_surround_enc
       nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
    } else if (mapping_family==255)
    {
       nb_streams=channels;
       nb_coupled_streams=0;
 #ifdef ENABLE_EXPERIMENTAL_AMBISONICS
    } else if (mapping_family==254)
    {
-      nb_streams=channels;
-      nb_coupled_streams=0;
+      if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
+         return 0;
 #endif
    } else
       return 0;
    size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
    if (channels>2)
    {
       size += channels*(120*sizeof(opus_val32) + sizeof(opus_val32));
    }
@@ -443,26 +478,33 @@ static int opus_multistream_encoder_init
    if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
        (streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
       return OPUS_BAD_ARG;
 
    st->arch = opus_select_arch();
    st->layout.nb_channels = channels;
    st->layout.nb_streams = streams;
    st->layout.nb_coupled_streams = coupled_streams;
-   st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
    if (mapping_type != MAPPING_TYPE_SURROUND)
       st->lfe_stream = -1;
    st->bitrate_bps = OPUS_AUTO;
    st->application = application;
    st->variable_duration = OPUS_FRAMESIZE_ARG;
    for (i=0;i<st->layout.nb_channels;i++)
       st->layout.mapping[i] = mapping[i];
-   if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
+   if (!validate_layout(&st->layout))
+      return OPUS_BAD_ARG;
+   if (mapping_type == MAPPING_TYPE_SURROUND &&
+       !validate_encoder_layout(&st->layout))
       return OPUS_BAD_ARG;
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+   if (mapping_type == MAPPING_TYPE_AMBISONICS &&
+       !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
+      return OPUS_BAD_ARG;
+#endif
    ptr = (char*)st + align(sizeof(OpusMSEncoder));
    coupled_size = opus_encoder_get_size(2);
    mono_size = opus_encoder_get_size(1);
 
    for (i=0;i<st->layout.nb_coupled_streams;i++)
    {
       ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
       if(ret!=OPUS_OK)return ret;
@@ -548,20 +590,22 @@ int opus_multistream_surround_encoder_in
       *streams=channels;
       *coupled_streams=0;
       for(i=0;i<channels;i++)
          mapping[i] = i;
 #ifdef ENABLE_EXPERIMENTAL_AMBISONICS
    } else if (mapping_family==254)
    {
       int i;
-      *streams=channels;
-      *coupled_streams=0;
-      for(i=0;i<channels;i++)
-         mapping[i] = i;
+      if (!validate_ambisonics(channels, streams, coupled_streams))
+         return OPUS_BAD_ARG;
+      for(i = 0; i < (*streams - *coupled_streams); i++)
+         mapping[i] = i + (*coupled_streams * 2);
+      for(i = 0; i < *coupled_streams * 2; i++)
+         mapping[i + (*streams - *coupled_streams)] = i;
 #endif
    } else
       return OPUS_UNIMPLEMENTED;
 
    if (channels>2 && mapping_family==1) {
       mapping_type = MAPPING_TYPE_SURROUND;
 #ifdef ENABLE_EXPERIMENTAL_AMBISONICS
    } else if (mapping_family==254)
@@ -667,121 +711,147 @@ static void surround_rate_allocation(
       )
 {
    int i;
    opus_int32 channel_rate;
    int stream_offset;
    int lfe_offset;
    int coupled_ratio; /* Q8 */
    int lfe_ratio;     /* Q8 */
+   int nb_lfe;
+   int nb_uncoupled;
+   int nb_coupled;
+   int nb_normal;
+   opus_int32 channel_offset;
+   opus_int32 bitrate;
+   int total;
 
-   if (st->bitrate_bps > st->layout.nb_channels*40000)
-      stream_offset = 20000;
-   else
-      stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
-   stream_offset += 60*(Fs/frame_size-50);
-   /* We start by giving each stream (coupled or uncoupled) the same bitrate.
+   nb_lfe = (st->lfe_stream!=-1);
+   nb_coupled = st->layout.nb_coupled_streams;
+   nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
+   nb_normal = 2*nb_coupled + nb_uncoupled;
+
+   /* Give each non-LFE channel enough bits per channel for coding band energy. */
+   channel_offset = 40*IMAX(50, Fs/frame_size);
+
+   if (st->bitrate_bps==OPUS_AUTO)
+   {
+      bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
+   } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
+   {
+      bitrate = nb_normal*300000 + nb_lfe*128000;
+   } else {
+      bitrate = st->bitrate_bps;
+   }
+
+   /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
+      total rate for the non-energy part to avoid problems at really low rate. */
+   lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
+
+   /* We give each stream (coupled or uncoupled) a starting bitrate.
       This models the main saving of coupled channels over uncoupled. */
-   /* The LFE stream is an exception to the above and gets fewer bits. */
-   lfe_offset = 3500 + 60*(Fs/frame_size-50);
-   /* Coupled streams get twice the mono rate after the first 20 kb/s. */
+   stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
+   stream_offset = IMAX(0, IMIN(20000, stream_offset));
+
+   /* Coupled streams get twice the mono rate after the offset is allocated. */
    coupled_ratio = 512;
    /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
    lfe_ratio = 32;
 
-   /* Compute bitrate allocation between streams */
-   if (st->bitrate_bps==OPUS_AUTO)
-   {
-      channel_rate = Fs+60*Fs/frame_size;
-   } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
-   {
-      channel_rate = 300000;
-   } else {
-      int nb_lfe;
-      int nb_uncoupled;
-      int nb_coupled;
-      int total;
-      nb_lfe = (st->lfe_stream!=-1);
-      nb_coupled = st->layout.nb_coupled_streams;
-      nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
-      total = (nb_uncoupled<<8)         /* mono */
-            + coupled_ratio*nb_coupled /* stereo */
-            + nb_lfe*lfe_ratio;
-      channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
-   }
-#ifndef FIXED_POINT
-   if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
-   {
-      opus_int32 bonus;
-      bonus = 60*(Fs/frame_size-50);
-      channel_rate += bonus;
-   }
-#endif
+   total = (nb_uncoupled<<8)         /* mono */
+         + coupled_ratio*nb_coupled /* stereo */
+         + nb_lfe*lfe_ratio;
+   channel_rate = 256*(opus_int64)(bitrate - lfe_offset*nb_lfe - stream_offset*(nb_coupled+nb_uncoupled) - channel_offset*nb_normal)/total;
 
    for (i=0;i<st->layout.nb_streams;i++)
    {
       if (i<st->layout.nb_coupled_streams)
-         rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
+         rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
       else if (i!=st->lfe_stream)
-         rate[i] = stream_offset+channel_rate;
+         rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
       else
-         rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
+         rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
    }
 }
 
 #ifdef ENABLE_EXPERIMENTAL_AMBISONICS
 static void ambisonics_rate_allocation(
       OpusMSEncoder *st,
       opus_int32 *rate,
       int frame_size,
       opus_int32 Fs
       )
 {
    int i;
-   int non_mono_rate;
    int total_rate;
+   int directional_rate;
+   int nondirectional_rate;
+   int leftover_bits;
 
-   /* The mono channel gets (rate_ratio_num / rate_ratio_den) times as many bits
-    * as all other channels */
+   /* Each nondirectional channel gets (rate_ratio_num / rate_ratio_den) times
+    * as many bits as all other ambisonics channels.
+    */
    const int rate_ratio_num = 4;
    const int rate_ratio_den = 3;
-   const int num_channels = st->layout.nb_streams;
+   const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
+   const int nb_nondirectional_channels = st->layout.nb_coupled_streams * 2 + 1;
+   const int nb_directional_channels = st->layout.nb_streams - 1;
 
    if (st->bitrate_bps==OPUS_AUTO)
    {
-      total_rate = num_channels * (20000 + st->layout.nb_streams*(Fs+60*Fs/frame_size));
+      total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
+         (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
    } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
    {
-      total_rate = num_channels * 320000;
-   } else {
+      total_rate = nb_channels * 320000;
+   } else
+   {
       total_rate = st->bitrate_bps;
    }
 
-   /* Let y be the non-mono rate and let p, q be integers such that the mono
-    * channel rate is (p/q) * y.
+   /* Let y be the directional rate, m be the num of nondirectional channels
+    *   m = (s + 1)
+    * and let p, q be integers such that the nondirectional rate is
+    *   m_rate = (p / q) * y
     * Also let T be the total bitrate to allocate. Then
-    *   (n - 1) y + (p/q) y = T
-    *   y = (T q) / (qn - q + p)
+    *   T = (n - m) * y + m * m_rate
+    * Solving for y,
+    *   y = (q * T) / (m * (p - q) + n * q)
     */
-   non_mono_rate =
-         total_rate * rate_ratio_den
-         / (rate_ratio_den*num_channels + rate_ratio_num - rate_ratio_den);
+   directional_rate =
+      total_rate * rate_ratio_den
+      / (nb_nondirectional_channels * (rate_ratio_num - rate_ratio_den)
+       + nb_channels * rate_ratio_den);
+
+   /* Calculate the nondirectional rate.
+    *   m_rate = y * (p / q)
+    */
+   nondirectional_rate = directional_rate * rate_ratio_num / rate_ratio_den;
 
-#ifndef FIXED_POINT
-   if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
+   /* Calculate the leftover from truncation error.
+    *   leftover = T - y * (n - m) - m_rate * m
+    * Place leftover bits in omnidirectional channel.
+    */
+   leftover_bits = total_rate
+      - directional_rate * nb_directional_channels
+      - nondirectional_rate * nb_nondirectional_channels;
+
+   /* Calculate rates for each channel */
+   for (i = 0; i < st->layout.nb_streams; i++)
    {
-      opus_int32 bonus = 60*(Fs/frame_size-50);
-      non_mono_rate += bonus;
-   }
-#endif
-
-   rate[0] = total_rate - (num_channels - 1) * non_mono_rate;
-   for (i=1;i<st->layout.nb_streams;i++)
-   {
-      rate[i] = non_mono_rate;
+      if (i < st->layout.nb_coupled_streams)
+      {
+         rate[i] = nondirectional_rate * 2;
+      } else if (i == st->layout.nb_coupled_streams)
+      {
+         rate[i] = nondirectional_rate + leftover_bits;
+      } else
+      {
+         rate[i] = directional_rate;
+      }
    }
 }
 #endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
 
 static opus_int32 rate_allocation(
       OpusMSEncoder *st,
       opus_int32 *rate,
       int frame_size
@@ -807,18 +877,18 @@ static opus_int32 rate_allocation(
    for (i=0;i<st->layout.nb_streams;i++)
    {
       rate[i] = IMAX(rate[i], 500);
       rate_sum += rate[i];
    }
    return rate_sum;
 }
 
-/* Max size in case the encoder decides to return three frames */
-#define MS_FRAME_TMP (3*1275+7)
+/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
+#define MS_FRAME_TMP (6*1275+12)
 static int opus_multistream_encode_native
 (
     OpusMSEncoder *st,
     opus_copy_channel_in_func copy_channel_in,
     const void *pcm,
     int analysis_frame_size,
     unsigned char *data,
     opus_int32 max_data_bytes,
@@ -854,49 +924,28 @@ static int opus_multistream_encode_nativ
       mem = ms_get_window_mem(st);
    }
 
    ptr = (char*)st + align(sizeof(OpusMSEncoder));
    opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
    opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
    opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
 
-   {
-      opus_int32 delay_compensation;
-      int channels;
-
-      channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
-      opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
-      delay_compensation -= Fs/400;
-      frame_size = compute_frame_size(pcm, analysis_frame_size,
-            st->variable_duration, channels, Fs, st->bitrate_bps,
-            delay_compensation, downmix
-#ifndef DISABLE_FLOAT_API
-            , st->subframe_mem
-#endif
-            );
-   }
-
-   if (400*frame_size < Fs)
-   {
-      RESTORE_STACK;
-      return OPUS_BAD_ARG;
-   }
-   /* Validate frame_size before using it to allocate stack space.
-      This mirrors the checks in opus_encode[_float](). */
-   if (400*frame_size != Fs && 200*frame_size != Fs &&
-       100*frame_size != Fs &&  50*frame_size != Fs &&
-        25*frame_size != Fs &&  50*frame_size != 3*Fs)
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
+   if (frame_size <= 0)
    {
       RESTORE_STACK;
       return OPUS_BAD_ARG;
    }
 
    /* Smallest packet the encoder can produce. */
    smallest_packet = st->layout.nb_streams*2-1;
+   /* 100 ms needs an extra byte per stream for the ToC. */
+   if (Fs/frame_size == 10)
+     smallest_packet += st->layout.nb_streams;
    if (max_data_bytes < smallest_packet)
    {
       RESTORE_STACK;
       return OPUS_BUFFER_TOO_SMALL;
    }
    ALLOC(buf, 2*frame_size, opus_val16);
    coupled_size = opus_encoder_get_size(2);
    mono_size = opus_encoder_get_size(1);
@@ -1008,16 +1057,19 @@ static int opus_multistream_encode_nativ
          c2 = -1;
       }
       if (st->mapping_type == MAPPING_TYPE_SURROUND)
          opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
       /* number of bytes left (+Toc) */
       curr_max = max_data_bytes - tot_size;
       /* Reserve one byte for the last stream and two for the others */
       curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
+      /* For 100 ms, reserve an extra byte per stream for the ToC */
+      if (Fs/frame_size == 10)
+        curr_max -= st->layout.nb_streams-s-1;
       curr_max = IMIN(curr_max,MS_FRAME_TMP);
       /* Repacketizer will add one or two bytes for self-delimited frames */
       if (s != st->layout.nb_streams-1) curr_max -=  curr_max>253 ? 2 : 1;
       if (!vbr && s == st->layout.nb_streams-1)
          opus_encoder_ctl(enc, OPUS_SET_BITRATE(curr_max*(8*Fs/frame_size)));
       len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
             pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix, float_api);
       if (len<0)
@@ -1156,19 +1208,21 @@ int opus_multistream_encoder_ctl(OpusMSE
    coupled_size = opus_encoder_get_size(2);
    mono_size = opus_encoder_get_size(1);
    ptr = (char*)st + align(sizeof(OpusMSEncoder));
    switch (request)
    {
    case OPUS_SET_BITRATE_REQUEST:
    {
       opus_int32 value = va_arg(ap, opus_int32);
-      if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
+      if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
       {
-         goto bad_arg;
+         if (value <= 0)
+            goto bad_arg;
+         value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
       }
       st->bitrate_bps = value;
    }
    break;
    case OPUS_GET_BITRATE_REQUEST:
    {
       int s;
       opus_int32 *value = va_arg(ap, opus_int32*);
@@ -1201,16 +1255,17 @@ int opus_multistream_encoder_ctl(OpusMSE
    case OPUS_GET_VOICE_RATIO_REQUEST:
    case OPUS_GET_VBR_CONSTRAINT_REQUEST:
    case OPUS_GET_SIGNAL_REQUEST:
    case OPUS_GET_LOOKAHEAD_REQUEST:
    case OPUS_GET_SAMPLE_RATE_REQUEST:
    case OPUS_GET_INBAND_FEC_REQUEST:
    case OPUS_GET_FORCE_CHANNELS_REQUEST:
    case OPUS_GET_PREDICTION_DISABLED_REQUEST:
+   case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
    {
       OpusEncoder *enc;
       /* For int32* GET params, just query the first stream */
       opus_int32 *value = va_arg(ap, opus_int32*);
       enc = (OpusEncoder*)ptr;
       ret = opus_encoder_ctl(enc, request, value);
    }
    break;
@@ -1247,16 +1302,17 @@ int opus_multistream_encoder_ctl(OpusMSE
    case OPUS_SET_SIGNAL_REQUEST:
    case OPUS_SET_APPLICATION_REQUEST:
    case OPUS_SET_INBAND_FEC_REQUEST:
    case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
    case OPUS_SET_DTX_REQUEST:
    case OPUS_SET_FORCE_MODE_REQUEST:
    case OPUS_SET_FORCE_CHANNELS_REQUEST:
    case OPUS_SET_PREDICTION_DISABLED_REQUEST:
+   case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
    {
       int s;
       /* This works for int32 params */
       opus_int32 value = va_arg(ap, opus_int32);
       for (s=0;s<st->layout.nb_streams;s++)
       {
          OpusEncoder *enc;
 
@@ -1308,17 +1364,16 @@ int opus_multistream_encoder_ctl(OpusMSE
           goto bad_arg;
        }
        *value = st->variable_duration;
    }
    break;
    case OPUS_RESET_STATE:
    {
       int s;
-      st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
       if (st->mapping_type == MAPPING_TYPE_SURROUND)
       {
          OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
          OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
       }
       for (s=0;s<st->layout.nb_streams;s++)
       {
          OpusEncoder *enc;
--- a/media/libopus/src/opus_private.h
+++ b/media/libopus/src/opus_private.h
@@ -87,24 +87,16 @@ int get_mono_channel(const ChannelLayout
 typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
 void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
 void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
 
 int encode_size(int size, unsigned char *data);
 
 opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
 
-opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
-      int variable_duration, int C, opus_int32 Fs, int bitrate_bps,
-      int delay_compensation, downmix_func downmix
-#ifndef DISABLE_FLOAT_API
-      , float *subframe_mem
-#endif
-      );
-
 opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
       unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
       const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
       int analysis_channels, downmix_func downmix, int float_api);
 
 int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len,
       opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited,
       opus_int32 *packet_offset, int soft_clip);