diff --git a/celt/celt.h b/celt/celt.h index d1f7eb690db3f641047b31bac7c41328cfba3058..1df9092ca2c49f8f7861c1c09afe7f24e4f3c617 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 030887c869481897b086f1ebfecabe2c9d2450e2..544b7bc32ab3dcc3ea5c6bc1a5e604d21eea4c72 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 747e5426a0c3fc7cb9b5bdb7834ddd98a23e9791..dfbead9f8e6dca0302583afb5af8abbc467a0da4 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 f8060286dbafa9a1fa780f4eb7446adddf2ed08e..f6406d297fdc8ec07261e200413e42bd209c55b4 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 dbd6f7cb4963bff77ee14afc54fa5b428fc36dcc..4a1bd47ab12d97591d350d665b83fc7d521cc3ad 100644 --- a/src/opus_encoder.c +++ b/src/opus_encoder.c @@ -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 (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)