diff --git a/celt b/celt
index 0b405d1170122c859faab435405666506d52fa2e..b3c05b6be2a6579af55a625903e9e70687a4d77f 160000
--- a/celt
+++ b/celt
@@ -1 +1 @@
-Subproject commit 0b405d1170122c859faab435405666506d52fa2e
+Subproject commit b3c05b6be2a6579af55a625903e9e70687a4d77f
diff --git a/silk b/silk
index fc06bda89e40f8adfa1af9cebf869e63ef693bb5..485d64dfdf4145bf45929c697cdb2b3eed9c91c1 160000
--- a/silk
+++ b/silk
@@ -1 +1 @@
-Subproject commit fc06bda89e40f8adfa1af9cebf869e63ef693bb5
+Subproject commit 485d64dfdf4145bf45929c697cdb2b3eed9c91c1
diff --git a/silk_headers.txt b/silk_headers.txt
index 230082530e0905e406370e39ce929338891adce0..1157db7999bc937d27a9aba338d3e312babc2343 100644
--- a/silk_headers.txt
+++ b/silk_headers.txt
@@ -6,7 +6,7 @@ silk/interface/SKP_Silk_typedef.h
 silk/src_common/SKP_Silk_define.h
 silk/src_common/SKP_Silk_main.h
 silk/src_common/SKP_Silk_PLC.h
-silk/src_common/SKP_Silk_setup_complexity.h
+silk/src_common/SKP_Silk_setup.h
 silk/src_common/SKP_Silk_structs.h
 silk/src_common/SKP_Silk_tables.h
 silk/src_common/SKP_Silk_tables_NLSF_CB.h
diff --git a/silk_sources.mk b/silk_sources.mk
index 815ad4b6862646466dc28e12c953940120445768..7fc3e6e13f234dd37d6a39f5f1f73881bab5b2ac 100644
--- a/silk_sources.mk
+++ b/silk_sources.mk
@@ -13,13 +13,13 @@ silk/src_common/SKP_Silk_encode_indices.c \
 silk/src_common/SKP_Silk_encode_pulses.c \
 silk/src_common/SKP_Silk_gain_quant.c \
 silk/src_common/SKP_Silk_interpolate.c \
+silk/src_common/SKP_Silk_LBRR_embed.c \
 silk/src_common/SKP_Silk_LP_variable_cutoff.c \
 silk/src_common/SKP_Silk_NLSF2A_stable.c \
 silk/src_common/SKP_Silk_NLSF_MSVQ_decode.c \
 silk/src_common/SKP_Silk_NSQ.c \
 silk/src_common/SKP_Silk_NSQ_del_dec.c \
 silk/src_common/SKP_Silk_PLC.c \
-silk/src_common/SKP_Silk_pulses_to_bytes.c \
 silk/src_common/SKP_Silk_shell_coder.c \
 silk/src_common/SKP_Silk_tables_gain.c \
 silk/src_common/SKP_Silk_tables_LTP.c \
@@ -51,7 +51,6 @@ silk/src_FLP/SKP_Silk_NLSF_MSVQ_decode_FLP.c \
 silk/src_FLP/SKP_Silk_NLSF_MSVQ_encode_FLP.c \
 silk/src_FLP/SKP_Silk_NLSF_VQ_rate_distortion_FLP.c \
 silk/src_FLP/SKP_Silk_NLSF_VQ_sum_error_FLP.c \
-silk/src_FLP/SKP_Silk_NLSF_VQ_weights_laroia_FLP.c \
 silk/src_FLP/SKP_Silk_noise_shape_analysis_FLP.c \
 silk/src_FLP/SKP_Silk_prefilter_FLP.c \
 silk/src_FLP/SKP_Silk_process_gains_FLP.c \
@@ -111,12 +110,9 @@ silk/src_SigProc_FIX/SKP_Silk_schur.c \
 silk/src_SigProc_FIX/SKP_Silk_sigm_Q15.c \
 silk/src_SigProc_FIX/SKP_Silk_sort.c \
 silk/src_SigProc_FIX/SKP_Silk_sum_sqr_shift.c \
-silk/src_SigProc_FLP/SKP_Silk_allpass_int_FLP.c \
 silk/src_SigProc_FLP/SKP_Silk_autocorrelation_FLP.c \
 silk/src_SigProc_FLP/SKP_Silk_burg_modified_FLP.c \
 silk/src_SigProc_FLP/SKP_Silk_bwexpander_FLP.c \
-silk/src_SigProc_FLP/SKP_Silk_decimate2_coarse_FLP.c \
-silk/src_SigProc_FLP/SKP_Silk_decimate2_coarsest_FLP.c \
 silk/src_SigProc_FLP/SKP_Silk_energy_FLP.c \
 silk/src_SigProc_FLP/SKP_Silk_inner_product_FLP.c \
 silk/src_SigProc_FLP/SKP_Silk_k2a_FLP.c \
diff --git a/src/opus.h b/src/opus.h
index 6e42949edb58403af000877579c56dc724c557c3..a7c8569d384fbca8631e4e1dd27baaf23b66e480 100644
--- a/src/opus.h
+++ b/src/opus.h
@@ -114,7 +114,7 @@ OpusDecoder *opus_decoder_create(int Fs, int channels);
 
 /* returns (CELT) error code */
 int opus_decode(OpusDecoder *st, const unsigned char *data, int len,
-		short *pcm, int frame_size);
+		short *pcm, int frame_size, int decode_fec);
 
 void opus_decoder_ctl(OpusDecoder *st, int request, ...);
 
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index 525ad9780a62c5d0ba982625520434bffa9a556e..624b7fe2309fc4a1078b799bd13026f4d2a345c7 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -71,7 +71,7 @@ OpusDecoder *opus_decoder_create(int Fs, int channels)
 }
 
 int opus_decode(OpusDecoder *st, const unsigned char *data,
-		int len, short *pcm, int frame_size)
+		int len, short *pcm, int frame_size, int decode_fec)
 {
 	int i, silk_ret=0, celt_ret=0;
 	ec_dec dec;
@@ -131,6 +131,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
     /* SILK processing */
     if (st->mode != MODE_CELT_ONLY)
     {
+        int lost_flag, decoded_samples;
         SKP_int16 *pcm_ptr = pcm;
         DecControl.API_sampleRate = st->Fs;
         DecControl.payloadSize_ms = 1000 * audiosize / st->Fs;
@@ -149,15 +150,20 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
             DecControl.internalSampleRate = 16000;
         }
 
+        lost_flag = data == NULL ? 1 : 2 * decode_fec;
+        decoded_samples = 0;
         do {
             /* Call SILK decoder */
-            silk_ret = SKP_Silk_SDK_Decode( st->silk_dec, &DecControl, data == NULL, &dec, len, pcm_ptr, &silk_frame_size );
+            int first_frame = decoded_samples == 0;
+            silk_ret = SKP_Silk_SDK_Decode( st->silk_dec, &DecControl, 
+                lost_flag, first_frame, &dec, len, pcm_ptr, &silk_frame_size );
             if( silk_ret ) {
                 fprintf (stderr, "SILK decode error\n");
                 /* Handle error */
             }
             pcm_ptr += silk_frame_size;
-        } while( DecControl.moreInternalDecoderFrames );
+            decoded_samples += silk_frame_size;
+        } while( decoded_samples < frame_size );
     } else {
         for (i=0;i<frame_size*st->channels;i++)
             pcm[i] = 0;
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 66da681fc1912804862822884554e18d8c401eb2..ca908916f352aa57398ef7a86e8c4ad3bd2d6473 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -134,7 +134,9 @@ int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
         }
         if( st->mode == MODE_HYBRID ) {
             /* Don't allow bandwidth reduction at lowest bitrates in hybrid mode */
-            st->silk_mode.minInternalSampleRate = st->silk_mode.maxInternalSampleRate ;
+            st->silk_mode.minInternalSampleRate = 16000;
+        } else {
+            st->silk_mode.minInternalSampleRate = 8000;
         }
 
         /* Call SILK encoder for the low band */
diff --git a/src/test_opus.c b/src/test_opus.c
index e8a6583e0a256b40e57f1b0a62d1884a2a63e924..e322be062b330f919ead41a2040058aa4c457119 100644
--- a/src/test_opus.c
+++ b/src/test_opus.c
@@ -71,10 +71,10 @@ int main(int argc, char *argv[])
    OpusEncoder *enc;
    OpusDecoder *dec;
    int args;
-   int len;
+   int len[2];
    int frame_size, channels;
    int bitrate_bps;
-   unsigned char *data;
+   unsigned char *data[2];
    int sampling_rate;
    int use_vbr;
    int internal_sampling_rate_Hz;
@@ -92,6 +92,10 @@ int main(int argc, char *argv[])
    double bits=0.0, bits_act=0.0, bits2=0.0, nrg;
    int bandwidth=-1;
    const char *bandwidth_string;
+   int write_samples;
+   int lost, lost_prev = 1;
+   int toggle = 0;
+   int enc_final_range[2];
 
    if (argc < 7 )
    {
@@ -257,20 +261,19 @@ int main(int argc, char *argv[])
    enc = opus_encoder_create(sampling_rate, channels);
    dec = opus_decoder_create(sampling_rate, channels);
 
-   opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
-   opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
-
    if (bandwidth == -1)
    {
        fprintf (stderr, "Please specify a bandwidth when the sampling rate does not match one exactly\n");
        return 1;
    }
+   opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
+   opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
    opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
-
    opus_encoder_ctl(enc, OPUS_SET_VBR_FLAG(use_vbr));
    opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
    opus_encoder_ctl(enc, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
    opus_encoder_ctl(enc, OPUS_SET_DTX_FLAG(use_dtx));
+   opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
 
    skip = 5*sampling_rate/1000;
    /* When SILK resamples, add 18 samples delay */
@@ -302,11 +305,13 @@ int main(int argc, char *argv[])
 
    in = (short*)malloc(frame_size*channels*sizeof(short));
    out = (short*)malloc(frame_size*channels*sizeof(short));
-   data = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
+   data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
+   if( use_inbandfec ) {
+       data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(char));
+   }
    while (!stop)
    {
-      int write_samples;
-      int lost;
+
       err = fread(in, sizeof(short), frame_size*channels, fin);
       tot_read += err;
       if (err < frame_size*channels)
@@ -315,51 +320,75 @@ int main(int argc, char *argv[])
           for (i=err;i<frame_size*channels;i++)
               in[i] = 0;
       }
-      len = opus_encode(enc, in, frame_size, data, max_payload_bytes);
-      if (len <= 0)
+
+      len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
+#if OPUS_TEST_RANGE_CODER_STATE
+      enc_final_range[toggle] = opus_encoder_get_final_range( enc );
+#endif
+      if (len[toggle] <= 0)
       {
-         fprintf (stderr, "opus_encode() returned %d\n", len);
+         fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
          return 1;
       }
 
       lost = rand()%100<packet_loss_perc;
-      opus_decode(dec, lost ? NULL : data, len, out, frame_size);
-      count++;
-      tot_written += (frame_size-skip)*channels;
-      write_samples = frame_size;
-      if (tot_written > tot_read && skip==0)
-      {
-          write_samples -= (tot_written-tot_read)/channels;
-          stop = 1;
+      if( count >= use_inbandfec ) {
+          /* delay by one packet when using in-band FEC */
+          if( use_inbandfec  ) {
+              if( lost_prev ) {
+                  /* attempt to decode with in-band FEC from next packet */
+                  opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 1);
+              } else {
+                  /* regular decode */
+                  opus_decode(dec, data[1-toggle], len[1-toggle], out, frame_size, 0);
+              }
+          } else {
+              opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, frame_size, 0);
+          }
+          write_samples = frame_size-skip;
+          tot_written += write_samples*channels;
+          if (tot_written > tot_read)
+          {
+              write_samples -= (tot_written-tot_read)/channels;
+              stop = 1;
+          }
+          fwrite(out+skip, sizeof(short), write_samples*channels, fout);
+          skip = 0;
       }
-      fwrite(out+skip, sizeof(short), (write_samples-skip)*channels, fout);
-      skip = 0;
 
 #if OPUS_TEST_RANGE_CODER_STATE
       /* compare final range encoder rng values of encoder and decoder */
-      if( !lost && opus_decoder_get_final_range( dec ) != opus_encoder_get_final_range( enc ) ) {
+      if( !lost && !lost_prev && opus_decoder_get_final_range( dec ) != enc_final_range[toggle^use_inbandfec] ) {
           fprintf (stderr, "Error: Range coder state mismatch between encoder and decoder.\n");
           return 0;
       }
 #endif
 
+      lost_prev = lost;
+
       /* count bits */
-      bits += len*8;
-      nrg = 0.0;
-      for ( k = 0; k < frame_size * channels; k++ ) {
-          nrg += out[ k ] * (double)out[ k ];
+      bits += len[toggle]*8;
+      if( count >= use_inbandfec ) {
+          nrg = 0.0;
+          for ( k = 0; k < frame_size * channels; k++ ) {
+              nrg += in[ k ] * (double)in[ k ];
+          }
+          if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
+              bits_act += len[toggle]*8;
+              count_act++;
+          }
+	      /* Variance */
+	      bits2 += len[toggle]*len[toggle]*64;
       }
-      if ( ( nrg / ( frame_size * channels ) ) > 1e5 ) {
-          bits_act += len*8;
-          count_act++;
-      }
-	  /* Variance */
-	  bits2 += len*len*64;
+      count++;
+      toggle = (toggle + use_inbandfec) & 1;
    }
    fprintf (stderr, "average bitrate:             %7.3f kb/s\n", 1e-3*bits*sampling_rate/(frame_size*(double)count));
    fprintf (stderr, "active bitrate:              %7.3f kb/s\n", 1e-3*bits_act*sampling_rate/(frame_size*(double)count_act));
    fprintf (stderr, "bitrate standard deviation:  %7.3f kb/s\n", 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
-   DEBUG_STORE_CLOSE_FILES		/* Close any files to which intermediate results were stored */
+   /* Close any files to which intermediate results were stored */
+   DEBUG_STORE_CLOSE_FILES
+   SKP_TimerSave("opus_timing.txt");
    opus_encoder_destroy(enc);
    opus_decoder_destroy(dec);
    fclose(fin);