diff --git a/silk/dred_coding.c b/silk/dred_coding.c
index ff592e81725531aa8d2e07d628a6a53730473db5..34829390b8bb053c691ea30f050778796e059d94 100644
--- a/silk/dred_coding.c
+++ b/silk/dred_coding.c
@@ -37,11 +37,21 @@
 #include "celt/cwrs.h"
 #include "celt/laplace.h"
 #include "os_support.h"
+#include "dred_config.h"
 
 #define LATENT_DIM 80
 #define PVQ_DIM 24
 #define PVQ_K 82
 
+int compute_quantizer(int q0, int dQ, int i) {
+  int quant;
+  static const int dQ_table[8] = {0, 2, 3, 4, 6, 8, 12, 16};
+  quant = 0;
+  quant = q0 + (dQ_table[dQ]*i + 8)/16;
+  return quant > 15 ? 15 : quant;
+  return (int) floor(0.5f + DRED_ENC_Q0 + 1.f * (DRED_ENC_Q1 - DRED_ENC_Q0) * i / (DRED_NUM_REDUNDANCY_FRAMES - 2));
+}
+
 static void encode_pvq(const int *iy, int N, int K, ec_enc *enc) {
     int fits;
     celt_assert(N==24 || N==12 || N==6);
diff --git a/silk/dred_coding.h b/silk/dred_coding.h
index a36f93d92da67eb8c5dd4cc703c79466535c95e5..662ba549d92f14a5180c711af882670a2b5e0f71 100644
--- a/silk/dred_coding.h
+++ b/silk/dred_coding.h
@@ -31,6 +31,8 @@
 #include "opus_types.h"
 #include "entcode.h"
 
+int compute_quantizer(int q0, int dQ, int i);
+
 void dred_encode_state(ec_enc *enc, float *x);
 
 void dred_encode_latents(ec_enc *enc, const float *x, const opus_uint16 *scale, const opus_uint16 *dzone, const opus_uint16 *r, const opus_uint16 *p0);
diff --git a/silk/dred_config.h b/silk/dred_config.h
index f396219f3c2932567a8219f5d578da4d0b9f622f..ff9903bafe9b8177e65b638aa70e4a8f4767600b 100644
--- a/silk/dred_config.h
+++ b/silk/dred_config.h
@@ -28,7 +28,7 @@
 #ifndef DRED_CONFIG_H
 #define DRED_CONFIG_H
 
-#define DRED_VERSION 0
+#define DRED_VERSION 1
 #define DRED_MIN_BYTES 16
 
 /* these are inpart duplicates to the values defined in dred_rdovae_constants.h */
diff --git a/silk/dred_decoder.c b/silk/dred_decoder.c
index 20eb98ec46225394ae6d67fb3405e9766ff59cb3..dea532518ffab2994a0d6a7be9843809b641d6cb 100644
--- a/silk/dred_decoder.c
+++ b/silk/dred_decoder.c
@@ -48,6 +48,8 @@ int dred_ec_decode(OpusDRED *dec, const opus_uint8 *bytes, int num_bytes, int mi
   int q_level;
   int i;
   int offset;
+  int q0;
+  int dQ;
 
 
   /* since features are decoded in quadruples, it makes no sense to go with an uneven number of redundancy frames */
@@ -55,6 +57,11 @@ int dred_ec_decode(OpusDRED *dec, const opus_uint8 *bytes, int num_bytes, int mi
 
   /* decode initial state and initialize RDOVAE decoder */
   ec_dec_init(&ec, (unsigned char*)bytes, num_bytes);
+  dec->dred_offset = ec_dec_uint(&ec, 32);
+  q0 = ec_dec_uint(&ec, 16);
+  dQ = ec_dec_uint(&ec, 8);
+  /*printf("%d %d %d\n", dred_offset, q0, dQ);*/
+
   dred_decode_state(&ec, dec->state);
 
   /* decode newest to oldest and store oldest to newest */
@@ -63,7 +70,7 @@ int dred_ec_decode(OpusDRED *dec, const opus_uint8 *bytes, int num_bytes, int mi
       /* FIXME: Figure out how to avoid missing a last frame that would take up < 8 bits. */
       if (8*num_bytes - ec_tell(&ec) <= 7)
          break;
-      q_level = (int) floor(.5 + DRED_ENC_Q0 + 1.f * (DRED_ENC_Q1 - DRED_ENC_Q0) * i / (DRED_NUM_REDUNDANCY_FRAMES - 2));
+      q_level = compute_quantizer(q0, dQ, i/2);
       offset = q_level * DRED_LATENT_DIM;
       dred_decode_latents(
           &ec,
diff --git a/silk/dred_decoder.h b/silk/dred_decoder.h
index e2640964704686bc3743f53e6c7a8c074129f9e1..c7355ed109caf6c2e3868eb5fd3df0f10ac4d338 100644
--- a/silk/dred_decoder.h
+++ b/silk/dred_decoder.h
@@ -39,6 +39,7 @@ struct OpusDRED {
     float        latents[(DRED_NUM_REDUNDANCY_FRAMES/2)*DRED_LATENT_DIM];
     int          nb_latents;
     int          process_stage;
+    int          dred_offset;
 };
 
 
diff --git a/silk/dred_encoder.c b/silk/dred_encoder.c
index ffc24b7c80349d9a6959a37ee1ec01741d4fe527..02f1eb9fbbf06be3755ffe713c88d45f175ec805 100644
--- a/silk/dred_encoder.c
+++ b/silk/dred_encoder.c
@@ -85,9 +85,18 @@ int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int
     int i;
     int offset;
     int ec_buffer_fill;
+    int dred_offset;
+    int q0;
+    int dQ;
 
     /* entropy coding of state and latents */
     ec_enc_init(&ec_encoder, buf, max_bytes);
+    dred_offset = 8; /* 20 ms */
+    q0 = DRED_ENC_Q0;
+    dQ = 3;
+    ec_enc_uint(&ec_encoder, dred_offset, 32);
+    ec_enc_uint(&ec_encoder, q0, 16);
+    ec_enc_uint(&ec_encoder, dQ, 8);
     dred_encode_state(&ec_encoder, enc->state_buffer);
 
     for (i = 0; i < IMIN(2*max_chunks, enc->latents_buffer_fill-1); i += 2)
@@ -95,7 +104,7 @@ int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int
         ec_enc ec_bak;
         ec_bak = ec_encoder;
 
-        q_level = (int) floor(0.5f + DRED_ENC_Q0 + 1.f * (DRED_ENC_Q1 - DRED_ENC_Q0) * i / (DRED_NUM_REDUNDANCY_FRAMES - 2));
+        q_level = compute_quantizer(q0, dQ, i/2);
         offset = q_level * DRED_LATENT_DIM;
 
         dred_encode_latents(