Cleaning up VBR to be frame-size independent

This commit is contained in:
Jean-Marc Valin 2010-05-29 08:07:18 -04:00
parent 524623899c
commit 8cc945c53a

View file

@ -102,7 +102,7 @@ struct CELTEncoder {
celt_int32 vbr_offset; celt_int32 vbr_offset;
celt_int32 vbr_count; celt_int32 vbr_count;
celt_int32 vbr_rate; /* Target number of 16th bits per frame */ celt_int32 vbr_rate_norm; /* Target number of 16th bits per frame */
celt_word16 * restrict preemph_memE; celt_word16 * restrict preemph_memE;
celt_sig * restrict preemph_memD; celt_sig * restrict preemph_memD;
@ -167,7 +167,7 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode, int channels, int *error)
st->start = 0; st->start = 0;
st->end = st->mode->nbEBands; st->end = st->mode->nbEBands;
st->vbr_rate = 0; st->vbr_rate_norm = 0;
st->pitch_enabled = 1; st->pitch_enabled = 1;
st->pitch_permitted = 1; st->pitch_permitted = 1;
st->pitch_available = 1; st->pitch_available = 1;
@ -677,6 +677,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c
int gain_id=0; int gain_id=0;
int norm_rate; int norm_rate;
int LM, M; int LM, M;
celt_int32 vbr_rate=0;
SAVE_STACK; SAVE_STACK;
if (check_encoder(st) != CELT_OK) if (check_encoder(st) != CELT_OK)
@ -890,13 +891,14 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c
ALLOC(fine_quant, st->mode->nbEBands, int); ALLOC(fine_quant, st->mode->nbEBands, int);
ALLOC(pulses, st->mode->nbEBands, int); ALLOC(pulses, st->mode->nbEBands, int);
vbr_rate = M*st->vbr_rate_norm;
/* Computes the max bit-rate allowed in VBR more to avoid busting the budget */ /* Computes the max bit-rate allowed in VBR more to avoid busting the budget */
if (st->vbr_rate>0) if (st->vbr_rate_norm>0)
{ {
celt_int32 vbr_bound, max_allowed; celt_int32 vbr_bound, max_allowed;
vbr_bound = st->vbr_rate; vbr_bound = vbr_rate;
max_allowed = (st->vbr_rate + vbr_bound - st->vbr_reservoir)>>(BITRES+3); max_allowed = (vbr_rate + vbr_bound - st->vbr_reservoir)>>(BITRES+3);
if (max_allowed < 4) if (max_allowed < 4)
max_allowed = 4; max_allowed = 4;
if (max_allowed < nbCompressedBytes) if (max_allowed < nbCompressedBytes)
@ -913,12 +915,12 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c
if (coarse_needed > nbCompressedBytes) if (coarse_needed > nbCompressedBytes)
coarse_needed = nbCompressedBytes; coarse_needed = nbCompressedBytes;
/* Variable bitrate */ /* Variable bitrate */
if (st->vbr_rate>0) if (vbr_rate>0)
{ {
celt_word16 alpha; celt_word16 alpha;
celt_int32 delta; celt_int32 delta;
/* The target rate in 16th bits per frame */ /* The target rate in 16th bits per frame */
celt_int32 target=st->vbr_rate; celt_int32 target=vbr_rate;
/* Shortblocks get a large boost in bitrate, but since they /* Shortblocks get a large boost in bitrate, but since they
are uncommon long blocks are not greatly effected */ are uncommon long blocks are not greatly effected */
@ -944,7 +946,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, c
alpha = QCONST16(.001f,15); alpha = QCONST16(.001f,15);
/* By how much did we "miss" the target on that frame */ /* By how much did we "miss" the target on that frame */
delta = (8<<BITRES)*(celt_int32)target - st->vbr_rate; delta = (8<<BITRES)*(celt_int32)target - vbr_rate;
/* How many bits have we used in excess of what we're allowed */ /* How many bits have we used in excess of what we're allowed */
st->vbr_reservoir += delta; st->vbr_reservoir += delta;
/*printf ("%d\n", st->vbr_reservoir);*/ /*printf ("%d\n", st->vbr_reservoir);*/
@ -1189,14 +1191,14 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
case CELT_SET_VBR_RATE_REQUEST: case CELT_SET_VBR_RATE_REQUEST:
{ {
celt_int32 value = va_arg(ap, celt_int32); celt_int32 value = va_arg(ap, celt_int32);
int N = st->mode->nbShortMdcts*st->mode->shortMdctSize; int frame_rate;
int N = st->mode->shortMdctSize;
if (value<0) if (value<0)
goto bad_arg; goto bad_arg;
if (value>3072000) if (value>3072000)
value = 3072000; value = 3072000;
/* FIXME: We need to find a better way to do this if N is going to change */ frame_rate = ((st->mode->Fs<<3)+(N>>1))/N;
st->vbr_rate = ((st->mode->Fs<<3)+(N>>1))/N; st->vbr_rate_norm = ((value<<(BITRES+3))+(frame_rate>>1))/frame_rate;
st->vbr_rate = ((value<<7)+(st->vbr_rate>>1))/st->vbr_rate;
} }
break; break;
case CELT_RESET_STATE: case CELT_RESET_STATE: