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(
--
⑨