shithub: opus

Download patch

ref: 9c137d493370cb195f0fb062f94b362c8bed481e
parent: 4fbf6dcaf46bbc13ddd91a5762a486981fd0a14a
author: Jean-Marc Valin <jmvalin@amazon.com>
date: Mon May 29 14:10:56 EDT 2023

Add offset and quantization to DRED bitstream

Brings the DRED implementation in line with the -00 draft

--- a/silk/dred_coding.c
+++ b/silk/dred_coding.c
@@ -37,10 +37,20 @@
 #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;
--- 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);
--- 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 */
--- a/silk/dred_decoder.c
+++ b/silk/dred_decoder.c
@@ -48,6 +48,8 @@
   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 @@
 
   /* 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 @@
       /* 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,
--- a/silk/dred_decoder.h
+++ b/silk/dred_decoder.h
@@ -39,6 +39,7 @@
     float        latents[(DRED_NUM_REDUNDANCY_FRAMES/2)*DRED_LATENT_DIM];
     int          nb_latents;
     int          process_stage;
+    int          dred_offset;
 };
 
 
--- a/silk/dred_encoder.c
+++ b/silk/dred_encoder.c
@@ -85,9 +85,18 @@
     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 @@
         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(
--