From 1cd5d95b3fe6ba959037e427324bea22563f67a3 Mon Sep 17 00:00:00 2001
From: Jean-Marc Valin <jmvalin@jmvalin.ca>
Date: Wed, 11 Jul 2012 02:54:47 -0400
Subject: [PATCH] Implements OPUS_{GET,SET}_LSB_DEPTH

This implements an API used in future encoders to avoid dynalloc doing silly things
on periodic LSB patterns and to reduce the bitrate on near-silence.
---
 celt/celt.c            | 16 ++++++++++++++++
 include/opus_defines.h | 13 +++++++++++++
 src/opus_demo.c        |  1 +
 src/opus_encoder.c     | 12 ++++++++++++
 4 files changed, 42 insertions(+)

diff --git a/celt/celt.c b/celt/celt.c
index 4f16887d3..8164269e9 100644
--- a/celt/celt.c
+++ b/celt/celt.c
@@ -156,6 +156,7 @@ struct OpusCustomEncoder {
    int signalling;
    int constrained_vbr;      /* If zero, VBR can do whatever it likes with the rate */
    int loss_rate;
+   int lsb_depth;
 
    /* Everything beyond this point gets cleared on a reset */
 #define ENCODER_RESET_START rng
@@ -266,6 +267,7 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_init(CELTEncoder *st, const CELTMod
    st->vbr = 0;
    st->force_intra  = 0;
    st->complexity = 5;
+   st->lsb_depth=24;
 
    opus_custom_encoder_ctl(st, OPUS_RESET_STATE);
 
@@ -1823,6 +1825,20 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
          st->stream_channels = value;
       }
       break;
+      case OPUS_SET_LSB_DEPTH_REQUEST:
+      {
+          opus_int32 value = va_arg(ap, opus_int32);
+          if (value<8 || value>24)
+             goto bad_arg;
+          st->lsb_depth=value;
+      }
+      break;
+      case OPUS_GET_LSB_DEPTH_REQUEST:
+      {
+          opus_int32 *value = va_arg(ap, opus_int32*);
+          *value=st->lsb_depth;
+      }
+      break;
       case OPUS_RESET_STATE:
       {
          int i;
diff --git a/include/opus_defines.h b/include/opus_defines.h
index b2a559d4a..14d5e5ebb 100644
--- a/include/opus_defines.h
+++ b/include/opus_defines.h
@@ -142,6 +142,8 @@ extern "C" {
 #define OPUS_GET_PITCH_REQUEST               4033
 #define OPUS_SET_GAIN_REQUEST                4034
 #define OPUS_GET_GAIN_REQUEST                4045
+#define OPUS_SET_LSB_DEPTH_REQUEST           4036
+#define OPUS_GET_LSB_DEPTH_REQUEST           4037
 
 /* Macros to trigger compilation errors when the wrong types are provided to a CTL */
 #define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
@@ -464,6 +466,17 @@ extern "C" {
   * @hideinitializer */
 #define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
 
+/** Configures the depth of signal being encoded.
+  * This is a hint which helps the encoder identify silence and near-silence.
+  * The supported values are between 8 and 24 (default)
+  * @param[in] x <tt>opus_int32</tt>:   Input precision
+  * @hideinitializer */
+#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured signal depth. @see OPUS_SET_LSB_DEPTH
+  *
+  * @param[out] x <tt>opus_int32*</tt>: Input precision
+  * @hideinitializer */
+#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
 /**@}*/
 
 /** @defgroup opus_decoderctls Decoder related CTLs
diff --git a/src/opus_demo.c b/src/opus_demo.c
index 2a1d371b2..20bebba33 100644
--- a/src/opus_demo.c
+++ b/src/opus_demo.c
@@ -498,6 +498,7 @@ int main(int argc, char *argv[])
        opus_encoder_ctl(enc, OPUS_SET_PACKET_LOSS_PERC(packet_loss_perc));
 
        opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
+       opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));
     }
     if (!encode_only)
     {
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index c0abb66b1..1fcbf0f55 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -1537,6 +1537,18 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
             *value = st->rangeFinal;
         }
         break;
+        case OPUS_SET_LSB_DEPTH_REQUEST:
+        {
+            opus_int32 value = va_arg(ap, opus_int32);
+            ret = celt_encoder_ctl(celt_enc, OPUS_SET_LSB_DEPTH(value));
+        }
+        break;
+        case OPUS_GET_LSB_DEPTH_REQUEST:
+        {
+            opus_int32 *value = va_arg(ap, opus_int32*);
+            celt_encoder_ctl(celt_enc, OPUS_GET_LSB_DEPTH(value));
+        }
+        break;
         case OPUS_RESET_STATE:
         {
            void *silk_enc;
-- 
GitLab