From 4ed368e68d4ba749fc0fe7cb0ef4568350aaa9aa Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Sat, 23 Apr 2016 00:34:53 -0400 Subject: Quality: Increase CELT rate for voiced frames in hybrid mode --- celt/celt.h | 12 +++++++++++- celt/celt_encoder.c | 11 +++++++++++ silk/control.h | 5 +++++ silk/enc_API.c | 4 ++++ src/opus_encoder.c | 8 ++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) 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) -- cgit v1.2.1