From bd5d54adb837b94ba648e9f7770b59bf64cb4e6c Mon Sep 17 00:00:00 2001 From: Jean-Marc Valin Date: Tue, 20 Oct 2009 00:25:31 -0400 Subject: New VBR rate controller that doesn't allow more than one frame worth of excess bit-rate --- libcelt/celt.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/libcelt/celt.c b/libcelt/celt.c index 1e3bf9b..2c9f4ef 100644 --- a/libcelt/celt.c +++ b/libcelt/celt.c @@ -92,7 +92,13 @@ struct CELTEncoder { int fold_decision; celt_word16 gain_prod; - int VBR_rate; /* Target number of 16th bits per frame */ + /* VBR-related parameters */ + celt_int32 vbr_reservoir; + celt_int32 vbr_drift; + celt_int32 vbr_offset; + celt_int32 vbr_count; + + celt_int32 vbr_rate; /* Target number of 16th bits per frame */ celt_word16 * restrict preemph_memE; celt_sig * restrict preemph_memD; @@ -133,6 +139,16 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error) *error = CELT_INVALID_MODE; return NULL; } +#ifdef DISABLE_STEREO + if (channels > 1) + { + celt_warning("Stereo support was disable from this build"); + if (error) + *error = CELT_BAD_ARG; + return NULL; + } +#endif + if (channels < 0 || channels > 2) { celt_warning("Only mono and stereo supported"); @@ -158,7 +174,7 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error) st->overlap = mode->overlap; st->channels = channels; - st->VBR_rate = 0; + st->vbr_rate = 0; st->pitch_enabled = 1; st->pitch_permitted = 1; st->pitch_available = 1; @@ -662,7 +678,7 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig * pcm, celt_sig compute_band_energies(st->mode, freq, bandE, C); for (i=0;imode->nbEBands*C;i++) bandLogE[i] = amp2Log(bandE[i]); - + /* Band normalisation */ normalise_bands(st->mode, freq, X, bandE, C); if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C)) @@ -754,25 +770,69 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig * pcm, celt_sig coarse_needed = ((coarse_needed*3-1)>>3)+1; /* Variable bitrate */ - if (st->VBR_rate>0) + if (st->vbr_rate>0) { + celt_word16 alpha; + celt_int32 delta, vbr_bound; /* The target rate in 16th bits per frame */ - int target=st->VBR_rate; + celt_int32 target=st->vbr_rate; /* Shortblocks get a large boost in bitrate, but since they are uncommon long blocks are not greatly effected */ if (shortBlocks) target*=2; else if (st->mode->nbShortMdcts > 1) - target-=(target+14)/28; + target-=(target+14)/28; /* The average energy is removed from the target and the actual energy added*/ - target=target-588+ec_enc_tell(&enc, BITRES); + target=target+st->vbr_offset-588+ec_enc_tell(&enc, BITRES); /* In VBR mode the frame size must not be reduced so much that it would result in the coarse energy busting its budget */ target=IMAX(coarse_needed,(target+64)/128); nbCompressedBytes=IMIN(nbCompressedBytes,target); + + /* Make the adaptation coef (alpha) higher at the beginning */ + if (st->vbr_count < 990) + { + st->vbr_count++; + alpha = celt_rcp(SHL32(EXTEND32(st->vbr_count+10),16)); + /*printf ("%d %d\n", st->vbr_count+10, alpha);*/ + } else + alpha = QCONST16(.001f,15); + + /* By how much did we "miss" the target on that frame */ + delta = (8<vbr_rate; + /* How many bits have we used in excess of what we're allowed */ + st->vbr_reservoir += delta; + /*printf ("%d\n", st->vbr_reservoir);*/ + + /* Compute the offset we need to apply in order to reach the target */ + st->vbr_drift += MULT16_32_Q15(alpha,delta-st->vbr_offset-st->vbr_drift); + st->vbr_offset = -st->vbr_drift; + /*printf ("%d\n", st->vbr_drift);*/ + + /* We could use any multiple of vbr_rate as bound (depending on the delay) */ + vbr_bound = st->vbr_rate; + if (st->vbr_reservoir > vbr_bound) + { + /* Busted the reservoir -- reduce the rate */ + int adjust = 1+(st->vbr_reservoir-vbr_bound-1)/(8<vbr_reservoir -= adjust*(8<vbr_offset -= 8<vbr_reservoir < 0) + { + /* We're under the min value -- increase rate */ + int adjust = 1-(st->vbr_reservoir-1)/(8<vbr_reservoir += adjust*(8<vbr_offset += 8<3072000) value = 3072000; - st->VBR_rate = ((st->mode->Fs<<3)+(st->block_size>>1))/st->block_size; - st->VBR_rate = ((value<<7)+(st->VBR_rate>>1))/st->VBR_rate; + st->vbr_rate = ((st->mode->Fs<<3)+(st->block_size>>1))/st->block_size; + st->vbr_rate = ((value<<7)+(st->vbr_rate>>1))/st->vbr_rate; } break; case CELT_RESET_STATE: @@ -1066,6 +1126,16 @@ CELTDecoder *celt_decoder_create(const CELTMode *mode, int channels, int *error) *error = CELT_INVALID_MODE; return NULL; } +#ifdef DISABLE_STEREO + if (channels > 1) + { + celt_warning("Stereo support was disable from this build"); + if (error) + *error = CELT_BAD_ARG; + return NULL; + } +#endif + if (channels < 0 || channels > 2) { celt_warning("Only mono and stereo supported"); -- cgit v1.2.3