ref: 9a6c4966309edea641602fea556e5ef654f95f08
parent: 9acd9293c35b9b2c005e8582fbdbbf3caebbe5fc
author: Jean-Marc Valin <[email protected]>
date: Sun Feb 8 19:45:48 EST 2009
Changed the allocator to be smarter about the way it allocates fine energy bits. Also, doing better rounding of the bits.
--- a/libcelt/cwrs.h
+++ b/libcelt/cwrs.h
@@ -36,6 +36,8 @@
#include "entenc.h"
#include "entdec.h"
+int log2_frac(ec_uint32 val, int frac);
+
/* Returns log of an integer with fractional accuracy */
int log2_frac64(ec_uint64 val, int frac);
/* Whether the CWRS codebook will fit into 32 bits */
--- a/libcelt/modes.c
+++ b/libcelt/modes.c
@@ -228,7 +228,7 @@
celt_int32_t alloc;
edge = mode->eBands[eband+1]*res;
alloc = band_allocation[i*BARK_BANDS+j];
- alloc = alloc*C*mode->mdctSize/256;
+ alloc = alloc*C*mode->mdctSize;
if (edge < bark_freq[j+1])
{
int num, den;
@@ -243,30 +243,15 @@
}
}
}
- /* Compute fine energy resolution and update the pulse allocation table to subtract that */
for (i=0;i<mode->nbAllocVectors;i++)
{
- int sum = 0;
for (j=0;j<mode->nbEBands;j++)
- {
- int ebits;
- int min_bits=0;
- if (allocVectors[i*mode->nbEBands+j] > 0)
- min_bits = 1;
- ebits = IMAX(min_bits , allocVectors[i*mode->nbEBands+j] / (C*(mode->eBands[j+1]-mode->eBands[j])));
- if (ebits>7)
- ebits=7;
- /* The bits used for fine allocation can't be used for pulses */
- /* However, we give two "free" bits to all modes to compensate for the fact that some energy
- resolution is needed regardless of the frame size. */
- if (ebits>1)
- allocVectors[i*mode->nbEBands+j] -= C*(ebits-2);
- if (allocVectors[i*mode->nbEBands+j] < 0)
- allocVectors[i*mode->nbEBands+j] = 0;
- sum += ebits;
- allocEnergy[i*(mode->nbEBands+1)+j] = ebits;
- }
- allocEnergy[i*(mode->nbEBands+1)+mode->nbEBands] = sum;
+ allocVectors[i*mode->nbEBands+j] = (allocVectors[i*mode->nbEBands+j]+128)/256;
+ }
+ for (i=0;i<mode->nbAllocVectors;i++)
+ {
+ for (j=0;j<mode->nbEBands;j++)
+ allocVectors[i*mode->nbEBands+j] += C;
}
mode->energy_alloc = allocEnergy;
mode->allocVectors = allocVectors;
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -73,9 +73,9 @@
-static int interp_bits2pulses(const CELTMode *m, int *bits1, int *bits2, int *ebits1, int *ebits2, int total, int *bits, int *ebits, int len)
+static void interp_bits2pulses(const CELTMode *m, int *bits1, int *bits2, int total, int *bits, int *ebits, int len)
{
- int esum, psum;
+ int psum;
int lo, hi;
int j;
const int C = CHANNELS(m);
@@ -86,27 +86,17 @@
{
int mid = (lo+hi)>>1;
psum = 0;
- esum = 0;
for (j=0;j<len;j++)
- {
- esum += (((1<<BITRES)-mid)*ebits1[j] + mid*ebits2[j] + (1<<(BITRES-1)))>>BITRES;
psum += ((1<<BITRES)-mid)*bits1[j] + mid*bits2[j];
- }
- if (psum > (total-C*esum)<<BITRES)
+ if (psum > (total<<BITRES))
hi = mid;
else
lo = mid;
}
- esum = 0;
psum = 0;
/*printf ("interp bisection gave %d\n", lo);*/
for (j=0;j<len;j++)
{
- ebits[j] = (((1<<BITRES)-lo)*ebits1[j] + lo*ebits2[j] + (1<<(BITRES-1)))>>BITRES;
- esum += ebits[j];
- }
- for (j=0;j<len;j++)
- {
bits[j] = ((1<<BITRES)-lo)*bits1[j] + lo*bits2[j];
psum += bits[j];
}
@@ -113,7 +103,7 @@
/* Allocate the remaining bits */
{
int left, perband;
- left = ((total-C*esum)<<BITRES)-psum;
+ left = (total<<BITRES)-psum;
perband = left/len;
for (j=0;j<len;j++)
bits[j] += perband;
@@ -121,26 +111,39 @@
for (j=0;j<left;j++)
bits[j]++;
}
+ for (j=0;j<len;j++)
+ {
+ int offset;
+ int min_bits=0;
+ if (bits[j] >= C>>BITRES)
+ min_bits = 1;
+ /* Offset for the number of fine bits compared to their "fair share" of total/N */
+ offset = 45 - log2_frac(m->eBands[j+1]-m->eBands[j], 4);
+ ebits[j] = IMAX(min_bits , ((bits[j]+C*(m->eBands[j+1]-m->eBands[j])/2) / (C*(m->eBands[j+1]-m->eBands[j])) - offset)>>BITRES );
+ /* Make sure not to bust */
+ if (C*ebits[j] > (bits[j]>>BITRES))
+ ebits[j] = bits[j]/C >> BITRES;
+
+ if (ebits[j]>7)
+ ebits[j]=7;
+ /* The bits used for fine allocation can't be used for pulses */
+ bits[j] -= C*ebits[j]<<BITRES;
+ if (bits[j] < 0)
+ bits[j] = 0;
+ }
RESTORE_STACK;
- return (total-C*esum)<<BITRES;
}
void compute_allocation(const CELTMode *m, int *offsets, const int *stereo_mode, int total, int *pulses, int *ebits)
{
int lo, hi, len, j;
- int remaining_bits;
VARDECL(int, bits1);
VARDECL(int, bits2);
- VARDECL(int, ebits1);
- VARDECL(int, ebits2);
- const int C = CHANNELS(m);
SAVE_STACK;
len = m->nbEBands;
ALLOC(bits1, len, int);
ALLOC(bits2, len, int);
- ALLOC(ebits1, len, int);
- ALLOC(ebits2, len, int);
lo = 0;
hi = m->nbAllocVectors - 1;
@@ -157,7 +160,7 @@
/*printf ("%d ", bits[j]);*/
}
/*printf ("\n");*/
- if (psum > (total-C*m->energy_alloc[mid*(len+1)+len])<<BITRES)
+ if (psum > (total<<BITRES))
hi = mid;
else
lo = mid;
@@ -166,8 +169,6 @@
/*printf ("interp between %d and %d\n", lo, hi);*/
for (j=0;j<len;j++)
{
- ebits1[j] = m->energy_alloc[lo*(len+1)+j];
- ebits2[j] = m->energy_alloc[hi*(len+1)+j];
bits1[j] = m->allocVectors[lo*len+j] + offsets[j];
bits2[j] = m->allocVectors[hi*len+j] + offsets[j];
if (bits1[j] < 0)
@@ -175,7 +176,7 @@
if (bits2[j] < 0)
bits2[j] = 0;
}
- remaining_bits = interp_bits2pulses(m, bits1, bits2, ebits1, ebits2, total, pulses, ebits, len);
+ interp_bits2pulses(m, bits1, bits2, total, pulses, ebits, len);
RESTORE_STACK;
}