diff --git a/celt/arch.h b/celt/arch.h
index f4c949e2ec5665b1a23cc5c077e561e3b187d809..e81e78c7f20c20d7af55bc60c5d4e80c93fd8cdc 100644
--- a/celt/arch.h
+++ b/celt/arch.h
@@ -166,6 +166,7 @@ typedef opus_val16 opus_res;
 #define RES2VAL16(a)    RES2INT16(a)
 #define FLOAT2SIG(a)    float2int(((opus_int32)32768<<SIG_SHIFT)*(a))
 #define INT16TOSIG(a)   SHL32(EXTEND32(a), SIG_SHIFT)
+#define INT24TOSIG(a)   SHL32(a, SIG_SHIFT-8)
 
 #define celt_isnan(x) 0
 
@@ -332,6 +333,7 @@ static OPUS_INLINE int celt_isnan(float x)
 #define RES2VAL16(a)    (a)
 #define FLOAT2SIG(a)    ((a)*CELT_SIG_SCALE)
 #define INT16TOSIG(a)   ((float)(a))
+#define INT24TOSIG(a)   ((float)(a)*(1.f/256.f))
 
 
 #endif /* !FIXED_POINT */
diff --git a/include/opus.h b/include/opus.h
index eadeda75a098b37f13dea8d38b589e2d70117ebc..edf455289191bba62b80f2a8f4ebc602f3eb230b 100644
--- a/include/opus.h
+++ b/include/opus.h
@@ -268,6 +268,42 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
     opus_int32 max_data_bytes
 ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
 
+/** Encodes an Opus frame.
+  * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
+  * @param [in] pcm <tt>opus_int32*</tt>: Input signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length is frame_size*channels*sizeof(opus_int32)
+  * @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
+  *                                      input signal.
+  *                                      This must be an Opus frame size for
+  *                                      the encoder's sampling rate.
+  *                                      For example, at 48 kHz the permitted
+  *                                      values are 120, 240, 480, 960, 1920,
+  *                                      and 2880.
+  *                                      Passing in a duration of less than
+  *                                      10 ms (480 samples at 48 kHz) will
+  *                                      prevent the encoder from using the LPC
+  *                                      or hybrid modes.
+  * @param [out] data <tt>unsigned char*</tt>: Output payload.
+  *                                            This must contain storage for at
+  *                                            least \a max_data_bytes.
+  * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+  *                                                 memory for the output
+  *                                                 payload. This may be
+  *                                                 used to impose an upper limit on
+  *                                                 the instant bitrate, but should
+  *                                                 not be used as the only bitrate
+  *                                                 control. Use #OPUS_SET_BITRATE to
+  *                                                 control the bitrate.
+  * @returns The length of the encoded packet (in bytes) on success or a
+  *          negative error code (see @ref opus_errorcodes) on failure.
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode24(
+    OpusEncoder *st,
+    const opus_int32 *pcm,
+    int frame_size,
+    unsigned char *data,
+    opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
 /** Encodes an Opus frame from floating point input.
   * @param [in] st <tt>OpusEncoder*</tt>: Encoder state
   * @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
@@ -483,6 +519,31 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
     int decode_fec
 ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
 
+/** Decode an Opus packet.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
+  * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
+  * @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length
+  *  is frame_size*channels*sizeof(opus_int32)
+  * @param [in] frame_size Number of samples per channel of available space in \a pcm.
+  *  If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
+  *  not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
+  *  then frame_size needs to be exactly the duration of audio that is missing, otherwise the
+  *  decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
+  *  FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
+  * @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
+  *  decoded. If no such data is available, the frame is decoded as if it were lost.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode24(
+    OpusDecoder *st,
+    const unsigned char *data,
+    opus_int32 len,
+    opus_int32 *pcm,
+    int frame_size,
+    int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
 /** Decode an Opus packet with floating point output.
   * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
   * @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
@@ -596,7 +657,7 @@ OPUS_EXPORT int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const
   */
 OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst);
 
-/** Decode audio from an Opus DRED packet with floating point output.
+/** Decode audio from an Opus DRED packet with 16-bit output.
   * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
   * @param [in] dred <tt>OpusDRED*</tt>: DRED state
   * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
@@ -608,6 +669,18 @@ OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src
   */
 OPUS_EXPORT int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int16 *pcm, opus_int32 frame_size);
 
+/** Decode audio from an Opus DRED packet with 24-bit output.
+  * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
+  * @param [in] dred <tt>OpusDRED*</tt>: DRED state
+  * @param [in] dred_offset <tt>opus_int32</tt>: position of the redundancy to decode (in samples before the beginning of the real audio data in the packet).
+  * @param [out] pcm <tt>opus_int32*</tt>: Output signal (interleaved if 2 channels). length
+  *  is frame_size*channels*sizeof(opus_int16)
+  * @param [in] frame_size Number of samples per channel to decode in \a pcm.
+  *  frame_size <b>must</b> be a multiple of 2.5 ms.
+  * @returns Number of decoded samples or @ref opus_errorcodes
+  */
+OPUS_EXPORT int opus_decoder_dred_decode24(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int32 *pcm, opus_int32 frame_size);
+
 /** Decode audio from an Opus DRED packet with floating point output.
   * @param [in] st <tt>OpusDecoder*</tt>: Decoder state
   * @param [in] dred <tt>OpusDRED*</tt>: DRED state
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index 83d92ddc490d8cfd9c6bb4d1c7830cc097bcfc0a..a37e2a6c5c8869802b67242a9378824c71bd59cc 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -819,7 +819,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
 #ifdef FIXED_POINT
 #ifdef ENABLE_RES24
 int opus_decode(OpusDecoder *st, const unsigned char *data,
-      opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
+      opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
 {
 	   VARDECL(opus_res, out);
 	   int ret, i;
@@ -851,14 +851,59 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
 	   RESTORE_STACK;
 	   return ret;
 }
+
+int opus_decode24(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
+{
+   if(frame_size<=0)
+      return OPUS_BAD_ARG;
+   return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+}
+
 #else
+
 int opus_decode(OpusDecoder *st, const unsigned char *data,
-      opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
+      opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
 {
    if(frame_size<=0)
       return OPUS_BAD_ARG;
    return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
 }
+
+int opus_decode24(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
+{
+       VARDECL(opus_res, out);
+       int ret, i;
+       int nb_samples;
+       ALLOC_STACK;
+
+       if(frame_size<=0)
+       {
+          RESTORE_STACK;
+          return OPUS_BAD_ARG;
+       }
+       if (data != NULL && len > 0 && !decode_fec)
+       {
+          nb_samples = opus_decoder_get_nb_samples(st, data, len);
+          if (nb_samples>0)
+             frame_size = IMIN(frame_size, nb_samples);
+          else
+             return OPUS_INVALID_PACKET;
+       }
+       celt_assert(st->channels == 1 || st->channels == 2);
+       ALLOC(out, frame_size*st->channels, opus_res);
+
+       ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0, NULL, 0);
+       if (ret > 0)
+       {
+          for (i=0;i<ret*st->channels;i++)
+             pcm[i] = RES2INT24(out[i]);
+       }
+       RESTORE_STACK;
+       return ret;
+}
+
 #endif
 
 #ifndef DISABLE_FLOAT_API
@@ -934,6 +979,41 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
    return ret;
 }
 
+int opus_decode24(OpusDecoder *st, const unsigned char *data,
+      opus_int32 len, opus_int32 *pcm, int frame_size, int decode_fec)
+{
+   VARDECL(float, out);
+   int ret, i;
+   int nb_samples;
+   ALLOC_STACK;
+
+   if(frame_size<=0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+
+   if (data != NULL && len > 0 && !decode_fec)
+   {
+      nb_samples = opus_decoder_get_nb_samples(st, data, len);
+      if (nb_samples>0)
+         frame_size = IMIN(frame_size, nb_samples);
+      else
+         return OPUS_INVALID_PACKET;
+   }
+   celt_assert(st->channels == 1 || st->channels == 2);
+   ALLOC(out, frame_size*st->channels, float);
+
+   ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1, NULL, 0);
+   if (ret > 0)
+   {
+      for (i=0;i<ret*st->channels;i++)
+         pcm[i] = RES2INT24(out[i]);
+   }
+   RESTORE_STACK;
+   return ret;
+}
+
 int opus_decode_float(OpusDecoder *st, const unsigned char *data,
       opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
 {
@@ -1498,7 +1578,41 @@ int opus_decoder_dred_decode(OpusDecoder *st, const OpusDRED *dred, opus_int32 d
    if (ret > 0)
    {
       for (i=0;i<ret*st->channels;i++)
-         pcm[i] = FLOAT2INT16(out[i]);
+         pcm[i] = RES2INT16(out[i]);
+   }
+   RESTORE_STACK;
+   return ret;
+#else
+   (void)st;
+   (void)dred;
+   (void)dred_offset;
+   (void)pcm;
+   (void)frame_size;
+   return OPUS_UNIMPLEMENTED;
+#endif
+}
+
+int opus_decoder_dred_decode24(OpusDecoder *st, const OpusDRED *dred, opus_int32 dred_offset, opus_int32 *pcm, opus_int32 frame_size)
+{
+#ifdef ENABLE_DRED
+   VARDECL(float, out);
+   int ret, i;
+   ALLOC_STACK;
+
+   if(frame_size<=0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+
+   celt_assert(st->channels == 1 || st->channels == 2);
+   ALLOC(out, frame_size*st->channels, float);
+
+   ret = opus_decode_native(st, NULL, 0, out, frame_size, 0, 0, NULL, 1, dred, dred_offset);
+   if (ret > 0)
+   {
+      for (i=0;i<ret*st->channels;i++)
+         pcm[i] = RES2INT24(out[i]);
    }
    RESTORE_STACK;
    return ret;
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 26b1994ca615c040025463708af1a5d7e410cefe..cba7edcb13e111ab86275f99da45f4d5b7cf6de9 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -739,6 +739,29 @@ void downmix_int(const void *_x, opus_val32 *y, int subframe, int offset, int c1
    }
 }
 
+void downmix_int24(const void *_x, opus_val32 *y, int subframe, int offset, int c1, int c2, int C)
+{
+   const opus_int32 *x;
+   int j;
+
+   x = (const opus_int32 *)_x;
+   for (j=0;j<subframe;j++)
+      y[j] = INT24TOSIG(x[(j+offset)*C+c1]);
+   if (c2>-1)
+   {
+      for (j=0;j<subframe;j++)
+         y[j] += INT24TOSIG(x[(j+offset)*C+c2]);
+   } else if (c2==-2)
+   {
+      int c;
+      for (c=1;c<C;c++)
+      {
+         for (j=0;j<subframe;j++)
+            y[j] += INT24TOSIG(x[(j+offset)*C+c]);
+      }
+   }
+}
+
 opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs)
 {
    int new_size;
@@ -2534,6 +2557,16 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_fram
    RESTORE_STACK;
    return ret;
 }
+
+opus_int32 opus_encode24(OpusEncoder *st, const opus_int32 *pcm, int analysis_frame_size,
+                unsigned char *data, opus_int32 max_data_bytes)
+{
+   int frame_size;
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
+   return opus_encode_native(st, pcm, frame_size, data, max_data_bytes, 16,
+                             pcm, analysis_frame_size, 0, -2, st->channels, downmix_int24, 0);
+}
+
 #else
 opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
                 unsigned char *data, opus_int32 max_data_bytes)
@@ -2543,6 +2576,30 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_fram
    return opus_encode_native(st, pcm, frame_size, data, max_data_bytes, 16,
                              pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
 }
+
+opus_int32 opus_encode24(OpusEncoder *st, const opus_int32 *pcm, int analysis_frame_size,
+                unsigned char *data, opus_int32 max_data_bytes)
+{
+   int i, ret;
+   int frame_size;
+   VARDECL(opus_res, in);
+   ALLOC_STACK;
+
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
+   if (frame_size <= 0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+   ALLOC(in, frame_size*st->channels, opus_res);
+
+   for (i=0;i<frame_size*st->channels;i++)
+      in[i] = INT24TORES(pcm[i]);
+   ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
+                            pcm, analysis_frame_size, 0, -2, st->channels, downmix_int24, 1);
+   RESTORE_STACK;
+   return ret;
+}
 #endif /* ENABLE_RES24 */
 
 #else
@@ -2563,12 +2620,37 @@ opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_fram
    ALLOC(in, frame_size*st->channels, float);
 
    for (i=0;i<frame_size*st->channels;i++)
-      in[i] = (1.0f/32768)*pcm[i];
+      in[i] = INT16TORES(pcm[i]);
    ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
                             pcm, analysis_frame_size, 0, -2, st->channels, downmix_int, 0);
    RESTORE_STACK;
    return ret;
 }
+
+opus_int32 opus_encode24(OpusEncoder *st, const opus_int32 *pcm, int analysis_frame_size,
+      unsigned char *data, opus_int32 max_data_bytes)
+{
+   int i, ret;
+   int frame_size;
+   VARDECL(float, in);
+   ALLOC_STACK;
+
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, st->Fs);
+   if (frame_size <= 0)
+   {
+      RESTORE_STACK;
+      return OPUS_BAD_ARG;
+   }
+   ALLOC(in, frame_size*st->channels, float);
+
+   for (i=0;i<frame_size*st->channels;i++)
+      in[i] = INT24TORES(pcm[i]);
+   ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16,
+                            pcm, analysis_frame_size, 0, -2, st->channels, downmix_int24, 0);
+   RESTORE_STACK;
+   return ret;
+}
+
 opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
                       unsigned char *data, opus_int32 out_data_bytes)
 {
diff --git a/src/opus_private.h b/src/opus_private.h
index 4d968848018048e00c549c9d092c1a22a450f64c..19deb6ee210cbec4bb8e29022c34fd30da345e0f 100644
--- a/src/opus_private.h
+++ b/src/opus_private.h
@@ -174,6 +174,7 @@ typedef void (*opus_copy_channel_out_func)(
 typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
 void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
 void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
+void downmix_int24(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
 int is_digital_silence(const opus_res* pcm, int frame_size, int channels, int lsb_depth);
 
 int encode_size(int size, unsigned char *data);
diff --git a/tests/test_opus_custom.c b/tests/test_opus_custom.c
index b2d879c94548320e3af8a48f11e336e62ea78ee1..175bfa3338aaba04eaa3936774305fa42a2678f4 100644
--- a/tests/test_opus_custom.c
+++ b/tests/test_opus_custom.c
@@ -233,16 +233,31 @@ int test_encode(TestCustomParams params) {
             }
          }
          else {
-            opus_int16* input = (opus_int16*)inbuf;
-            len = opus_encode(enc,
-                              &input[samp_count*num_channels],
-                              frame_size,
-                              packet,
-                              MAX_PACKET);
-            if (len <= 0) {
-                fprintf(stderr, "opus_encode() failed: %s\n", opus_strerror(len));
-                ret = -1;
-                break;
+            if (params.encoder_bit_depth == 24) {
+               opus_int32* input = (opus_int32*)inbuf;
+               len = opus_encode24(enc,
+                                   &input[samp_count*num_channels],
+                                   frame_size,
+                                   packet,
+                                   MAX_PACKET);
+               if (len <= 0) {
+                  fprintf(stderr, "opus_encode24() failed: %s\n", opus_strerror(len));
+                  ret = -1;
+                  break;
+               }
+            }
+            else {
+               opus_int16* input = (opus_int16*)inbuf;
+               len = opus_encode(enc,
+                                 &input[samp_count*num_channels],
+                                 frame_size,
+                                 packet,
+                                 MAX_PACKET);
+               if (len <= 0) {
+                   fprintf(stderr, "opus_encode() failed: %s\n", opus_strerror(len));
+                   ret = -1;
+                   break;
+               }
             }
          }
       }
@@ -356,17 +371,34 @@ int test_encode(TestCustomParams params) {
             }
          }
          else {
-            opus_int16* output = (opus_int16*)outbuf;
-            samples_decoded = opus_decode(dec,
-                                          packet,
-                                          len,
-                                          &output[samp_count*num_channels],
-                                          frame_size,
-                                          0);
-            if (samples_decoded != frame_size) {
-                fprintf(stderr, "opus_decode() returned %d\n", samples_decoded);
-                ret = -1;
-                break;
+            if (params.decoder_bit_depth == 24) {
+               opus_int32* output = (opus_int32*)outbuf;
+               samples_decoded = opus_decode24(dec,
+                                               packet,
+                                               len,
+                                               &output[samp_count*num_channels],
+                                               frame_size,
+                                               0);
+
+               if (samples_decoded != frame_size) {
+                  fprintf(stderr, "opus_decode24() returned %d\n", samples_decoded);
+                  ret = -1;
+                  break;
+               }
+            }
+            else {
+               opus_int16* output = (opus_int16*)outbuf;
+               samples_decoded = opus_decode(dec,
+                                             packet,
+                                             len,
+                                             &output[samp_count*num_channels],
+                                             frame_size,
+                                             0);
+               if (samples_decoded != frame_size) {
+                   fprintf(stderr, "opus_decode() returned %d\n", samples_decoded);
+                   ret = -1;
+                   break;
+               }
             }
          }
       }
@@ -375,8 +407,13 @@ int test_encode(TestCustomParams params) {
    } while (samp_count + frame_size <= input_samples);
 
 #ifdef RESYNTH
-   /* Resynth only works with OpusCustom encoder */
-   if (params.custom_encode && params.custom_decode) {
+   /* Resynth only works with OpusCustom encoder. Also, we don't enable it if there's
+      a 16-bit bottleneck in the decoder that can cause clipping. */
+   if (params.custom_encode && (params.custom_decode
+#if !defined(FIXED_POINT) || defined(ENABLE_RES24)
+         || params.decoder_bit_depth > 16
+#endif
+         )) {
       if (params.float_encode) {
          float* input = (float*)inbuf;
          float* output = (float*)outbuf;
@@ -552,18 +589,8 @@ void test_opus_custom(const int num_encoders, const int num_setting_changes) {
          params.float_encode = 0;
          params.float_decode = 0;
 #endif
-         if (params.custom_encode) {
-            params.encoder_bit_depth = RAND_SAMPLE(encoder_bit_depths);
-         }
-         else {
-            params.encoder_bit_depth = 16;
-         }
-         if (params.custom_decode) {
-            params.decoder_bit_depth = RAND_SAMPLE(decoder_bit_depths);
-         }
-         else {
-            params.decoder_bit_depth = 16;
-         }
+         params.encoder_bit_depth = RAND_SAMPLE(encoder_bit_depths);
+         params.decoder_bit_depth = RAND_SAMPLE(decoder_bit_depths);
 #ifdef RESYNTH
          /* Resynth logic works best when encoder/decoder use same datatype */
          params.float_decode = params.float_encode;