summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@jmvalin.ca>2016-04-23 00:34:53 -0400
committerJean-Marc Valin <jmvalin@jmvalin.ca>2016-04-27 14:54:25 -0400
commit4ed368e68d4ba749fc0fe7cb0ef4568350aaa9aa (patch)
treeff1d92c074633f38ddd58bf70d9a5fe318f0fca2
parentf587785a0d465ab67382d589aa5bfe2de97d0a74 (diff)
downloadopus-4ed368e68d4ba749fc0fe7cb0ef4568350aaa9aa.tar.gz
Quality: Increase CELT rate for voiced frames in hybrid mode
-rw-r--r--celt/celt.h12
-rw-r--r--celt/celt_encoder.c11
-rw-r--r--silk/control.h5
-rw-r--r--silk/enc_API.c4
-rw-r--r--src/opus_encoder.c8
5 files changed, 39 insertions, 1 deletions
diff --git a/celt/celt.h b/celt/celt.h
index a423b950..1b8b86f9 100644
--- a/celt/celt.h
+++ b/celt/celt.h
@@ -58,12 +58,19 @@ typedef struct {
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_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
+
/* 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 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);
diff --git a/celt/celt_encoder.c b/celt/celt_encoder.c
index 614f421f..763adcfc 100644
--- a/celt/celt_encoder.c
+++ b/celt/celt_encoder.c
@@ -98,6 +98,7 @@ struct OpusCustomEncoder {
#endif
int consec_transient;
AnalysisInfo analysis;
+ SILKInfo silk_info;
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;
+ /* 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))
@@ -2383,6 +2387,13 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
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**);
diff --git a/silk/control.h b/silk/control.h
index 747e5426..dfbead9f 100644
--- a/silk/control.h
+++ b/silk/control.h
@@ -110,6 +110,11 @@ typedef struct {
/* 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;
/**************************************************************************/
diff --git a/silk/enc_API.c b/silk/enc_API.c
index f8060286..f6406d29 100644
--- a/silk/enc_API.c
+++ b/silk/enc_API.c
@@ -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;
}
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 566f9d2c..63ec9215 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -1903,6 +1903,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 (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)