From 2ad6a746cb49f14ac399ed1f893f2f40ca2a5edf Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Mon, 4 Jul 2016 01:06:11 -0400 Subject: Adds some smoothing to the energy quantization When the energy is stable, we slightly bias energy quantization towards the previous error to make the gain more stable (a constant offset is better than fluctuations). We reduce the bitrate by about 0.2% to 1% at low bitrate for the same quality. --- celt/celt_encoder.c | 28 ++++++++++++++++++++++++++-- celt/quant_bands.c | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/celt/celt_encoder.c b/celt/celt_encoder.c index 1520a6ca..1f6d0ce9 100644 --- a/celt/celt_encoder.c +++ b/celt/celt_encoder.c @@ -124,6 +124,7 @@ struct OpusCustomEncoder { /* opus_val16 oldBandE[], Size = channels*mode->nbEBands */ /* opus_val16 oldLogE[], Size = channels*mode->nbEBands */ /* opus_val16 oldLogE2[], Size = channels*mode->nbEBands */ + /* opus_val16 energyError[], Size = channels*mode->nbEBands */ }; int celt_encoder_get_size(int channels) @@ -137,9 +138,10 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int int size = sizeof(struct CELTEncoder) + (channels*mode->overlap-1)*sizeof(celt_sig) /* celt_sig in_mem[channels*mode->overlap]; */ + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */ - + 3*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ + + 4*channels*mode->nbEBands*sizeof(opus_val16); /* opus_val16 oldBandE[channels*mode->nbEBands]; */ /* opus_val16 oldLogE[channels*mode->nbEBands]; */ /* opus_val16 oldLogE2[channels*mode->nbEBands]; */ + /* opus_val16 energyError[channels*mode->nbEBands]; */ return size; } @@ -1320,7 +1322,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, VARDECL(int, tf_res); VARDECL(unsigned char, collapse_masks); celt_sig *prefilter_mem; - opus_val16 *oldBandE, *oldLogE, *oldLogE2; + opus_val16 *oldBandE, *oldLogE, *oldLogE2, *energyError; int shortBlocks=0; int isTransient=0; const int CC = st->channels; @@ -1400,6 +1402,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, oldBandE = (opus_val16*)(st->in_mem+CC*(overlap+COMBFILTER_MAXPERIOD)); oldLogE = oldBandE + CC*nbEBands; oldLogE2 = oldLogE + CC*nbEBands; + energyError = oldLogE2 + CC*nbEBands; if (enc==NULL) { @@ -1775,6 +1778,19 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, } ALLOC(error, C*nbEBands, opus_val16); + c=0; + do { + for (i=start;iforce_intra, @@ -2074,6 +2090,14 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, ec_enc_bits(enc, anti_collapse_on, 1); } quant_energy_finalise(mode, start, end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C); + OPUS_CLEAR(energyError, nbEBands*CC); + c=0; + do { + for (i=start;inbEBands] += offset; + error[i+c*m->nbEBands] -= offset; bits_left--; } while (++c < C); } -- cgit v1.2.3