shithub: opus

Download patch

ref: dcce2fd455b1f407bf4e1347ce5358a6d0096bd2
parent: b589ab470add6e376a1ed4d72934fb74ee3636cc
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Sat Feb 24 18:37:44 EST 2024

Move all DRED encoding/decoding files to dnn/ dir

--- /dev/null
+++ b/dnn/dred_coding.c
@@ -1,0 +1,44 @@
+/* Copyright (c) 2022 Amazon
+   Written by Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+
+#include "celt/entenc.h"
+#include "os_support.h"
+#include "dred_config.h"
+#include "dred_coding.h"
+
+int compute_quantizer(int q0, int dQ, int qmax, int i) {
+  int quant;
+  static const int dQ_table[8] = {0, 2, 3, 4, 6, 8, 12, 16};
+  quant = q0 + (dQ_table[dQ]*i + 8)/16;
+  return quant > qmax ? qmax : quant;
+}
--- /dev/null
+++ b/dnn/dred_coding.h
@@ -1,0 +1,36 @@
+/* Copyright (c) 2022 Amazon
+   Written by Jan Buethe */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DRED_CODING_H
+#define DRED_CODING_H
+
+#include "opus_types.h"
+#include "entcode.h"
+
+int compute_quantizer(int q0, int dQ, int qmax, int i);
+
+#endif
--- /dev/null
+++ b/dnn/dred_config.h
@@ -1,0 +1,54 @@
+/* Copyright (c) 2022 Amazon
+   Written by Jan Buethe */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DRED_CONFIG_H
+#define DRED_CONFIG_H
+
+/* Change this once DRED gets an extension number assigned. */
+#define DRED_EXTENSION_ID 126
+
+/* Remove these two completely once DRED gets an extension number assigned. */
+#define DRED_EXPERIMENTAL_VERSION 10
+#define DRED_EXPERIMENTAL_BYTES 2
+
+
+#define DRED_MIN_BYTES 8
+
+/* these are inpart duplicates to the values defined in dred_rdovae_constants.h */
+#define DRED_SILK_ENCODER_DELAY (79+12-80)
+#define DRED_FRAME_SIZE 160
+#define DRED_DFRAME_SIZE (2 * (DRED_FRAME_SIZE))
+#define DRED_MAX_DATA_SIZE 1000
+#define DRED_ENC_Q0 6
+#define DRED_ENC_Q1 15
+
+/* Covers 1.04 second so we can cover one second, after the lookahead. */
+#define DRED_MAX_LATENTS 26
+#define DRED_NUM_REDUNDANCY_FRAMES (2*DRED_MAX_LATENTS)
+#define DRED_MAX_FRAMES (4*DRED_MAX_LATENTS)
+
+#endif
--- /dev/null
+++ b/dnn/dred_decoder.c
@@ -1,0 +1,129 @@
+/* Copyright (c) 2022 Amazon
+   Written by Jan Buethe */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "os_support.h"
+#include "dred_decoder.h"
+#include "dred_coding.h"
+#include "celt/entdec.h"
+#include "celt/laplace.h"
+#include "dred_rdovae_stats_data.h"
+#include "dred_rdovae_constants.h"
+
+static void dred_decode_latents(ec_dec *dec, float *x, const opus_uint8 *scale, const opus_uint8 *r, const opus_uint8 *p0, int dim) {
+    int i;
+    for (i=0;i<dim;i++) {
+        int q;
+        if (r[i] == 0 || p0[i] == 255) q = 0;
+        else q = ec_laplace_decode_p0(dec, p0[i]<<7, r[i]<<7);
+        x[i] = q*256.f/(scale[i] == 0 ? 1 : scale[i]);
+    }
+}
+
+int dred_ec_decode(OpusDRED *dec, const opus_uint8 *bytes, int num_bytes, int min_feature_frames, int dred_frame_offset)
+{
+  ec_dec ec;
+  int q_level;
+  int i;
+  int offset;
+  int q0;
+  int dQ;
+  int qmax;
+  int state_qoffset;
+  int extra_offset;
+
+  /* since features are decoded in quadruples, it makes no sense to go with an uneven number of redundancy frames */
+  celt_assert(DRED_NUM_REDUNDANCY_FRAMES % 2 == 0);
+
+  /* decode initial state and initialize RDOVAE decoder */
+  ec_dec_init(&ec, (unsigned char*)bytes, num_bytes);
+  q0 = ec_dec_uint(&ec, 16);
+  dQ = ec_dec_uint(&ec, 8);
+  if (ec_dec_uint(&ec, 2)) extra_offset = 32*ec_dec_uint(&ec, 256);
+  else extra_offset = 0;
+  /* Compute total offset, including DRED position in a multiframe packet. */
+  dec->dred_offset = 16 - ec_dec_uint(&ec, 32) - extra_offset + dred_frame_offset;
+  /*printf("%d %d %d\n", dred_offset, q0, dQ);*/
+  qmax = 15;
+  if (q0 < 14 && dQ > 0) {
+    int nvals;
+    int ft;
+    int s;
+    /* The distribution for the dQmax symbol is split evenly between zero
+        (which implies qmax == 15) and larger values, with the probability of
+        all larger values being uniform.
+       This is equivalent to coding 1 bit to decide if the maximum is less than
+        15 followed by a uint to decide the actual value if it is less than
+        15, but combined into a single symbol. */
+    nvals = 15 - (q0 + 1);
+    ft = 2*nvals;
+    s = ec_decode(&ec, ft);
+    if (s >= nvals) {
+      qmax = q0 + (s - nvals) + 1;
+      ec_dec_update(&ec, s, s + 1, ft);
+    }
+    else {
+      ec_dec_update(&ec, 0, nvals, ft);
+    }
+  }
+  state_qoffset = q0*DRED_STATE_DIM;
+  dred_decode_latents(
+      &ec,
+      dec->state,
+      dred_state_quant_scales_q8 + state_qoffset,
+      dred_state_r_q8 + state_qoffset,
+      dred_state_p0_q8 + state_qoffset,
+      DRED_STATE_DIM);
+
+  /* decode newest to oldest and store oldest to newest */
+  for (i = 0; i < IMIN(DRED_NUM_REDUNDANCY_FRAMES, (min_feature_frames+1)/2); i += 2)
+  {
+      /* 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 = compute_quantizer(q0, dQ, qmax, i/2);
+      offset = q_level*DRED_LATENT_DIM;
+      dred_decode_latents(
+          &ec,
+          &dec->latents[(i/2)*DRED_LATENT_DIM],
+          dred_latent_quant_scales_q8 + offset,
+          dred_latent_r_q8 + offset,
+          dred_latent_p0_q8 + offset,
+          DRED_LATENT_DIM
+          );
+
+      offset = 2 * i * DRED_NUM_FEATURES;
+  }
+  dec->process_stage = 1;
+  dec->nb_latents = i/2;
+  return i/2;
+}
--- /dev/null
+++ b/dnn/dred_decoder.h
@@ -1,0 +1,49 @@
+/* Copyright (c) 2022 Amazon
+   Written by Jan Buethe */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DRED_DECODER_H
+#define DRED_DECODER_H
+
+#include "opus.h"
+#include "dred_config.h"
+#include "dred_rdovae.h"
+#include "entcode.h"
+#include "dred_rdovae_constants.h"
+
+struct OpusDRED {
+    float        fec_features[2*DRED_NUM_REDUNDANCY_FRAMES*DRED_NUM_FEATURES];
+    float        state[DRED_STATE_DIM];
+    float        latents[(DRED_NUM_REDUNDANCY_FRAMES/2)*DRED_LATENT_DIM];
+    int          nb_latents;
+    int          process_stage;
+    int          dred_offset;
+};
+
+
+int dred_ec_decode(OpusDRED *dec, const opus_uint8 *bytes, int num_bytes, int min_feature_frames, int dred_frame_offset);
+
+#endif
--- /dev/null
+++ b/dnn/dred_encoder.c
@@ -1,0 +1,363 @@
+/* Copyright (c) 2022 Amazon
+   Written by Jan Buethe */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#if 0
+#include <stdio.h>
+#include <math.h>
+#endif
+
+#include "dred_encoder.h"
+#include "dred_coding.h"
+#include "celt/entenc.h"
+
+#include "dred_decoder.h"
+#include "float_cast.h"
+#include "os_support.h"
+#include "celt/laplace.h"
+#include "dred_rdovae_stats_data.h"
+
+
+static void DRED_rdovae_init_encoder(RDOVAEEncState *enc_state)
+{
+    memset(enc_state, 0, sizeof(*enc_state));
+}
+
+int dred_encoder_load_model(DREDEnc* enc, const unsigned char *data, int len)
+{
+    WeightArray *list;
+    int ret;
+    parse_weights(&list, data, len);
+    ret = init_rdovaeenc(&enc->model, list);
+    opus_free(list);
+    if (ret == 0) {
+      ret = lpcnet_encoder_load_model(&enc->lpcnet_enc_state, data, len);
+    }
+    if (ret == 0) enc->loaded = 1;
+    return (ret == 0) ? OPUS_OK : OPUS_BAD_ARG;
+}
+
+void dred_encoder_reset(DREDEnc* enc)
+{
+    OPUS_CLEAR((char*)&enc->DREDENC_RESET_START,
+              sizeof(DREDEnc)-
+              ((char*)&enc->DREDENC_RESET_START - (char*)enc));
+    enc->input_buffer_fill = DRED_SILK_ENCODER_DELAY;
+    lpcnet_encoder_init(&enc->lpcnet_enc_state);
+    DRED_rdovae_init_encoder(&enc->rdovae_enc);
+}
+
+void dred_encoder_init(DREDEnc* enc, opus_int32 Fs, int channels)
+{
+    enc->Fs = Fs;
+    enc->channels = channels;
+    enc->loaded = 0;
+#ifndef USE_WEIGHTS_FILE
+    if (init_rdovaeenc(&enc->model, rdovaeenc_arrays) == 0) enc->loaded = 1;
+#endif
+    dred_encoder_reset(enc);
+}
+
+static void dred_process_frame(DREDEnc *enc, int arch)
+{
+    float feature_buffer[2 * 36];
+    float input_buffer[2*DRED_NUM_FEATURES] = {0};
+
+    celt_assert(enc->loaded);
+    /* shift latents buffer */
+    OPUS_MOVE(enc->latents_buffer + DRED_LATENT_DIM, enc->latents_buffer, (DRED_MAX_FRAMES - 1) * DRED_LATENT_DIM);
+    OPUS_MOVE(enc->state_buffer + DRED_STATE_DIM, enc->state_buffer, (DRED_MAX_FRAMES - 1) * DRED_STATE_DIM);
+
+    /* calculate LPCNet features */
+    lpcnet_compute_single_frame_features_float(&enc->lpcnet_enc_state, enc->input_buffer, feature_buffer, arch);
+    lpcnet_compute_single_frame_features_float(&enc->lpcnet_enc_state, enc->input_buffer + DRED_FRAME_SIZE, feature_buffer + 36, arch);
+
+    /* prepare input buffer (discard LPC coefficients) */
+    OPUS_COPY(input_buffer, feature_buffer, DRED_NUM_FEATURES);
+    OPUS_COPY(input_buffer + DRED_NUM_FEATURES, feature_buffer + 36, DRED_NUM_FEATURES);
+
+    /* run RDOVAE encoder */
+    dred_rdovae_encode_dframe(&enc->rdovae_enc, &enc->model, enc->latents_buffer, enc->state_buffer, input_buffer, arch);
+    enc->latents_buffer_fill = IMIN(enc->latents_buffer_fill+1, DRED_NUM_REDUNDANCY_FRAMES);
+}
+
+void filter_df2t(const float *in, float *out, int len, float b0, const float *b, const float *a, int order, float *mem)
+{
+    int i;
+    for (i=0;i<len;i++) {
+        int j;
+        float xi, yi, nyi;
+        xi = in[i];
+        yi = xi*b0 + mem[0];
+        nyi = -yi;
+        for (j=0;j<order;j++)
+        {
+           mem[j] = mem[j+1] + b[j]*xi + a[j]*nyi;
+        }
+        out[i] = yi;
+        /*fprintf(stdout, "%f\n", out[i]);*/
+    }
+}
+
+#define MAX_DOWNMIX_BUFFER (960*2)
+static void dred_convert_to_16k(DREDEnc *enc, const float *in, int in_len, float *out, int out_len)
+{
+    float downmix[MAX_DOWNMIX_BUFFER];
+    int i;
+    int up;
+    celt_assert(enc->channels*in_len <= MAX_DOWNMIX_BUFFER);
+    celt_assert(in_len * (opus_int32)16000 == out_len * enc->Fs);
+    switch(enc->Fs) {
+        case 8000:
+            up = 2;
+            break;
+        case 12000:
+            up = 4;
+            break;
+        case 16000:
+            up = 1;
+            break;
+        case 24000:
+            up = 2;
+            break;
+        case 48000:
+            up = 1;
+            break;
+        default:
+            celt_assert(0);
+    }
+    OPUS_CLEAR(downmix, up*in_len);
+    if (enc->channels == 1) {
+        for (i=0;i<in_len;i++) downmix[up*i] = FLOAT2INT16(up*in[i]);
+    } else {
+        for (i=0;i<in_len;i++) downmix[up*i] = FLOAT2INT16(.5*up*(in[2*i]+in[2*i+1]));
+    }
+    if (enc->Fs == 16000) {
+        OPUS_COPY(out, downmix, out_len);
+    } else if (enc->Fs == 48000 || enc->Fs == 24000) {
+        /* ellip(7, .2, 70, 7750/24000) */
+
+        static const float filter_b[8] = { 0.005873358047f,  0.012980854831f, 0.014531340042f,  0.014531340042f, 0.012980854831f,  0.005873358047f, 0.004523418224f, 0.f};
+        static const float filter_a[8] = {-3.878718597768f, 7.748834257468f, -9.653651699533f, 8.007342726666f, -4.379450178552f, 1.463182111810f, -0.231720677804f, 0.f};
+        float b0 = 0.004523418224f;
+        filter_df2t(downmix, downmix, up*in_len, b0, filter_b, filter_a, RESAMPLING_ORDER, enc->resample_mem);
+        for (i=0;i<out_len;i++) out[i] = downmix[3*i];
+    } else if (enc->Fs == 12000) {
+        /* ellip(7, .2, 70, 7750/24000) */
+        static const float filter_b[8] = {-0.001017101081f,  0.003673127243f,   0.001009165267f,  0.001009165267f,  0.003673127243f, -0.001017101081f,  0.002033596776f, 0.f};
+        static const float filter_a[8] = {-4.930414411612f, 11.291643096504f, -15.322037343815f, 13.216403930898f, -7.220409219553f,  2.310550142771f, -0.334338618782f, 0.f};
+        float b0 = 0.002033596776f;
+        filter_df2t(downmix, downmix, up*in_len, b0, filter_b, filter_a, RESAMPLING_ORDER, enc->resample_mem);
+        for (i=0;i<out_len;i++) out[i] = downmix[3*i];
+    } else if (enc->Fs == 8000) {
+        /* ellip(7, .2, 70, 3900/8000) */
+        static const float filter_b[8] = { 0.081670120929f, 0.180401598565f,  0.259391051971f, 0.259391051971f,  0.180401598565f, 0.081670120929f,  0.020109185709f, 0.f};
+        static const float filter_a[8] = {-1.393651933659f, 2.609789872676f, -2.403541968806f, 2.056814957331f, -1.148908574570f, 0.473001413788f, -0.110359852412f, 0.f};
+        float b0 = 0.020109185709f;
+        filter_df2t(downmix, out, out_len, b0, filter_b, filter_a, RESAMPLING_ORDER, enc->resample_mem);
+    } else {
+        celt_assert(0);
+    }
+}
+
+void dred_compute_latents(DREDEnc *enc, const float *pcm, int frame_size, int extra_delay, int arch)
+{
+    int curr_offset16k;
+    int frame_size16k = frame_size * 16000 / enc->Fs;
+    celt_assert(enc->loaded);
+    curr_offset16k = 40 + extra_delay*16000/enc->Fs - enc->input_buffer_fill;
+    enc->dred_offset = (int)floor((curr_offset16k+20.f)/40.f);
+    enc->latent_offset = 0;
+    while (frame_size16k > 0) {
+        int process_size16k;
+        int process_size;
+        process_size16k = IMIN(2*DRED_FRAME_SIZE, frame_size16k);
+        process_size = process_size16k * enc->Fs / 16000;
+        dred_convert_to_16k(enc, pcm, process_size, &enc->input_buffer[enc->input_buffer_fill], process_size16k);
+        enc->input_buffer_fill += process_size16k;
+        if (enc->input_buffer_fill >= 2*DRED_FRAME_SIZE)
+        {
+            curr_offset16k += 320;
+            dred_process_frame(enc, arch);
+            enc->input_buffer_fill -= 2*DRED_FRAME_SIZE;
+            OPUS_MOVE(&enc->input_buffer[0], &enc->input_buffer[2*DRED_FRAME_SIZE], enc->input_buffer_fill);
+            /* 15 ms (6*2.5 ms) is the ideal offset for DRED because it corresponds to our vocoder look-ahead. */
+            if (enc->dred_offset < 6) {
+                enc->dred_offset += 8;
+            } else {
+                enc->latent_offset++;
+            }
+        }
+
+        pcm += process_size;
+        frame_size16k -= process_size16k;
+    }
+}
+
+static void dred_encode_latents(ec_enc *enc, const float *x, const opus_uint8 *scale, const opus_uint8 *dzone, const opus_uint8 *r, const opus_uint8 *p0, int dim, int arch) {
+    int i;
+    int q[IMAX(DRED_LATENT_DIM,DRED_STATE_DIM)];
+    float xq[IMAX(DRED_LATENT_DIM,DRED_STATE_DIM)];
+    float delta[IMAX(DRED_LATENT_DIM,DRED_STATE_DIM)];
+    float deadzone[IMAX(DRED_LATENT_DIM,DRED_STATE_DIM)];
+    float eps = .1f;
+    /* This is split into multiple loops (with temporary arrays) so that the compiler
+       can vectorize all of it, and so we can call the vector tanh(). */
+    for (i=0;i<dim;i++) {
+        delta[i] = dzone[i]*(1.f/256.f);
+        xq[i] = x[i]*scale[i]*(1.f/256.f);
+        deadzone[i] = xq[i]/(delta[i]+eps);
+    }
+    compute_activation(deadzone, deadzone, dim, ACTIVATION_TANH, arch);
+    for (i=0;i<dim;i++) {
+        xq[i] = xq[i] - delta[i]*deadzone[i];
+        q[i] = (int)floor(.5f+xq[i]);
+    }
+    for (i=0;i<dim;i++) {
+        /* Make the impossible actually impossible. */
+        if (r[i] == 0 || p0[i] == 255) q[i] = 0;
+        else ec_laplace_encode_p0(enc, q[i], p0[i]<<7, r[i]<<7);
+    }
+}
+
+static int dred_voice_active(const unsigned char *activity_mem, int offset) {
+    int i;
+    for (i=0;i<16;i++) {
+        if (activity_mem[8*offset + i] == 1) return 1;
+    }
+    return 0;
+}
+
+int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes, int q0, int dQ, int qmax, unsigned char *activity_mem, int arch) {
+    ec_enc ec_encoder;
+
+    int q_level;
+    int i;
+    int offset;
+    int ec_buffer_fill;
+    int state_qoffset;
+    ec_enc ec_bak;
+    int prev_active=0;
+    int latent_offset;
+    int extra_dred_offset=0;
+    int dred_encoded=0;
+    int delayed_dred=0;
+    int total_offset;
+
+    latent_offset = enc->latent_offset;
+    /* Delaying new DRED data when just out of silence because we already have the
+       main Opus payload for that frame. */
+    if (activity_mem[0] && enc->last_extra_dred_offset>0) {
+        latent_offset = enc->last_extra_dred_offset;
+        delayed_dred = 1;
+        enc->last_extra_dred_offset = 0;
+    }
+    while (latent_offset < enc->latents_buffer_fill && !dred_voice_active(activity_mem, latent_offset)) {
+       latent_offset++;
+       extra_dred_offset++;
+    }
+    if (!delayed_dred) enc->last_extra_dred_offset = extra_dred_offset;
+
+    /* entropy coding of state and latents */
+    ec_enc_init(&ec_encoder, buf, max_bytes);
+    ec_enc_uint(&ec_encoder, q0, 16);
+    ec_enc_uint(&ec_encoder, dQ, 8);
+    total_offset = 16 - (enc->dred_offset - extra_dred_offset*8);
+    celt_assert(total_offset>=0);
+    if (total_offset > 31) {
+       ec_enc_uint(&ec_encoder, 1, 2);
+       ec_enc_uint(&ec_encoder, total_offset>>5, 256);
+       ec_enc_uint(&ec_encoder, total_offset&31, 32);
+    } else {
+       ec_enc_uint(&ec_encoder, 0, 2);
+       ec_enc_uint(&ec_encoder, total_offset, 32);
+    }
+    celt_assert(qmax >= q0);
+    if (q0 < 14 && dQ > 0) {
+      int nvals;
+      /* If you want to use qmax == q0, you should have set dQ = 0. */
+      celt_assert(qmax > q0);
+      nvals = 15 - (q0 + 1);
+      ec_encode(&ec_encoder, qmax >= 15 ? 0 : nvals + qmax - (q0 + 1),
+        qmax >= 15 ? nvals : nvals + qmax - q0, 2*nvals);
+    }
+    state_qoffset = q0*DRED_STATE_DIM;
+    dred_encode_latents(
+        &ec_encoder,
+        &enc->state_buffer[latent_offset*DRED_STATE_DIM],
+        dred_state_quant_scales_q8 + state_qoffset,
+        dred_state_dead_zone_q8 + state_qoffset,
+        dred_state_r_q8 + state_qoffset,
+        dred_state_p0_q8 + state_qoffset,
+        DRED_STATE_DIM,
+        arch);
+    if (ec_tell(&ec_encoder) > 8*max_bytes) {
+      return 0;
+    }
+    ec_bak = ec_encoder;
+    for (i = 0; i < IMIN(2*max_chunks, enc->latents_buffer_fill-latent_offset-1); i += 2)
+    {
+        int active;
+        q_level = compute_quantizer(q0, dQ, qmax, i/2);
+        offset = q_level * DRED_LATENT_DIM;
+
+        dred_encode_latents(
+            &ec_encoder,
+            enc->latents_buffer + (i+latent_offset) * DRED_LATENT_DIM,
+            dred_latent_quant_scales_q8 + offset,
+            dred_latent_dead_zone_q8 + offset,
+            dred_latent_r_q8 + offset,
+            dred_latent_p0_q8 + offset,
+            DRED_LATENT_DIM,
+            arch
+        );
+        if (ec_tell(&ec_encoder) > 8*max_bytes) {
+          /* If we haven't been able to code one chunk, give up on DRED completely. */
+          if (i==0) return 0;
+          break;
+        }
+        active = dred_voice_active(activity_mem, i+latent_offset);
+        if (active || prev_active) {
+           ec_bak = ec_encoder;
+           dred_encoded = i+2;
+        }
+        prev_active = active;
+    }
+    /* Avoid sending empty DRED packets. */
+    if (dred_encoded==0 || (dred_encoded<=2 && extra_dred_offset)) return 0;
+    ec_encoder = ec_bak;
+
+    ec_buffer_fill = (ec_tell(&ec_encoder)+7)/8;
+    ec_enc_shrink(&ec_encoder, ec_buffer_fill);
+    ec_enc_done(&ec_encoder);
+    return ec_buffer_fill;
+}
--- /dev/null
+++ b/dnn/dred_encoder.h
@@ -1,0 +1,71 @@
+/* Copyright (c) 2022 Amazon
+   Written by Jan Buethe */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DRED_ENCODER_H
+#define DRED_ENCODER_H
+
+#include "lpcnet.h"
+#include "dred_config.h"
+#include "dred_rdovae.h"
+#include "entcode.h"
+#include "lpcnet_private.h"
+#include "dred_rdovae_enc.h"
+#include "dred_rdovae_enc_data.h"
+
+#define RESAMPLING_ORDER 8
+
+typedef struct {
+    RDOVAEEnc model;
+    LPCNetEncState lpcnet_enc_state;
+    RDOVAEEncState rdovae_enc;
+    int loaded;
+    opus_int32 Fs;
+    int channels;
+
+#define DREDENC_RESET_START input_buffer
+    float input_buffer[2*DRED_DFRAME_SIZE];
+    int input_buffer_fill;
+    int dred_offset;
+    int latent_offset;
+    int last_extra_dred_offset;
+    float latents_buffer[DRED_MAX_FRAMES * DRED_LATENT_DIM];
+    int latents_buffer_fill;
+    float state_buffer[DRED_MAX_FRAMES * DRED_STATE_DIM];
+    float resample_mem[RESAMPLING_ORDER + 1];
+} DREDEnc;
+
+int dred_encoder_load_model(DREDEnc* enc, const unsigned char *data, int len);
+void dred_encoder_init(DREDEnc* enc, opus_int32 Fs, int channels);
+void dred_encoder_reset(DREDEnc* enc);
+
+void dred_deinit_encoder(DREDEnc *enc);
+
+void dred_compute_latents(DREDEnc *enc, const float *pcm, int frame_size, int extra_delay, int arch);
+
+int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes, int q0, int dQ, int qmax, unsigned char *activity_mem, int arch);
+
+#endif
--- a/lpcnet_headers.mk
+++ b/lpcnet_headers.mk
@@ -18,10 +18,10 @@
 dnn/arm/dnn_arm.h
 
 DRED_HEAD = \
-silk/dred_coding.h \
-silk/dred_config.h \
-silk/dred_decoder.h \
-silk/dred_encoder.h \
+dnn/dred_coding.h \
+dnn/dred_config.h \
+dnn/dred_decoder.h \
+dnn/dred_encoder.h \
 dnn/dred_rdovae.h \
 dnn/dred_rdovae_constants.h \
 dnn/dred_rdovae_enc.h \
--- a/lpcnet_sources.mk
+++ b/lpcnet_sources.mk
@@ -19,9 +19,9 @@
 dnn/dred_rdovae_dec.c \
 dnn/dred_rdovae_dec_data.c \
 dnn/dred_rdovae_stats_data.c \
-silk/dred_encoder.c \
-silk/dred_coding.c \
-silk/dred_decoder.c
+dnn/dred_encoder.c \
+dnn/dred_coding.c \
+dnn/dred_decoder.c
 
 OSCE_SOURCES = \
 dnn/osce.c \
--- a/silk/dred_coding.c
+++ /dev/null
@@ -1,44 +1,0 @@
-/* Copyright (c) 2022 Amazon
-   Written by Jean-Marc Valin */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <math.h>
-
-#include "celt/entenc.h"
-#include "os_support.h"
-#include "dred_config.h"
-#include "dred_coding.h"
-
-int compute_quantizer(int q0, int dQ, int qmax, int i) {
-  int quant;
-  static const int dQ_table[8] = {0, 2, 3, 4, 6, 8, 12, 16};
-  quant = q0 + (dQ_table[dQ]*i + 8)/16;
-  return quant > qmax ? qmax : quant;
-}
--- a/silk/dred_coding.h
+++ /dev/null
@@ -1,36 +1,0 @@
-/* Copyright (c) 2022 Amazon
-   Written by Jan Buethe */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef DRED_CODING_H
-#define DRED_CODING_H
-
-#include "opus_types.h"
-#include "entcode.h"
-
-int compute_quantizer(int q0, int dQ, int qmax, int i);
-
-#endif
--- a/silk/dred_config.h
+++ /dev/null
@@ -1,54 +1,0 @@
-/* Copyright (c) 2022 Amazon
-   Written by Jan Buethe */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef DRED_CONFIG_H
-#define DRED_CONFIG_H
-
-/* Change this once DRED gets an extension number assigned. */
-#define DRED_EXTENSION_ID 126
-
-/* Remove these two completely once DRED gets an extension number assigned. */
-#define DRED_EXPERIMENTAL_VERSION 10
-#define DRED_EXPERIMENTAL_BYTES 2
-
-
-#define DRED_MIN_BYTES 8
-
-/* these are inpart duplicates to the values defined in dred_rdovae_constants.h */
-#define DRED_SILK_ENCODER_DELAY (79+12-80)
-#define DRED_FRAME_SIZE 160
-#define DRED_DFRAME_SIZE (2 * (DRED_FRAME_SIZE))
-#define DRED_MAX_DATA_SIZE 1000
-#define DRED_ENC_Q0 6
-#define DRED_ENC_Q1 15
-
-/* Covers 1.04 second so we can cover one second, after the lookahead. */
-#define DRED_MAX_LATENTS 26
-#define DRED_NUM_REDUNDANCY_FRAMES (2*DRED_MAX_LATENTS)
-#define DRED_MAX_FRAMES (4*DRED_MAX_LATENTS)
-
-#endif
--- a/silk/dred_decoder.c
+++ /dev/null
@@ -1,129 +1,0 @@
-/* Copyright (c) 2022 Amazon
-   Written by Jan Buethe */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <string.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "os_support.h"
-#include "dred_decoder.h"
-#include "dred_coding.h"
-#include "celt/entdec.h"
-#include "celt/laplace.h"
-#include "dred_rdovae_stats_data.h"
-#include "dred_rdovae_constants.h"
-
-static void dred_decode_latents(ec_dec *dec, float *x, const opus_uint8 *scale, const opus_uint8 *r, const opus_uint8 *p0, int dim) {
-    int i;
-    for (i=0;i<dim;i++) {
-        int q;
-        if (r[i] == 0 || p0[i] == 255) q = 0;
-        else q = ec_laplace_decode_p0(dec, p0[i]<<7, r[i]<<7);
-        x[i] = q*256.f/(scale[i] == 0 ? 1 : scale[i]);
-    }
-}
-
-int dred_ec_decode(OpusDRED *dec, const opus_uint8 *bytes, int num_bytes, int min_feature_frames, int dred_frame_offset)
-{
-  ec_dec ec;
-  int q_level;
-  int i;
-  int offset;
-  int q0;
-  int dQ;
-  int qmax;
-  int state_qoffset;
-  int extra_offset;
-
-  /* since features are decoded in quadruples, it makes no sense to go with an uneven number of redundancy frames */
-  celt_assert(DRED_NUM_REDUNDANCY_FRAMES % 2 == 0);
-
-  /* decode initial state and initialize RDOVAE decoder */
-  ec_dec_init(&ec, (unsigned char*)bytes, num_bytes);
-  q0 = ec_dec_uint(&ec, 16);
-  dQ = ec_dec_uint(&ec, 8);
-  if (ec_dec_uint(&ec, 2)) extra_offset = 32*ec_dec_uint(&ec, 256);
-  else extra_offset = 0;
-  /* Compute total offset, including DRED position in a multiframe packet. */
-  dec->dred_offset = 16 - ec_dec_uint(&ec, 32) - extra_offset + dred_frame_offset;
-  /*printf("%d %d %d\n", dred_offset, q0, dQ);*/
-  qmax = 15;
-  if (q0 < 14 && dQ > 0) {
-    int nvals;
-    int ft;
-    int s;
-    /* The distribution for the dQmax symbol is split evenly between zero
-        (which implies qmax == 15) and larger values, with the probability of
-        all larger values being uniform.
-       This is equivalent to coding 1 bit to decide if the maximum is less than
-        15 followed by a uint to decide the actual value if it is less than
-        15, but combined into a single symbol. */
-    nvals = 15 - (q0 + 1);
-    ft = 2*nvals;
-    s = ec_decode(&ec, ft);
-    if (s >= nvals) {
-      qmax = q0 + (s - nvals) + 1;
-      ec_dec_update(&ec, s, s + 1, ft);
-    }
-    else {
-      ec_dec_update(&ec, 0, nvals, ft);
-    }
-  }
-  state_qoffset = q0*DRED_STATE_DIM;
-  dred_decode_latents(
-      &ec,
-      dec->state,
-      dred_state_quant_scales_q8 + state_qoffset,
-      dred_state_r_q8 + state_qoffset,
-      dred_state_p0_q8 + state_qoffset,
-      DRED_STATE_DIM);
-
-  /* decode newest to oldest and store oldest to newest */
-  for (i = 0; i < IMIN(DRED_NUM_REDUNDANCY_FRAMES, (min_feature_frames+1)/2); i += 2)
-  {
-      /* 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 = compute_quantizer(q0, dQ, qmax, i/2);
-      offset = q_level*DRED_LATENT_DIM;
-      dred_decode_latents(
-          &ec,
-          &dec->latents[(i/2)*DRED_LATENT_DIM],
-          dred_latent_quant_scales_q8 + offset,
-          dred_latent_r_q8 + offset,
-          dred_latent_p0_q8 + offset,
-          DRED_LATENT_DIM
-          );
-
-      offset = 2 * i * DRED_NUM_FEATURES;
-  }
-  dec->process_stage = 1;
-  dec->nb_latents = i/2;
-  return i/2;
-}
--- a/silk/dred_decoder.h
+++ /dev/null
@@ -1,49 +1,0 @@
-/* Copyright (c) 2022 Amazon
-   Written by Jan Buethe */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef DRED_DECODER_H
-#define DRED_DECODER_H
-
-#include "opus.h"
-#include "dred_config.h"
-#include "dred_rdovae.h"
-#include "entcode.h"
-#include "dred_rdovae_constants.h"
-
-struct OpusDRED {
-    float        fec_features[2*DRED_NUM_REDUNDANCY_FRAMES*DRED_NUM_FEATURES];
-    float        state[DRED_STATE_DIM];
-    float        latents[(DRED_NUM_REDUNDANCY_FRAMES/2)*DRED_LATENT_DIM];
-    int          nb_latents;
-    int          process_stage;
-    int          dred_offset;
-};
-
-
-int dred_ec_decode(OpusDRED *dec, const opus_uint8 *bytes, int num_bytes, int min_feature_frames, int dred_frame_offset);
-
-#endif
--- a/silk/dred_encoder.c
+++ /dev/null
@@ -1,363 +1,0 @@
-/* Copyright (c) 2022 Amazon
-   Written by Jan Buethe */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#if 0
-#include <stdio.h>
-#include <math.h>
-#endif
-
-#include "dred_encoder.h"
-#include "dred_coding.h"
-#include "celt/entenc.h"
-
-#include "dred_decoder.h"
-#include "float_cast.h"
-#include "os_support.h"
-#include "celt/laplace.h"
-#include "dred_rdovae_stats_data.h"
-
-
-static void DRED_rdovae_init_encoder(RDOVAEEncState *enc_state)
-{
-    memset(enc_state, 0, sizeof(*enc_state));
-}
-
-int dred_encoder_load_model(DREDEnc* enc, const unsigned char *data, int len)
-{
-    WeightArray *list;
-    int ret;
-    parse_weights(&list, data, len);
-    ret = init_rdovaeenc(&enc->model, list);
-    opus_free(list);
-    if (ret == 0) {
-      ret = lpcnet_encoder_load_model(&enc->lpcnet_enc_state, data, len);
-    }
-    if (ret == 0) enc->loaded = 1;
-    return (ret == 0) ? OPUS_OK : OPUS_BAD_ARG;
-}
-
-void dred_encoder_reset(DREDEnc* enc)
-{
-    OPUS_CLEAR((char*)&enc->DREDENC_RESET_START,
-              sizeof(DREDEnc)-
-              ((char*)&enc->DREDENC_RESET_START - (char*)enc));
-    enc->input_buffer_fill = DRED_SILK_ENCODER_DELAY;
-    lpcnet_encoder_init(&enc->lpcnet_enc_state);
-    DRED_rdovae_init_encoder(&enc->rdovae_enc);
-}
-
-void dred_encoder_init(DREDEnc* enc, opus_int32 Fs, int channels)
-{
-    enc->Fs = Fs;
-    enc->channels = channels;
-    enc->loaded = 0;
-#ifndef USE_WEIGHTS_FILE
-    if (init_rdovaeenc(&enc->model, rdovaeenc_arrays) == 0) enc->loaded = 1;
-#endif
-    dred_encoder_reset(enc);
-}
-
-static void dred_process_frame(DREDEnc *enc, int arch)
-{
-    float feature_buffer[2 * 36];
-    float input_buffer[2*DRED_NUM_FEATURES] = {0};
-
-    celt_assert(enc->loaded);
-    /* shift latents buffer */
-    OPUS_MOVE(enc->latents_buffer + DRED_LATENT_DIM, enc->latents_buffer, (DRED_MAX_FRAMES - 1) * DRED_LATENT_DIM);
-    OPUS_MOVE(enc->state_buffer + DRED_STATE_DIM, enc->state_buffer, (DRED_MAX_FRAMES - 1) * DRED_STATE_DIM);
-
-    /* calculate LPCNet features */
-    lpcnet_compute_single_frame_features_float(&enc->lpcnet_enc_state, enc->input_buffer, feature_buffer, arch);
-    lpcnet_compute_single_frame_features_float(&enc->lpcnet_enc_state, enc->input_buffer + DRED_FRAME_SIZE, feature_buffer + 36, arch);
-
-    /* prepare input buffer (discard LPC coefficients) */
-    OPUS_COPY(input_buffer, feature_buffer, DRED_NUM_FEATURES);
-    OPUS_COPY(input_buffer + DRED_NUM_FEATURES, feature_buffer + 36, DRED_NUM_FEATURES);
-
-    /* run RDOVAE encoder */
-    dred_rdovae_encode_dframe(&enc->rdovae_enc, &enc->model, enc->latents_buffer, enc->state_buffer, input_buffer, arch);
-    enc->latents_buffer_fill = IMIN(enc->latents_buffer_fill+1, DRED_NUM_REDUNDANCY_FRAMES);
-}
-
-void filter_df2t(const float *in, float *out, int len, float b0, const float *b, const float *a, int order, float *mem)
-{
-    int i;
-    for (i=0;i<len;i++) {
-        int j;
-        float xi, yi, nyi;
-        xi = in[i];
-        yi = xi*b0 + mem[0];
-        nyi = -yi;
-        for (j=0;j<order;j++)
-        {
-           mem[j] = mem[j+1] + b[j]*xi + a[j]*nyi;
-        }
-        out[i] = yi;
-        /*fprintf(stdout, "%f\n", out[i]);*/
-    }
-}
-
-#define MAX_DOWNMIX_BUFFER (960*2)
-static void dred_convert_to_16k(DREDEnc *enc, const float *in, int in_len, float *out, int out_len)
-{
-    float downmix[MAX_DOWNMIX_BUFFER];
-    int i;
-    int up;
-    celt_assert(enc->channels*in_len <= MAX_DOWNMIX_BUFFER);
-    celt_assert(in_len * (opus_int32)16000 == out_len * enc->Fs);
-    switch(enc->Fs) {
-        case 8000:
-            up = 2;
-            break;
-        case 12000:
-            up = 4;
-            break;
-        case 16000:
-            up = 1;
-            break;
-        case 24000:
-            up = 2;
-            break;
-        case 48000:
-            up = 1;
-            break;
-        default:
-            celt_assert(0);
-    }
-    OPUS_CLEAR(downmix, up*in_len);
-    if (enc->channels == 1) {
-        for (i=0;i<in_len;i++) downmix[up*i] = FLOAT2INT16(up*in[i]);
-    } else {
-        for (i=0;i<in_len;i++) downmix[up*i] = FLOAT2INT16(.5*up*(in[2*i]+in[2*i+1]));
-    }
-    if (enc->Fs == 16000) {
-        OPUS_COPY(out, downmix, out_len);
-    } else if (enc->Fs == 48000 || enc->Fs == 24000) {
-        /* ellip(7, .2, 70, 7750/24000) */
-
-        static const float filter_b[8] = { 0.005873358047f,  0.012980854831f, 0.014531340042f,  0.014531340042f, 0.012980854831f,  0.005873358047f, 0.004523418224f, 0.f};
-        static const float filter_a[8] = {-3.878718597768f, 7.748834257468f, -9.653651699533f, 8.007342726666f, -4.379450178552f, 1.463182111810f, -0.231720677804f, 0.f};
-        float b0 = 0.004523418224f;
-        filter_df2t(downmix, downmix, up*in_len, b0, filter_b, filter_a, RESAMPLING_ORDER, enc->resample_mem);
-        for (i=0;i<out_len;i++) out[i] = downmix[3*i];
-    } else if (enc->Fs == 12000) {
-        /* ellip(7, .2, 70, 7750/24000) */
-        static const float filter_b[8] = {-0.001017101081f,  0.003673127243f,   0.001009165267f,  0.001009165267f,  0.003673127243f, -0.001017101081f,  0.002033596776f, 0.f};
-        static const float filter_a[8] = {-4.930414411612f, 11.291643096504f, -15.322037343815f, 13.216403930898f, -7.220409219553f,  2.310550142771f, -0.334338618782f, 0.f};
-        float b0 = 0.002033596776f;
-        filter_df2t(downmix, downmix, up*in_len, b0, filter_b, filter_a, RESAMPLING_ORDER, enc->resample_mem);
-        for (i=0;i<out_len;i++) out[i] = downmix[3*i];
-    } else if (enc->Fs == 8000) {
-        /* ellip(7, .2, 70, 3900/8000) */
-        static const float filter_b[8] = { 0.081670120929f, 0.180401598565f,  0.259391051971f, 0.259391051971f,  0.180401598565f, 0.081670120929f,  0.020109185709f, 0.f};
-        static const float filter_a[8] = {-1.393651933659f, 2.609789872676f, -2.403541968806f, 2.056814957331f, -1.148908574570f, 0.473001413788f, -0.110359852412f, 0.f};
-        float b0 = 0.020109185709f;
-        filter_df2t(downmix, out, out_len, b0, filter_b, filter_a, RESAMPLING_ORDER, enc->resample_mem);
-    } else {
-        celt_assert(0);
-    }
-}
-
-void dred_compute_latents(DREDEnc *enc, const float *pcm, int frame_size, int extra_delay, int arch)
-{
-    int curr_offset16k;
-    int frame_size16k = frame_size * 16000 / enc->Fs;
-    celt_assert(enc->loaded);
-    curr_offset16k = 40 + extra_delay*16000/enc->Fs - enc->input_buffer_fill;
-    enc->dred_offset = (int)floor((curr_offset16k+20.f)/40.f);
-    enc->latent_offset = 0;
-    while (frame_size16k > 0) {
-        int process_size16k;
-        int process_size;
-        process_size16k = IMIN(2*DRED_FRAME_SIZE, frame_size16k);
-        process_size = process_size16k * enc->Fs / 16000;
-        dred_convert_to_16k(enc, pcm, process_size, &enc->input_buffer[enc->input_buffer_fill], process_size16k);
-        enc->input_buffer_fill += process_size16k;
-        if (enc->input_buffer_fill >= 2*DRED_FRAME_SIZE)
-        {
-            curr_offset16k += 320;
-            dred_process_frame(enc, arch);
-            enc->input_buffer_fill -= 2*DRED_FRAME_SIZE;
-            OPUS_MOVE(&enc->input_buffer[0], &enc->input_buffer[2*DRED_FRAME_SIZE], enc->input_buffer_fill);
-            /* 15 ms (6*2.5 ms) is the ideal offset for DRED because it corresponds to our vocoder look-ahead. */
-            if (enc->dred_offset < 6) {
-                enc->dred_offset += 8;
-            } else {
-                enc->latent_offset++;
-            }
-        }
-
-        pcm += process_size;
-        frame_size16k -= process_size16k;
-    }
-}
-
-static void dred_encode_latents(ec_enc *enc, const float *x, const opus_uint8 *scale, const opus_uint8 *dzone, const opus_uint8 *r, const opus_uint8 *p0, int dim, int arch) {
-    int i;
-    int q[IMAX(DRED_LATENT_DIM,DRED_STATE_DIM)];
-    float xq[IMAX(DRED_LATENT_DIM,DRED_STATE_DIM)];
-    float delta[IMAX(DRED_LATENT_DIM,DRED_STATE_DIM)];
-    float deadzone[IMAX(DRED_LATENT_DIM,DRED_STATE_DIM)];
-    float eps = .1f;
-    /* This is split into multiple loops (with temporary arrays) so that the compiler
-       can vectorize all of it, and so we can call the vector tanh(). */
-    for (i=0;i<dim;i++) {
-        delta[i] = dzone[i]*(1.f/256.f);
-        xq[i] = x[i]*scale[i]*(1.f/256.f);
-        deadzone[i] = xq[i]/(delta[i]+eps);
-    }
-    compute_activation(deadzone, deadzone, dim, ACTIVATION_TANH, arch);
-    for (i=0;i<dim;i++) {
-        xq[i] = xq[i] - delta[i]*deadzone[i];
-        q[i] = (int)floor(.5f+xq[i]);
-    }
-    for (i=0;i<dim;i++) {
-        /* Make the impossible actually impossible. */
-        if (r[i] == 0 || p0[i] == 255) q[i] = 0;
-        else ec_laplace_encode_p0(enc, q[i], p0[i]<<7, r[i]<<7);
-    }
-}
-
-static int dred_voice_active(const unsigned char *activity_mem, int offset) {
-    int i;
-    for (i=0;i<16;i++) {
-        if (activity_mem[8*offset + i] == 1) return 1;
-    }
-    return 0;
-}
-
-int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes, int q0, int dQ, int qmax, unsigned char *activity_mem, int arch) {
-    ec_enc ec_encoder;
-
-    int q_level;
-    int i;
-    int offset;
-    int ec_buffer_fill;
-    int state_qoffset;
-    ec_enc ec_bak;
-    int prev_active=0;
-    int latent_offset;
-    int extra_dred_offset=0;
-    int dred_encoded=0;
-    int delayed_dred=0;
-    int total_offset;
-
-    latent_offset = enc->latent_offset;
-    /* Delaying new DRED data when just out of silence because we already have the
-       main Opus payload for that frame. */
-    if (activity_mem[0] && enc->last_extra_dred_offset>0) {
-        latent_offset = enc->last_extra_dred_offset;
-        delayed_dred = 1;
-        enc->last_extra_dred_offset = 0;
-    }
-    while (latent_offset < enc->latents_buffer_fill && !dred_voice_active(activity_mem, latent_offset)) {
-       latent_offset++;
-       extra_dred_offset++;
-    }
-    if (!delayed_dred) enc->last_extra_dred_offset = extra_dred_offset;
-
-    /* entropy coding of state and latents */
-    ec_enc_init(&ec_encoder, buf, max_bytes);
-    ec_enc_uint(&ec_encoder, q0, 16);
-    ec_enc_uint(&ec_encoder, dQ, 8);
-    total_offset = 16 - (enc->dred_offset - extra_dred_offset*8);
-    celt_assert(total_offset>=0);
-    if (total_offset > 31) {
-       ec_enc_uint(&ec_encoder, 1, 2);
-       ec_enc_uint(&ec_encoder, total_offset>>5, 256);
-       ec_enc_uint(&ec_encoder, total_offset&31, 32);
-    } else {
-       ec_enc_uint(&ec_encoder, 0, 2);
-       ec_enc_uint(&ec_encoder, total_offset, 32);
-    }
-    celt_assert(qmax >= q0);
-    if (q0 < 14 && dQ > 0) {
-      int nvals;
-      /* If you want to use qmax == q0, you should have set dQ = 0. */
-      celt_assert(qmax > q0);
-      nvals = 15 - (q0 + 1);
-      ec_encode(&ec_encoder, qmax >= 15 ? 0 : nvals + qmax - (q0 + 1),
-        qmax >= 15 ? nvals : nvals + qmax - q0, 2*nvals);
-    }
-    state_qoffset = q0*DRED_STATE_DIM;
-    dred_encode_latents(
-        &ec_encoder,
-        &enc->state_buffer[latent_offset*DRED_STATE_DIM],
-        dred_state_quant_scales_q8 + state_qoffset,
-        dred_state_dead_zone_q8 + state_qoffset,
-        dred_state_r_q8 + state_qoffset,
-        dred_state_p0_q8 + state_qoffset,
-        DRED_STATE_DIM,
-        arch);
-    if (ec_tell(&ec_encoder) > 8*max_bytes) {
-      return 0;
-    }
-    ec_bak = ec_encoder;
-    for (i = 0; i < IMIN(2*max_chunks, enc->latents_buffer_fill-latent_offset-1); i += 2)
-    {
-        int active;
-        q_level = compute_quantizer(q0, dQ, qmax, i/2);
-        offset = q_level * DRED_LATENT_DIM;
-
-        dred_encode_latents(
-            &ec_encoder,
-            enc->latents_buffer + (i+latent_offset) * DRED_LATENT_DIM,
-            dred_latent_quant_scales_q8 + offset,
-            dred_latent_dead_zone_q8 + offset,
-            dred_latent_r_q8 + offset,
-            dred_latent_p0_q8 + offset,
-            DRED_LATENT_DIM,
-            arch
-        );
-        if (ec_tell(&ec_encoder) > 8*max_bytes) {
-          /* If we haven't been able to code one chunk, give up on DRED completely. */
-          if (i==0) return 0;
-          break;
-        }
-        active = dred_voice_active(activity_mem, i+latent_offset);
-        if (active || prev_active) {
-           ec_bak = ec_encoder;
-           dred_encoded = i+2;
-        }
-        prev_active = active;
-    }
-    /* Avoid sending empty DRED packets. */
-    if (dred_encoded==0 || (dred_encoded<=2 && extra_dred_offset)) return 0;
-    ec_encoder = ec_bak;
-
-    ec_buffer_fill = (ec_tell(&ec_encoder)+7)/8;
-    ec_enc_shrink(&ec_encoder, ec_buffer_fill);
-    ec_enc_done(&ec_encoder);
-    return ec_buffer_fill;
-}
--- a/silk/dred_encoder.h
+++ /dev/null
@@ -1,71 +1,0 @@
-/* Copyright (c) 2022 Amazon
-   Written by Jan Buethe */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef DRED_ENCODER_H
-#define DRED_ENCODER_H
-
-#include "lpcnet.h"
-#include "dred_config.h"
-#include "dred_rdovae.h"
-#include "entcode.h"
-#include "lpcnet_private.h"
-#include "dred_rdovae_enc.h"
-#include "dred_rdovae_enc_data.h"
-
-#define RESAMPLING_ORDER 8
-
-typedef struct {
-    RDOVAEEnc model;
-    LPCNetEncState lpcnet_enc_state;
-    RDOVAEEncState rdovae_enc;
-    int loaded;
-    opus_int32 Fs;
-    int channels;
-
-#define DREDENC_RESET_START input_buffer
-    float input_buffer[2*DRED_DFRAME_SIZE];
-    int input_buffer_fill;
-    int dred_offset;
-    int latent_offset;
-    int last_extra_dred_offset;
-    float latents_buffer[DRED_MAX_FRAMES * DRED_LATENT_DIM];
-    int latents_buffer_fill;
-    float state_buffer[DRED_MAX_FRAMES * DRED_STATE_DIM];
-    float resample_mem[RESAMPLING_ORDER + 1];
-} DREDEnc;
-
-int dred_encoder_load_model(DREDEnc* enc, const unsigned char *data, int len);
-void dred_encoder_init(DREDEnc* enc, opus_int32 Fs, int channels);
-void dred_encoder_reset(DREDEnc* enc);
-
-void dred_deinit_encoder(DREDEnc *enc);
-
-void dred_compute_latents(DREDEnc *enc, const float *pcm, int frame_size, int extra_delay, int arch);
-
-int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes, int q0, int dQ, int qmax, unsigned char *activity_mem, int arch);
-
-#endif
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -47,7 +47,7 @@
 #include "tuning_parameters.h"
 
 #ifdef ENABLE_DRED
-#include "silk/dred_coding.h"
+#include "dred_coding.h"
 #endif
 
 #ifdef FIXED_POINT
--