Adds OPUS_SET_PREDICTION_DISABLED() ctl to force "independent" frames
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Fri, 15 Nov 2013 18:50:38 +0000 (13:50 -0500)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Fri, 15 Nov 2013 18:50:38 +0000 (13:50 -0500)
Works by turning off pitch and energy prediction in CELT, while
setting first_frame_after_reset in SILK to disable pitch and LSF interpolation
and reduce LPC gain.

include/opus_defines.h
silk/control.h
silk/enc_API.c
src/opus_encoder.c
src/opus_multistream_encoder.c

index c39a60e..265089f 100644 (file)
@@ -163,6 +163,8 @@ extern "C" {
 #define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
 #define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
 #define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
+#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
+#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
 
 /* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
 
@@ -586,6 +588,14 @@ extern "C" {
   * @hideinitializer */
 #define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
 
+/** If set to 1, disables almost all use of prediction, making frames almost
+    completely independent. This reduces quality. (default : 0)
+  * @hideinitializer */
+#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured prediction status.
+  * @hideinitializer */
+#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
+
 /**@}*/
 
 /** @defgroup opus_genericctls Generic CTLs
index 896cbe8..747e542 100644 (file)
@@ -92,6 +92,9 @@ typedef struct {
     /* I:   Opus encoder is allowing us to switch bandwidth                                 */
     opus_int opusCanSwitch;
 
+    /* I: Make frames as independent as possible (but still use LPC)                        */
+    opus_int reducedDependency;
+
     /* O:   Internal sampling rate used, in Hertz; 8000/12000/16000                         */
     opus_int32 internalSampleRate;
 
index 44b9ab3..b342487 100644 (file)
@@ -156,6 +156,11 @@ opus_int silk_Encode(                                   /* O    Returns error co
     opus_int transition, curr_block, tot_blocks;
     SAVE_STACK;
 
+    if (encControl->reducedDependency)
+    {
+       psEnc->state_Fxx[0].sCmn.first_frame_after_reset = 1;
+       psEnc->state_Fxx[1].sCmn.first_frame_after_reset = 1;
+    }
     psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded = psEnc->state_Fxx[ 1 ].sCmn.nFramesEncoded = 0;
 
     /* Check values in encoder control structure */
index d2066f0..a365e56 100644 (file)
@@ -205,6 +205,7 @@ int opus_encoder_init(OpusEncoder* st, opus_int32 Fs, int channels, int applicat
     st->silk_mode.useInBandFEC              = 0;
     st->silk_mode.useDTX                    = 0;
     st->silk_mode.useCBR                    = 0;
+    st->silk_mode.reducedDependency         = 0;
 
     /* Create CELT encoder */
     /* Initialize CELT encoder */
@@ -1671,9 +1672,12 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
     celt_encoder_ctl(celt_enc, OPUS_SET_BITRATE(OPUS_BITRATE_MAX));
     if (st->mode != MODE_SILK_ONLY)
     {
+        opus_val32 celt_pred=2;
         celt_encoder_ctl(celt_enc, OPUS_SET_VBR(0));
-        /* Allow prediction unless we decide to disable it later */
-        celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(2));
+        /* We may still decide to disable prediction later */
+        if (st->silk_mode.reducedDependency)
+           celt_pred = 0;
+        celt_encoder_ctl(celt_enc, CELT_SET_PREDICTION(celt_pred));
 
         if (st->mode == MODE_HYBRID)
         {
@@ -2387,6 +2391,22 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
             *value = st->variable_duration;
         }
         break;
+        case OPUS_SET_PREDICTION_DISABLED_REQUEST:
+        {
+           opus_int32 value = va_arg(ap, opus_int32);
+           if (value > 1 || value < 0)
+              goto bad_arg;
+           st->silk_mode.reducedDependency = value;
+        }
+        break;
+        case OPUS_GET_PREDICTION_DISABLED_REQUEST:
+        {
+           opus_int32 *value = va_arg(ap, opus_int32*);
+           if (!value)
+              goto bad_arg;
+           *value = st->silk_mode.reducedDependency;
+        }
+        break;
         case OPUS_RESET_STATE:
         {
            void *silk_enc;
index 7cb1af7..cec6266 100644 (file)
@@ -1028,6 +1028,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_GET_SAMPLE_RATE_REQUEST:
    case OPUS_GET_INBAND_FEC_REQUEST:
    case OPUS_GET_FORCE_CHANNELS_REQUEST:
+   case OPUS_GET_PREDICTION_DISABLED_REQUEST:
    {
       OpusEncoder *enc;
       /* For int32* GET params, just query the first stream */
@@ -1073,6 +1074,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_SET_DTX_REQUEST:
    case OPUS_SET_FORCE_MODE_REQUEST:
    case OPUS_SET_FORCE_CHANNELS_REQUEST:
+   case OPUS_SET_PREDICTION_DISABLED_REQUEST:
    {
       int s;
       /* This works for int32 params */