mirror of
https://github.com/xiph/opus.git
synced 2025-06-06 07:21:03 +00:00
Implemented rate-dependant allocation for the fine energy quantisation.
This commit is contained in:
parent
827f93175b
commit
ad6371906a
5 changed files with 108 additions and 19 deletions
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ struct CELTMode {
|
|||
struct PsyDecay psy;
|
||||
|
||||
int *prob;
|
||||
const celt_int16_t *energy_alloc;
|
||||
|
||||
celt_uint32_t marker_end;
|
||||
};
|
||||
|
|
|
@ -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");*/
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue