Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/celt.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <Jean-Marc.Valin@csiro.au>2008-05-07 07:44:39 +0400
committerJean-Marc Valin <Jean-Marc.Valin@csiro.au>2008-05-07 07:44:39 +0400
commitad6371906a816bef202f10fb3cca602280a8765f (patch)
tree2acd65ecbef687f409826b9e3e40022e4b7f943b
parent827f93175bc532beab5c5d49eed6649282795708 (diff)
Implemented rate-dependant allocation for the fine energy quantisation.
-rw-r--r--libcelt/celt.c4
-rw-r--r--libcelt/dump_modes.c1
-rw-r--r--libcelt/modes.c35
-rw-r--r--libcelt/modes.h1
-rw-r--r--libcelt/quant_bands.c86
5 files changed, 108 insertions, 19 deletions
diff --git a/libcelt/celt.c b/libcelt/celt.c
index f28be89..fddd416 100644
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -321,7 +321,7 @@ int EXPORT celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, u
for (i=0;i<C*N;i++)
P[i] = 0;
}
- quant_energy(st->mode, bandE, st->oldBandE, nbCompressedBytes*8/3, st->mode->prob, &st->enc);
+ quant_energy(st->mode, bandE, st->oldBandE, 20+nbCompressedBytes*8/5, st->mode->prob, &st->enc);
if (C==2)
{
@@ -589,7 +589,7 @@ int EXPORT celt_decode(CELTDecoder * restrict st, unsigned char *data, int len,
}
/* Get band energies */
- unquant_energy(st->mode, bandE, st->oldBandE, len*8/3, st->mode->prob, &dec);
+ unquant_energy(st->mode, bandE, st->oldBandE, 20+len*8/5, st->mode->prob, &dec);
/* Pitch MDCT */
compute_mdcts(st->mode, st->mode->window, st->out_mem+pitch_index*C, freq);
diff --git a/libcelt/dump_modes.c b/libcelt/dump_modes.c
index 6a19086..9f00dcc 100644
--- a/libcelt/dump_modes.c
+++ b/libcelt/dump_modes.c
@@ -161,6 +161,7 @@ void dump_modes(FILE *file, CELTMode **modes, int nb_modes)
fprintf(file, "window%d,\t/* window */\n", mode->overlap);
fprintf(file, "{psy_decayR_%d},\t/* psy */\n", mode->Fs);
fprintf(file, "0,\t/* prob */\n");
+ fprintf(file, "0,\t/* energy_alloc */\n");
fprintf(file, "0x%x,\t/* marker */\n", 0xa110ca7e);
fprintf(file, "};\n");
}
diff --git a/libcelt/modes.c b/libcelt/modes.c
index 29ea983..6b9af97 100644
--- a/libcelt/modes.c
+++ b/libcelt/modes.c
@@ -232,6 +232,38 @@ static void compute_allocation_table(CELTMode *mode, int res)
#endif /* STATIC_MODES */
+static void compute_energy_allocation_table(CELTMode *mode)
+{
+ int i, j;
+ celt_int16_t *alloc;
+
+ alloc = celt_alloc(sizeof(celt_int16_t)*(mode->nbAllocVectors*(mode->nbEBands+1)));
+ for (i=0;i<mode->nbAllocVectors;i++)
+ {
+ int sum = 0;
+ int min_bits = 1;
+ if (mode->allocVectors[i*mode->nbEBands]>12)
+ min_bits = 2;
+ if (mode->allocVectors[i*mode->nbEBands]>24)
+ min_bits = 3;
+ for (j=0;j<mode->nbEBands;j++)
+ {
+ alloc[i*(mode->nbEBands+1)+j] = mode->allocVectors[i*mode->nbEBands+j]
+ / (mode->eBands[j+1]-mode->eBands[j]-1);
+ if (alloc[i*(mode->nbEBands+1)+j]<min_bits)
+ alloc[i*(mode->nbEBands+1)+j] = min_bits;
+ if (alloc[i*(mode->nbEBands+1)+j]>7)
+ alloc[i*(mode->nbEBands+1)+j] = 7;
+ sum += alloc[i*(mode->nbEBands+1)+j];
+ /*printf ("%d ", alloc[i*(mode->nbEBands+1)+j]);*/
+ /*printf ("%f ", mode->allocVectors[i*mode->nbEBands+j]*1.f/(mode->eBands[j+1]-mode->eBands[j]-1));*/
+ }
+ alloc[i*(mode->nbEBands+1)+mode->nbEBands] = sum;
+ /*printf ("\n");*/
+ }
+ mode->energy_alloc = alloc;
+}
+
CELTMode EXPORT *celt_mode_create(celt_int32_t Fs, int channels, int frame_size, int lookahead, int *error)
{
int i;
@@ -342,6 +374,8 @@ CELTMode EXPORT *celt_mode_create(celt_int32_t Fs, int channels, int frame_size,
mode->fft = pitch_state_alloc(MAX_PERIOD);
mode->prob = quant_prob_alloc(mode);
+ compute_energy_allocation_table(mode);
+
if (error)
*error = CELT_OK;
return mode;
@@ -378,6 +412,7 @@ void EXPORT celt_mode_destroy(CELTMode *mode)
mdct_clear(&mode->mdct);
pitch_state_free(mode->fft);
quant_prob_free(mode->prob);
+ celt_free((celt_int16_t *)mode->energy_alloc);
celt_free((CELTMode *)mode);
}
diff --git a/libcelt/modes.h b/libcelt/modes.h
index d7b59f0..d47825e 100644
--- a/libcelt/modes.h
+++ b/libcelt/modes.h
@@ -96,6 +96,7 @@ struct CELTMode {
struct PsyDecay psy;
int *prob;
+ const celt_int16_t *energy_alloc;
celt_uint32_t marker_end;
};
diff --git a/libcelt/quant_bands.c b/libcelt/quant_bands.c
index 5e6ec9a..2c6fb63 100644
--- a/libcelt/quant_bands.c
+++ b/libcelt/quant_bands.c
@@ -48,7 +48,47 @@ const celt_word16_t eMeans[24] = {45.f, -8.f, -12.f, -2.5f, 1.f, 0.f, 0.f, 0.f,
#endif
/*const int frac[24] = {4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};*/
-const int frac[24] = {8, 6, 5, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+/*const int frac[24] = {8, 6, 5, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};*/
+
+static void compute_fine_allocation(const CELTMode *m, celt_int16_t *bits, int budget)
+{
+ int i,j;
+ int len;
+ len = m->nbEBands;
+ for (i=0;i<m->nbAllocVectors;i++)
+ {
+ if (m->energy_alloc[i*(len+1)+len] > budget)
+ break;
+ }
+ if (i==0)
+ {
+ for (j=0;j<len;j++)
+ bits[j] = 0;
+ } else {
+ for (j=0;j<len;j++)
+ bits[j] = m->energy_alloc[(i-1)*(len+1)+j];
+ budget -= m->energy_alloc[(i-1)*(len+1)+len];
+ }
+ if (i<m->nbAllocVectors)
+ {
+ j=0;
+ while (budget>0)
+ {
+ if (m->energy_alloc[i*(len+1)+j]>bits[j])
+ {
+ bits[j]++;
+ budget--;
+ }
+ j++;
+ if (j>=len)
+ j=0;
+ }
+ }
+
+ /*for (j=0;j<len;j++)
+ printf ("%d ", bits[j]);
+ printf ("\n");*/
+}
#ifdef FIXED_POINT
static inline celt_ener_t dB2Amp(celt_ener_t dB)
@@ -155,11 +195,13 @@ static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word1
celt_word16_t coef = m->ePredCoef;
celt_word16_t beta;
VARDECL(celt_word16_t, error);
+ VARDECL(celt_int16_t, fine_quant);
SAVE_STACK;
/* The .7 is a heuristic */
beta = MULT16_16_Q15(QCONST16(.8f,15),coef);
ALLOC(error, m->nbEBands, celt_word16_t);
+ ALLOC(fine_quant, m->nbEBands, celt_int16_t);
bits = ec_enc_tell(enc, 0);
/* Encode at a fixed coarse resolution */
for (i=0;i<m->nbEBands;i++)
@@ -177,8 +219,9 @@ static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word1
#else
qi = (int)floor(.5+f);
#endif
- /* If we don't have enough bits to encode all the energy, just assume something safe. */
- if (ec_enc_tell(enc, 0) - bits > budget)
+ /* If we don't have enough bits to encode all the energy, just assume something safe.
+ We allow slightly busting the budget here */
+ if (ec_enc_tell(enc, 0) - bits > budget+16)
qi = -1;
else
ec_laplace_encode_start(enc, qi, prob[2*i], prob[2*i+1]);
@@ -189,24 +232,25 @@ static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word1
prev = mean+prev+MULT16_16_Q15(Q15ONE-beta,q);
}
+
+ compute_fine_allocation(m, fine_quant, budget-(ec_enc_tell(enc, 0)-bits));
+
/* Encode finer resolution */
for (i=0;i<m->nbEBands;i++)
{
int q2;
- celt_word16_t offset = (error[i]+QCONST16(.5f,8))*frac[i];
- /* FIXME: Instead of giving up without warning, we should degrade everything gracefully */
- if (ec_enc_tell(enc, 0) - bits + celt_ilog2(frac[i]) >= budget)
- break;
+ celt_int16_t frac = 1<<fine_quant[i];
+ celt_word16_t offset = (error[i]+QCONST16(.5f,8))*frac;
#ifdef FIXED_POINT
/* Has to be without rounding */
q2 = offset>>8;
#else
q2 = (int)floor(offset);
#endif
- if (q2 > frac[i]-1)
- q2 = frac[i]-1;
- enc_frac(enc, q2, frac[i]);
- offset = EXTRACT16(celt_div(SHL16(q2,8)+QCONST16(.5,8),frac[i])-QCONST16(.5f,8));
+ if (q2 > frac-1)
+ q2 = frac-1;
+ enc_frac(enc, q2, frac);
+ offset = EXTRACT16(celt_div(SHL16(q2,8)+QCONST16(.5,8),frac)-QCONST16(.5f,8));
oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
/*printf ("%f ", error[i] - offset);*/
}
@@ -227,7 +271,11 @@ static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_wor
celt_word16_t prev = 0;
celt_word16_t coef = m->ePredCoef;
/* The .7 is a heuristic */
+ VARDECL(celt_int16_t, fine_quant);
celt_word16_t beta = MULT16_16_Q15(QCONST16(.8f,15),coef);
+ SAVE_STACK;
+
+ ALLOC(fine_quant, m->nbEBands, celt_int16_t);
bits = ec_dec_tell(dec, 0);
/* Decode at a fixed coarse resolution */
@@ -236,8 +284,9 @@ static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_wor
int qi;
celt_word16_t q;
celt_word16_t mean = MULT16_16_Q15(Q15ONE-coef,eMeans[i]);
- /* If we didn't have enough bits to encode all the energy, just assume something safe. */
- if (ec_dec_tell(dec, 0) - bits > budget)
+ /* If we didn't have enough bits to encode all the energy, just assume something safe.
+ We allow slightly busting the budget here */
+ if (ec_dec_tell(dec, 0) - bits > budget+16)
qi = -1;
else
qi = ec_laplace_decode_start(dec, prob[2*i], prob[2*i+1]);
@@ -247,21 +296,24 @@ static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_wor
prev = mean+prev+MULT16_16_Q15(Q15ONE-beta,q);
}
+
+ compute_fine_allocation(m, fine_quant, budget-(ec_dec_tell(dec, 0)-bits));
+
/* Decode finer resolution */
for (i=0;i<m->nbEBands;i++)
{
int q2;
+ celt_int16_t frac = 1<<fine_quant[i];
celt_word16_t offset;
- if (ec_dec_tell(dec, 0) - bits + celt_ilog2(frac[i]) >= budget)
- break;
- q2 = dec_frac(dec, frac[i]);
- offset = EXTRACT16(celt_div(SHL16(q2,8)+QCONST16(.5,8),frac[i])-QCONST16(.5f,8));
+ q2 = dec_frac(dec, frac);
+ offset = EXTRACT16(celt_div(SHL16(q2,8)+QCONST16(.5,8),frac)-QCONST16(.5f,8));
oldEBands[i] += PSHR32(MULT16_16(DB_SCALING*6,offset),8);
}
for (i=0;i<m->nbEBands;i++)
{
eBands[i] = dB2Amp(oldEBands[i]);
}
+ RESTORE_STACK;
/*printf ("\n");*/
}