From 8b42b00647df1c0ef5dd81459e355f293a9a28b6 Mon Sep 17 00:00:00 2001
From: Jean-Marc Valin <jmvalin@amazon.com>
Date: Mon, 5 Jun 2023 19:22:27 -0400
Subject: [PATCH] Fix DRED for 10-ms frames

---
 silk/dred_coding.c  | 8 ++++++--
 silk/dred_coding.h  | 2 +-
 silk/dred_encoder.c | 2 +-
 silk/dred_encoder.h | 2 +-
 src/opus_decoder.c  | 2 +-
 5 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/silk/dred_coding.c b/silk/dred_coding.c
index 34829390b..24e109ef7 100644
--- a/silk/dred_coding.c
+++ b/silk/dred_coding.c
@@ -38,6 +38,7 @@
 #include "celt/laplace.h"
 #include "os_support.h"
 #include "dred_config.h"
+#include "dred_coding.h"
 
 #define LATENT_DIM 80
 #define PVQ_DIM 24
@@ -74,9 +75,12 @@ static void encode_pvq(const int *iy, int N, int K, ec_enc *enc) {
     }
 }
 
-void dred_encode_state(ec_enc *enc, float *x) {
+void dred_encode_state(ec_enc *enc, const float *x) {
     int iy[PVQ_DIM];
-    op_pvq_search_c(x, iy, PVQ_K, PVQ_DIM, 0);
+    float x0[PVQ_DIM];
+    /* Copy state because the PVQ search will trash it. */
+    OPUS_COPY(x0, x, PVQ_DIM);
+    op_pvq_search_c(x0, iy, PVQ_K, PVQ_DIM, 0);
     encode_pvq(iy, PVQ_DIM, PVQ_K, enc);
 }
 
diff --git a/silk/dred_coding.h b/silk/dred_coding.h
index 662ba549d..0cefde7fb 100644
--- a/silk/dred_coding.h
+++ b/silk/dred_coding.h
@@ -33,7 +33,7 @@
 
 int compute_quantizer(int q0, int dQ, int i);
 
-void dred_encode_state(ec_enc *enc, float *x);
+void dred_encode_state(ec_enc *enc, const 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_encoder.c b/silk/dred_encoder.c
index 8d300af42..a6c827d9e 100644
--- a/silk/dred_encoder.c
+++ b/silk/dred_encoder.c
@@ -107,7 +107,7 @@ void dred_compute_latents(DREDEnc *enc, const float *pcm, int frame_size)
     }
 }
 
-int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes) {
+int dred_encode_silk_frame(const DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes) {
     const opus_uint16 *dead_zone       = DRED_rdovae_get_dead_zone_pointer();
     const opus_uint16 *p0              = DRED_rdovae_get_p0_pointer();
     const opus_uint16 *quant_scales    = DRED_rdovae_get_quant_scales_pointer();
diff --git a/silk/dred_encoder.h b/silk/dred_encoder.h
index 4f691bdd2..be96e3c04 100644
--- a/silk/dred_encoder.h
+++ b/silk/dred_encoder.h
@@ -59,6 +59,6 @@ void dred_deinit_encoder(DREDEnc *enc);
 
 void dred_compute_latents(DREDEnc *enc, const float *pcm, int frame_size);
 
-int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes);
+int dred_encode_silk_frame(const DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes);
 
 #endif
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index 8f5e96825..d28a052a1 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -670,7 +670,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
       if (st->lpcnet.blend == 0) needed_feature_frames+=2;
       for (i=0;i<needed_feature_frames;i++) {
          int feature_offset = (needed_feature_frames-i-1 + (dred_offset/(st->Fs/100)-2));
-         if (feature_offset <= 4*dred->nb_latents-1) {
+         if (feature_offset <= 4*dred->nb_latents-1 && feature_offset >= 0) {
            lpcnet_plc_fec_add(&st->lpcnet, dred->fec_features+feature_offset*DRED_NUM_FEATURES);
          } else {
            lpcnet_plc_fec_add(&st->lpcnet, NULL);
-- 
GitLab