Use a smarter per-band bitrate cap.

The previous "dumb cap" of (64<<LM)*(C<<BITRES) was not actually
 achievable by many (most) bands, and did not take the cost of
 coding theta for splits into account, and so was too small for some
 bands.
This patch adds code to compute a fairly accurate estimate of the
 real maximum per-band rate (an estimate only because of rounding
 effects and the fact that the bit usage for theta is variable),
 which is then truncated and stored in an 8-bit table in the mode.

This gives improved quality at all rates over 160 kbps/channel,
 prevents bits from being wasted all the way up to 255 kbps/channel
 (the maximum rate allowed, and approximately the maximum number of
 bits that can usefully be used regardless of the allocation), and
 prevents dynalloc and trim from producing enormous waste
 (eliminating the need for encoder logic to prevent this).
This commit is contained in:
Timothy B. Terriberry 2011-01-29 12:57:18 -08:00 committed by Jean-Marc Valin
parent 9b34bd835c
commit c564307463
6 changed files with 150 additions and 17 deletions

View file

@ -789,6 +789,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
VARDECL(int, fine_quant);
VARDECL(celt_word16, error);
VARDECL(int, pulses);
VARDECL(int, cap);
VARDECL(int, offsets);
VARDECL(int, fine_priority);
VARDECL(int, tf_res);
@ -1107,8 +1108,12 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5);
}
ALLOC(cap, st->mode->nbEBands, int);
ALLOC(offsets, st->mode->nbEBands, int);
for (i=0;i<st->mode->nbEBands;i++)
cap[i] = st->mode->cache.caps[st->mode->nbEBands*(2*LM+C-1)+i]
<< C+LM+BITRES-2;
for (i=0;i<st->mode->nbEBands;i++)
offsets[i] = 0;
/* Dynamic allocation code */
@ -1154,7 +1159,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
dynalloc_loop_logp = dynalloc_logp;
boost = 0;
for (j = 0; tell+(dynalloc_loop_logp<<BITRES) < total_bits-total_boost
&& boost < (64<<LM)*(C<<BITRES); j++)
&& boost < cap[i]; j++)
{
int flag;
flag = j<offsets[i];
@ -1293,7 +1298,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
bits = (nbCompressedBytes*8<<BITRES) - ec_enc_tell(enc, BITRES) - 1;
anti_collapse_rsv = isTransient&&LM>=2&&bits>=(LM+2<<BITRES) ? (1<<BITRES) : 0;
bits -= anti_collapse_rsv;
codedBands = compute_allocation(st->mode, st->start, st->end, offsets,
codedBands = compute_allocation(st->mode, st->start, st->end, offsets, cap,
alloc_trim, &intensity, &dual_stereo, bits, pulses, fine_quant,
fine_priority, C, LM, enc, 1, st->lastCodedBands);
st->lastCodedBands = codedBands;
@ -1953,6 +1958,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
VARDECL(celt_ener, bandE);
VARDECL(int, fine_quant);
VARDECL(int, pulses);
VARDECL(int, cap);
VARDECL(int, offsets);
VARDECL(int, fine_priority);
VARDECL(int, tf_res);
@ -2107,9 +2113,14 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
spread_decision = ec_dec_icdf(dec, spread_icdf, 5);
ALLOC(pulses, st->mode->nbEBands, int);
ALLOC(cap, st->mode->nbEBands, int);
ALLOC(offsets, st->mode->nbEBands, int);
ALLOC(fine_priority, st->mode->nbEBands, int);
for (i=0;i<st->mode->nbEBands;i++)
cap[i] = st->mode->cache.caps[st->mode->nbEBands*(2*LM+C-1)+i]
<< C+LM+BITRES-2;
dynalloc_logp = 6;
total_bits<<=BITRES;
tell = ec_dec_tell(dec, BITRES);
@ -2124,8 +2135,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
quanta = IMIN(width<<BITRES, IMAX(6<<BITRES, width));
dynalloc_loop_logp = dynalloc_logp;
boost = 0;
while (tell+(dynalloc_loop_logp<<BITRES) < total_bits &&
boost < (64<<LM)*(C<<BITRES))
while (tell+(dynalloc_loop_logp<<BITRES) < total_bits && boost < cap[i])
{
int flag;
flag = ec_dec_bit_logp(dec, dynalloc_loop_logp);
@ -2149,7 +2159,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
bits = (len*8<<BITRES) - ec_dec_tell(dec, BITRES) - 1;
anti_collapse_rsv = isTransient&&LM>=2&&bits>=(LM+2<<BITRES) ? (1<<BITRES) : 0;
bits -= anti_collapse_rsv;
codedBands = compute_allocation(st->mode, st->start, st->end, offsets,
codedBands = compute_allocation(st->mode, st->start, st->end, offsets, cap,
alloc_trim, &intensity, &dual_stereo, bits, pulses, fine_quant,
fine_priority, C, LM, dec, 0, 0);

View file

@ -129,6 +129,11 @@ void dump_modes(FILE *file, CELTMode **modes, int nb_modes)
for (j=0;j<mode->cache.size;j++)
fprintf (file, "%d, ", mode->cache.bits[j]);
fprintf (file, "};\n");
fprintf (file, "static const unsigned char cache_caps%d[%d] = {\n", mode->Fs/mdctSize, (mode->maxLM+1)*2*mode->nbEBands);
for (j=0;j<(mode->maxLM+1)*2*mode->nbEBands;j++)
fprintf (file, "%d, ", mode->cache.caps[j]);
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
@ -226,8 +231,8 @@ void dump_modes(FILE *file, CELTMode **modes, int nb_modes)
fprintf(file, "%d,\t/* nbShortMdcts */\n", mode->nbShortMdcts);
fprintf(file, "%d,\t/* shortMdctSize */\n", mode->shortMdctSize);
fprintf(file, "logN%d,\t/* logN */\n", framerate);
fprintf(file, "{%d, cache_index%d, cache_bits%d},\t/* cache */\n",
mode->cache.size, mode->Fs/mdctSize, mode->Fs/mdctSize);
fprintf(file, "{%d, cache_index%d, cache_bits%d, cache_caps%d},\t/* cache */\n",
mode->cache.size, mode->Fs/mdctSize, mode->Fs/mdctSize, mode->Fs/mdctSize);
fprintf(file, "};\n");
}
fprintf(file, "\n");

View file

@ -432,6 +432,7 @@ void celt_mode_destroy(CELTMode *mode)
celt_free((celt_int16*)mode->cache.index);
celt_free((unsigned char*)mode->cache.bits);
celt_free((unsigned char*)mode->cache.caps);
clt_mdct_clear(&mode->mdct);
celt_free((CELTMode *)mode);

View file

@ -71,6 +71,7 @@ typedef struct {
int size;
const celt_int16 *index;
const unsigned char *bits;
const unsigned char *caps;
} PulseCache;
/** Mode definition (opaque)

View file

@ -77,7 +77,9 @@ static int fits_in32(int _n, int _k)
void compute_pulse_cache(CELTMode *m, int LM)
{
int C;
int i;
int j;
int curr=0;
int nbEntries=0;
int entryN[100], entryK[100], entryI[100];
@ -85,6 +87,7 @@ void compute_pulse_cache(CELTMode *m, int LM)
PulseCache *cache = &m->cache;
celt_int16 *cindex;
unsigned char *bits;
unsigned char *cap;
cindex = celt_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2));
cache->index = cindex;
@ -92,7 +95,6 @@ void compute_pulse_cache(CELTMode *m, int LM)
/* Scan for all unique band sizes */
for (i=0;i<=LM+1;i++)
{
int j;
for (j=0;j<m->nbEBands;j++)
{
int k;
@ -133,7 +135,6 @@ void compute_pulse_cache(CELTMode *m, int LM)
/* Compute the cache for all unique sizes */
for (i=0;i<nbEntries;i++)
{
int j;
unsigned char *ptr = bits+entryI[i];
celt_int16 tmp[MAX_PULSES+1];
get_required_bits(tmp, entryN[i], get_pulses(entryK[i]), BITRES);
@ -141,6 +142,112 @@ void compute_pulse_cache(CELTMode *m, int LM)
ptr[j] = tmp[get_pulses(j)]-1;
ptr[0] = entryK[i];
}
/* Compute the maximum rate for each band at which we'll reliably use as
many bits as we ask for. */
cache->caps = cap = celt_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands);
for (i=0;i<=LM;i++)
{
for (C=1;C<=2;C++)
{
int shift;
shift = C+i+BITRES-2;
for (j=0;j<m->nbEBands;j++)
{
int N0;
int max_bits;
int rmask;
N0 = m->eBands[j+1]-m->eBands[j];
rmask = N0==1 ? (1<<shift)-1 : 0;
/* N=1 bands only have a sign bit and fine bits. */
if (N0<<i == 1)
max_bits = C*(1+MAX_FINE_BITS)<<BITRES;
else
{
const unsigned char *pcache;
celt_int32 num;
celt_int32 den;
int LM0;
int N;
int offset;
int ndof;
int qb;
int k;
LM0 = 0;
/* Even-sized bands bigger than N=4 can be split one more
time (N=4 also _can_ be split, but not without waste: the
result can only use 26 bits, but requires an allocation
of 32 to trigger the split). */
if (N0 > 4 && !(N0&1))
{
N0>>=1;
LM0--;
}
/* N0=1 and N0=2 bands can't be split down to N=2. */
else if (N0 <= 2)
{
LM0=IMIN(i,3-N0);
N0<<=LM0;
}
/* Compute the cost for the lowest-level PVQ of a fully split
band. */
pcache = bits + cindex[(LM0+1)*m->nbEBands+j];
max_bits = pcache[pcache[0]]+1;
/* Add in the cost of coding regular splits. */
N = N0;
for(k=0;k<i-LM0;k++){
max_bits <<= 1;
/* Offset the number of qtheta bits by log2(N)/2
+ QTHETA_OFFSET compared to their "fair share" of
total/N */
offset = (m->logN[j]+(LM0+k<<BITRES)>>1)-QTHETA_OFFSET;
/* The number of qtheta bits we'll allocate if the remainder
is to be max_bits. */
num=(celt_int32)((2*N-1)*offset+max_bits)<<9;
den=((celt_int32)(2*N-1)<<9)-495;
qb = IMIN((num+(den>>1))/den, 8<<BITRES);
celt_assert(qb >= 0);
/* The average cost for theta when qn==256 is
7.73246 bits for the triangular PDF. */
max_bits += qb*495+256>>9;
N <<= 1;
}
/* Add in the cost of a stereo split, if necessary. */
if (C==2)
{
max_bits <<= 1;
offset = (m->logN[j]+(i<<BITRES)>>1)-QTHETA_OFFSET_STEREO;
ndof = 2*N-1-(N==2);
num = (celt_int32)(max_bits+ndof*offset)<<7;
den = ((celt_int32)ndof<<7)-(N==2?128:125);
qb = IMIN((num+(den>>1))/den, 8<<BITRES);
celt_assert(qb >= 0);
/* The average cost for theta when qn==256, N>2 is
7.8174 bits for the step PDF. */
max_bits += N==2 ? qb : (qb*125+64>>7);
}
/* Add the fine bits we'll use. */
/* Compensate for the extra DoF in stereo */
ndof = C*N + ((C==2 && N>2) ? 1 : 0);
/* Offset the number of fine bits by log2(N)/2 + FINE_OFFSET
compared to their "fair share" of total/N */
offset = (m->logN[j] + (i<<BITRES)>>1)-FINE_OFFSET;
/* N=2 is the only point that doesn't match the curve */
if (N==2)
offset += 1<<BITRES>>2;
/* The number of fine bits we'll allocate if the remainder is
to be max_bits. */
num = max_bits+ndof*offset;
den = ndof-1<<BITRES;
qb = IMIN((num+(den>>1))/den, MAX_FINE_BITS);
celt_assert(qb >= 0);
max_bits += C*qb<<BITRES;
}
celt_assert(max_bits+rmask>>shift < 256);
*cap++ = (unsigned char)(max_bits+rmask>>shift);
}
}
}
}
#endif /* !STATIC_MODES */
@ -149,7 +256,7 @@ void compute_pulse_cache(CELTMode *m, int LM)
#define ALLOC_STEPS 6
static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int skip_start,
const int *bits1, const int *bits2, const int *thresh, int total, int skip_rsv,
const int *bits1, const int *bits2, const int *thresh, const int *cap, int total, int skip_rsv,
int *intensity, int intensity_rsv, int *dual_stereo, int dual_stereo_rsv, int *bits,
int *ebits, int *fine_priority, int _C, int LM, void *ec, int encode, int prev)
{
@ -184,7 +291,7 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int
{
done = 1;
/* Don't allocate more than we can actually use */
psum += IMIN(tmp, 64*C<<BITRES<<LM);
psum += IMIN(tmp, cap[j]);
} else {
if (tmp >= alloc_floor)
psum += alloc_floor;
@ -210,7 +317,7 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int
} else
done = 1;
/* Don't allocate more than we can actually use */
tmp = IMIN(tmp, 64*C<<BITRES<<LM);
tmp = IMIN(tmp, cap[j]);
bits[j] = tmp;
psum += tmp;
}
@ -388,7 +495,16 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int
}
}
/* The other bits are assigned to PVQ */
/* Sweep any bits over the cap into the first band.
They'll be reallocated by the normal rebalancing code, which gives
them the best chance to be used _somewhere_. */
{
int tmp = IMAX(bits[j]-cap[j],0);
bits[j] -= tmp;
bits[start] += tmp;
}
/* Remove the allocated fine bits; the other bits are assigned to PVQ */
bits[j] -= C*ebits[j]<<BITRES;
celt_assert(bits[j] >= 0);
celt_assert(ebits[j] >= 0);
@ -405,7 +521,7 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int
return codedBands;
}
int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, int alloc_trim, int *intensity, int *dual_stereo,
int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
int total, int *pulses, int *ebits, int *fine_priority, int _C, int LM, void *ec, int encode, int prev)
{
int lo, hi, len, j;
@ -476,7 +592,7 @@ int compute_allocation(const CELTMode *m, int start, int end, const int *offsets
{
done = 1;
/* Don't allocate more than we can actually use */
psum += IMIN(bits1[j], 64*C<<BITRES<<LM);
psum += IMIN(bits1[j], cap[j]);
} else {
if (bits1[j] >= C<<BITRES)
psum += C<<BITRES;
@ -507,7 +623,7 @@ int compute_allocation(const CELTMode *m, int start, int end, const int *offsets
skip_start = j;
bits2[j] -= bits1[j];
}
codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh,
codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh, cap,
total, skip_rsv, intensity, intensity_rsv, dual_stereo, dual_stereo_rsv,
pulses, ebits, fine_priority, C, LM, ec, encode, prev);
RESTORE_STACK;

View file

@ -105,7 +105,7 @@ celt_int16 **compute_alloc_cache(CELTMode *m, int M);
@param pulses Number of pulses per band (returned)
@return Total number of bits allocated
*/
int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, int alloc_trim, int *intensity, int *dual_stero,
int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero,
int total, int *pulses, int *ebits, int *fine_priority, int _C, int LM, void *ec, int encode, int prev);