Quality: Increase CELT rate for voiced frames in hybrid mode
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Sat, 23 Apr 2016 04:34:53 +0000 (00:34 -0400)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Sun, 17 Jul 2016 19:05:54 +0000 (15:05 -0400)
celt/celt.h
celt/celt_encoder.c
silk/control.h
silk/enc_API.c
src/opus_encoder.c

index d1f7eb6..1df9092 100644 (file)
@@ -58,12 +58,19 @@ typedef struct {
    float activity;
    float music_prob;
    int        bandwidth;
    float activity;
    float music_prob;
    int        bandwidth;
-}AnalysisInfo;
+} AnalysisInfo;
+
+typedef struct {
+   int signalType;
+   int offset;
+} SILKInfo;
 
 #define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
 
 #define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
 
 
 #define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
 
 #define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
 
+#define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
+
 /* Encoder/decoder Requests */
 
 /* Expose this option again when variable framesize actually works */
 /* Encoder/decoder Requests */
 
 /* Expose this option again when variable framesize actually works */
@@ -116,6 +123,9 @@ typedef struct {
 #define OPUS_SET_ENERGY_MASK_REQUEST    10026
 #define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x)
 
 #define OPUS_SET_ENERGY_MASK_REQUEST    10026
 #define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x)
 
+#define CELT_SET_SILK_INFO_REQUEST    10028
+#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, __celt_check_silkinfo_ptr(x)
+
 /* Encoder stuff */
 
 int celt_encoder_get_size(int channels);
 /* Encoder stuff */
 
 int celt_encoder_get_size(int channels);
index 030887c..544b7bc 100644 (file)
@@ -98,6 +98,7 @@ struct OpusCustomEncoder {
 #endif
    int consec_transient;
    AnalysisInfo analysis;
 #endif
    int consec_transient;
    AnalysisInfo analysis;
+   SILKInfo silk_info;
 
    opus_val32 preemph_memE[2];
    opus_val32 preemph_memD[2];
 
    opus_val32 preemph_memE[2];
    opus_val32 preemph_memD[2];
@@ -1935,6 +1936,9 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
            temporal_vbr);
      } else {
         target = base_target;
            temporal_vbr);
      } else {
         target = base_target;
+        /* Tonal frames (offset<100) need more bits than noisy (offset>100) ones. */
+        if (st->silk_info.offset < 100) target += 12 << BITRES >> (3-LM);
+        if (st->silk_info.offset > 100) target -= 18 << BITRES >> (3-LM);
         /* If we have a strong transient, let's make sure it has enough bits to code
            the first two bands, so that it can use folding rather than noise. */
         if (tf_estimate > QCONST16(.7f,14))
         /* If we have a strong transient, let's make sure it has enough bits to code
            the first two bands, so that it can use folding rather than noise. */
         if (tf_estimate > QCONST16(.7f,14))
@@ -2383,6 +2387,13 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
             OPUS_COPY(&st->analysis, info, 1);
       }
       break;
             OPUS_COPY(&st->analysis, info, 1);
       }
       break;
+      case CELT_SET_SILK_INFO_REQUEST:
+      {
+         SILKInfo *info = va_arg(ap, SILKInfo *);
+         if (info)
+            OPUS_COPY(&st->silk_info, info, 1);
+      }
+      break;
       case CELT_GET_MODE_REQUEST:
       {
          const CELTMode ** value = va_arg(ap, const CELTMode**);
       case CELT_GET_MODE_REQUEST:
       {
          const CELTMode ** value = va_arg(ap, const CELTMode**);
index 747e542..dfbead9 100644 (file)
@@ -110,6 +110,11 @@ typedef struct {
     /* O:   Tells the Opus encoder we're ready to switch                                    */
     opus_int switchReady;
 
     /* O:   Tells the Opus encoder we're ready to switch                                    */
     opus_int switchReady;
 
+    /* O: SILK Signal type */
+    opus_int signalType;
+
+    /* O: SILK offset (dithering) */
+    opus_int offset;
 } silk_EncControlStruct;
 
 /**************************************************************************/
 } silk_EncControlStruct;
 
 /**************************************************************************/
index f806028..f6406d2 100644 (file)
@@ -557,6 +557,10 @@ opus_int silk_Encode(                                   /* O    Returns error co
         }
     }
 
         }
     }
 
+    encControl->signalType = psEnc->state_Fxx[0].sCmn.indices.signalType;
+    encControl->offset = silk_Quantization_Offsets_Q10
+                         [ psEnc->state_Fxx[0].sCmn.indices.signalType >> 1 ]
+                         [ psEnc->state_Fxx[0].sCmn.indices.quantOffsetType ];
     RESTORE_STACK;
     return ret;
 }
     RESTORE_STACK;
     return ret;
 }
index dbd6f7c..4a1bd47 100644 (file)
@@ -1912,6 +1912,14 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
     if (redundancy || st->mode != MODE_SILK_ONLY)
        celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info));
 #endif
     if (redundancy || st->mode != MODE_SILK_ONLY)
        celt_encoder_ctl(celt_enc, CELT_SET_ANALYSIS(&analysis_info));
 #endif
+    if (st->mode == MODE_HYBRID) {
+       SILKInfo info;
+       info.signalType = st->silk_mode.signalType;
+       info.offset = st->silk_mode.offset;
+       celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO(&info));
+    } else {
+       celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO((SILKInfo*)NULL));
+    }
 
     /* 5 ms redundant frame for CELT->SILK */
     if (redundancy && celt_to_silk)
 
     /* 5 ms redundant frame for CELT->SILK */
     if (redundancy && celt_to_silk)