mirror of
https://github.com/xiph/opus.git
synced 2025-06-05 23:10:54 +00:00
Optimisation: caching the divisions used in the Laplace encoder.
This commit is contained in:
parent
e488a1077b
commit
4ce9205f38
9 changed files with 77 additions and 26 deletions
|
@ -301,7 +301,7 @@ int EXPORT celt_encode(CELTEncoder * restrict st, celt_int16_t * restrict pcm, u
|
||||||
/* Compute MDCTs of the pitch part */
|
/* Compute MDCTs of the pitch part */
|
||||||
compute_mdcts(st->mode, st->mode->window, st->out_mem+pitch_index*C, freq);
|
compute_mdcts(st->mode, st->mode->window, st->out_mem+pitch_index*C, freq);
|
||||||
|
|
||||||
quant_energy(st->mode, bandE, st->oldBandE, nbCompressedBytes*8/3, &st->enc);
|
quant_energy(st->mode, bandE, st->oldBandE, nbCompressedBytes*8/3, st->mode->prob, &st->enc);
|
||||||
|
|
||||||
if (C==2)
|
if (C==2)
|
||||||
{
|
{
|
||||||
|
@ -573,7 +573,7 @@ int EXPORT celt_decode(CELTDecoder * restrict st, unsigned char *data, int len,
|
||||||
ec_dec_init(&dec,&buf);
|
ec_dec_init(&dec,&buf);
|
||||||
|
|
||||||
/* Get band energies */
|
/* Get band energies */
|
||||||
unquant_energy(st->mode, bandE, st->oldBandE, len*8/3, &dec);
|
unquant_energy(st->mode, bandE, st->oldBandE, len*8/3, st->mode->prob, &dec);
|
||||||
|
|
||||||
/* Get the pitch gains */
|
/* Get the pitch gains */
|
||||||
has_pitch = unquant_pitch(gains, st->mode->nbPBands, &dec);
|
has_pitch = unquant_pitch(gains, st->mode->nbPBands, &dec);
|
||||||
|
|
|
@ -159,6 +159,7 @@ void dump_modes(FILE *file, CELTMode **modes, int nb_modes)
|
||||||
fprintf(file, "{%d, 0, 0},\t/* mdct */\n", 2*mode->mdctSize);
|
fprintf(file, "{%d, 0, 0},\t/* mdct */\n", 2*mode->mdctSize);
|
||||||
fprintf(file, "window%d,\t/* window */\n", mode->overlap);
|
fprintf(file, "window%d,\t/* window */\n", mode->overlap);
|
||||||
fprintf(file, "{psy_decayR_%d},\t/* psy */\n", mode->Fs);
|
fprintf(file, "{psy_decayR_%d},\t/* psy */\n", mode->Fs);
|
||||||
|
fprintf(file, "0,\t/* prob */\n");
|
||||||
fprintf(file, "0x%x,\t/* marker */\n", 0xa110ca7e);
|
fprintf(file, "0x%x,\t/* marker */\n", 0xa110ca7e);
|
||||||
fprintf(file, "};\n");
|
fprintf(file, "};\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,15 +35,15 @@
|
||||||
|
|
||||||
#include "laplace.h"
|
#include "laplace.h"
|
||||||
|
|
||||||
static int ec_laplace_get_start_freq(int decay)
|
int ec_laplace_get_start_freq(int decay)
|
||||||
{
|
{
|
||||||
return (((ec_uint32)32767)*(16384-decay))/(16384+decay);
|
return (((ec_uint32)32767)*(16384-decay))/(16384+decay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ec_laplace_encode(ec_enc *enc, int value, int decay)
|
void ec_laplace_encode_start(ec_enc *enc, int value, int decay, int fs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int fl, fs, ft;
|
int fl, ft;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
{
|
{
|
||||||
|
@ -51,7 +51,6 @@ void ec_laplace_encode(ec_enc *enc, int value, int decay)
|
||||||
value = -value;
|
value = -value;
|
||||||
}
|
}
|
||||||
ft = 32767;
|
ft = 32767;
|
||||||
fs = ec_laplace_get_start_freq(decay);
|
|
||||||
fl = -fs;
|
fl = -fs;
|
||||||
for (i=0;i<value;i++)
|
for (i=0;i<value;i++)
|
||||||
{
|
{
|
||||||
|
@ -76,13 +75,19 @@ void ec_laplace_encode(ec_enc *enc, int value, int decay)
|
||||||
ec_encode(enc, fl, fl+fs, ft);
|
ec_encode(enc, fl, fl+fs, ft);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ec_laplace_decode(ec_dec *dec, int decay)
|
void ec_laplace_encode(ec_enc *enc, int value, int decay)
|
||||||
|
{
|
||||||
|
int fs = ec_laplace_get_start_freq(decay);
|
||||||
|
ec_laplace_encode_start(enc, value, decay, fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ec_laplace_decode_start(ec_dec *dec, int decay, int fs)
|
||||||
{
|
{
|
||||||
int val=0;
|
int val=0;
|
||||||
int fl, fh, fs, ft, fm;
|
int fl, fh, ft, fm;
|
||||||
fl = 0;
|
fl = 0;
|
||||||
ft = 32767;
|
ft = 32767;
|
||||||
fs = ec_laplace_get_start_freq(decay);
|
|
||||||
fh = fs;
|
fh = fs;
|
||||||
fm = ec_decode(dec, ft);
|
fm = ec_decode(dec, ft);
|
||||||
/*DEBUG*/
|
/*DEBUG*/
|
||||||
|
@ -113,4 +118,8 @@ int ec_laplace_decode(ec_dec *dec, int decay)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ec_laplace_decode(ec_dec *dec, int decay)
|
||||||
|
{
|
||||||
|
int fs = ec_laplace_get_start_freq(decay);
|
||||||
|
return ec_laplace_decode_start(dec, decay, fs);
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include "entenc.h"
|
#include "entenc.h"
|
||||||
#include "entdec.h"
|
#include "entdec.h"
|
||||||
|
|
||||||
|
int ec_laplace_get_start_freq(int decay);
|
||||||
|
|
||||||
/** Encode a value that is assumed to be the realisation of a
|
/** Encode a value that is assumed to be the realisation of a
|
||||||
Laplace-distributed random process
|
Laplace-distributed random process
|
||||||
@param enc Entropy encoder state
|
@param enc Entropy encoder state
|
||||||
|
@ -40,6 +42,8 @@
|
||||||
*/
|
*/
|
||||||
void ec_laplace_encode(ec_enc *enc, int value, int decay);
|
void ec_laplace_encode(ec_enc *enc, int value, int decay);
|
||||||
|
|
||||||
|
void ec_laplace_encode_start(ec_enc *enc, int value, int decay, int fs);
|
||||||
|
|
||||||
/** Decode a value that is assumed to be the realisation of a
|
/** Decode a value that is assumed to be the realisation of a
|
||||||
Laplace-distributed random process
|
Laplace-distributed random process
|
||||||
@param dec Entropy decoder state
|
@param dec Entropy decoder state
|
||||||
|
@ -47,3 +51,5 @@ void ec_laplace_encode(ec_enc *enc, int value, int decay);
|
||||||
@return Value decoded
|
@return Value decoded
|
||||||
*/
|
*/
|
||||||
int ec_laplace_decode(ec_dec *dec, int decay);
|
int ec_laplace_decode(ec_dec *dec, int decay);
|
||||||
|
|
||||||
|
int ec_laplace_decode_start(ec_dec *dec, int decay, int fs);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "rate.h"
|
#include "rate.h"
|
||||||
#include "os_support.h"
|
#include "os_support.h"
|
||||||
#include "stack_alloc.h"
|
#include "stack_alloc.h"
|
||||||
|
#include "quant_bands.h"
|
||||||
|
|
||||||
#ifdef STATIC_MODES
|
#ifdef STATIC_MODES
|
||||||
#include "static_modes.c"
|
#include "static_modes.c"
|
||||||
|
@ -319,6 +320,7 @@ CELTMode EXPORT *celt_mode_create(celt_int32_t Fs, int channels, int frame_size,
|
||||||
mode->marker_end = MODEVALID;
|
mode->marker_end = MODEVALID;
|
||||||
#endif /* !STATIC_MODES */
|
#endif /* !STATIC_MODES */
|
||||||
mdct_init(&mode->mdct, 2*mode->mdctSize);
|
mdct_init(&mode->mdct, 2*mode->mdctSize);
|
||||||
|
mode->prob = quant_prob_alloc(mode);
|
||||||
if (error)
|
if (error)
|
||||||
*error = CELT_OK;
|
*error = CELT_OK;
|
||||||
return mode;
|
return mode;
|
||||||
|
@ -353,6 +355,7 @@ void EXPORT celt_mode_destroy(CELTMode *mode)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
mdct_clear(&mode->mdct);
|
mdct_clear(&mode->mdct);
|
||||||
|
quant_prob_free(mode->prob);
|
||||||
celt_free((CELTMode *)mode);
|
celt_free((CELTMode *)mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,8 @@ struct CELTMode {
|
||||||
|
|
||||||
struct PsyDecay psy;
|
struct PsyDecay psy;
|
||||||
|
|
||||||
|
int *prob;
|
||||||
|
|
||||||
celt_uint32_t marker_end;
|
celt_uint32_t marker_end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyD
|
||||||
#endif
|
#endif
|
||||||
celt_word16_t * restrict X, * restrict Y;
|
celt_word16_t * restrict X, * restrict Y;
|
||||||
celt_word16_t * restrict Xptr, * restrict Yptr;
|
celt_word16_t * restrict Xptr, * restrict Yptr;
|
||||||
|
const celt_sig_t * restrict yptr;
|
||||||
int n2;
|
int n2;
|
||||||
int L2;
|
int L2;
|
||||||
const int C = CHANNELS(m);
|
const int C = CHANNELS(m);
|
||||||
|
@ -164,11 +165,19 @@ void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyD
|
||||||
/* Deferred allocation to reduce peak stack usage */
|
/* Deferred allocation to reduce peak stack usage */
|
||||||
ALLOC(_Y, lag, celt_word16_t);
|
ALLOC(_Y, lag, celt_word16_t);
|
||||||
Y = _Y;
|
Y = _Y;
|
||||||
CELT_MEMSET(Y,0,lag);
|
yptr = &y[0];
|
||||||
/* Sum all channels of the past audio and copy into Y in bit-reverse order */
|
/* Copy first channel of the past audio into Y in bit-reverse order */
|
||||||
for (c=0;c<C;c++)
|
for (i=0;i<n2;i++)
|
||||||
{
|
{
|
||||||
const celt_sig_t * restrict yptr = &y[c];
|
Y[2*BITREV(fft,i)] = SHR32(*yptr,INPUT_SHIFT);
|
||||||
|
yptr += C;
|
||||||
|
Y[2*BITREV(fft,i)+1] = SHR32(*yptr,INPUT_SHIFT);
|
||||||
|
yptr += C;
|
||||||
|
}
|
||||||
|
/* Add remaining channels into Y in bit-reverse order */
|
||||||
|
for (c=1;c<C;c++)
|
||||||
|
{
|
||||||
|
yptr = &y[c];
|
||||||
for (i=0;i<n2;i++)
|
for (i=0;i<n2;i++)
|
||||||
{
|
{
|
||||||
Y[2*BITREV(fft,i)] += SHR32(*yptr,INPUT_SHIFT);
|
Y[2*BITREV(fft,i)] += SHR32(*yptr,INPUT_SHIFT);
|
||||||
|
|
|
@ -129,7 +129,25 @@ static inline int dec_frac(ec_dec *dec, int ft)
|
||||||
|
|
||||||
static const celt_word16_t base_resolution = QCONST16(6.f,8);
|
static const celt_word16_t base_resolution = QCONST16(6.f,8);
|
||||||
|
|
||||||
static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, unsigned budget, ec_enc *enc)
|
int *quant_prob_alloc(const CELTMode *m)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int *prob;
|
||||||
|
prob = celt_alloc(2*m->nbEBands*sizeof(int));
|
||||||
|
for (i=0;i<m->nbEBands;i++)
|
||||||
|
{
|
||||||
|
prob[2*i] = 6000-i*200;
|
||||||
|
prob[2*i+1] = ec_laplace_get_start_freq(prob[2*i]);
|
||||||
|
}
|
||||||
|
return prob;
|
||||||
|
}
|
||||||
|
|
||||||
|
void quant_prob_free(int *freq)
|
||||||
|
{
|
||||||
|
celt_free(freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, unsigned budget, int *prob, ec_enc *enc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned bits;
|
unsigned bits;
|
||||||
|
@ -163,7 +181,7 @@ static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word1
|
||||||
if (ec_enc_tell(enc, 0) - bits > budget)
|
if (ec_enc_tell(enc, 0) - bits > budget)
|
||||||
qi = -1;
|
qi = -1;
|
||||||
else
|
else
|
||||||
ec_laplace_encode(enc, qi, 6000-i*200);
|
ec_laplace_encode_start(enc, qi, prob[2*i], prob[2*i+1]);
|
||||||
q = qi*base_resolution;
|
q = qi*base_resolution;
|
||||||
error[i] = f - SHL16(qi,8);
|
error[i] = f - SHL16(qi,8);
|
||||||
|
|
||||||
|
@ -202,7 +220,7 @@ static void quant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word1
|
||||||
RESTORE_STACK;
|
RESTORE_STACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, unsigned budget, ec_dec *dec)
|
static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, unsigned budget, int *prob, ec_dec *dec)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned bits;
|
unsigned bits;
|
||||||
|
@ -222,7 +240,7 @@ static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_wor
|
||||||
if (ec_dec_tell(dec, 0) - bits > budget)
|
if (ec_dec_tell(dec, 0) - bits > budget)
|
||||||
qi = -1;
|
qi = -1;
|
||||||
else
|
else
|
||||||
qi = ec_laplace_decode(dec, 6000-i*200);
|
qi = ec_laplace_decode_start(dec, prob[2*i], prob[2*i+1]);
|
||||||
q = qi*base_resolution;
|
q = qi*base_resolution;
|
||||||
|
|
||||||
oldEBands[i] = mean+MULT16_16_Q15(coef,oldEBands[i])+prev+q;
|
oldEBands[i] = mean+MULT16_16_Q15(coef,oldEBands[i])+prev+q;
|
||||||
|
@ -249,7 +267,7 @@ static void unquant_energy_mono(const CELTMode *m, celt_ener_t *eBands, celt_wor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_enc *enc)
|
void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int *prob, ec_enc *enc)
|
||||||
{
|
{
|
||||||
int C;
|
int C;
|
||||||
SAVE_STACK;
|
SAVE_STACK;
|
||||||
|
@ -257,7 +275,7 @@ void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBan
|
||||||
C = m->nbChannels;
|
C = m->nbChannels;
|
||||||
|
|
||||||
if (C==1)
|
if (C==1)
|
||||||
quant_energy_mono(m, eBands, oldEBands, budget, enc);
|
quant_energy_mono(m, eBands, oldEBands, budget, prob, enc);
|
||||||
else
|
else
|
||||||
#if 1
|
#if 1
|
||||||
{
|
{
|
||||||
|
@ -269,7 +287,7 @@ void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBan
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<m->nbEBands;i++)
|
for (i=0;i<m->nbEBands;i++)
|
||||||
E[i] = eBands[C*i+c];
|
E[i] = eBands[C*i+c];
|
||||||
quant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, enc);
|
quant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, prob, enc);
|
||||||
for (i=0;i<m->nbEBands;i++)
|
for (i=0;i<m->nbEBands;i++)
|
||||||
eBands[C*i+c] = E[i];
|
eBands[C*i+c] = E[i];
|
||||||
}
|
}
|
||||||
|
@ -311,14 +329,14 @@ void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBan
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void unquant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_dec *dec)
|
void unquant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int *prob, ec_dec *dec)
|
||||||
{
|
{
|
||||||
int C;
|
int C;
|
||||||
SAVE_STACK;
|
SAVE_STACK;
|
||||||
C = m->nbChannels;
|
C = m->nbChannels;
|
||||||
|
|
||||||
if (C==1)
|
if (C==1)
|
||||||
unquant_energy_mono(m, eBands, oldEBands, budget, dec);
|
unquant_energy_mono(m, eBands, oldEBands, budget, prob, dec);
|
||||||
else {
|
else {
|
||||||
int c;
|
int c;
|
||||||
VARDECL(celt_ener_t, E);
|
VARDECL(celt_ener_t, E);
|
||||||
|
@ -326,7 +344,7 @@ void unquant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEB
|
||||||
for (c=0;c<C;c++)
|
for (c=0;c<C;c++)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unquant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, dec);
|
unquant_energy_mono(m, E, oldEBands+c*m->nbEBands, budget/C, prob, dec);
|
||||||
for (i=0;i<m->nbEBands;i++)
|
for (i=0;i<m->nbEBands;i++)
|
||||||
eBands[C*i+c] = E[i];
|
eBands[C*i+c] = E[i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,11 @@
|
||||||
#include "entenc.h"
|
#include "entenc.h"
|
||||||
#include "entdec.h"
|
#include "entdec.h"
|
||||||
|
|
||||||
void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_enc *enc);
|
int *quant_prob_alloc(const CELTMode *m);
|
||||||
|
void quant_prob_free(int *freq);
|
||||||
|
|
||||||
void unquant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, ec_dec *dec);
|
void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int *prob, ec_enc *enc);
|
||||||
|
|
||||||
|
void unquant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int *prob, ec_dec *dec);
|
||||||
|
|
||||||
#endif /* QUANT_BANDS */
|
#endif /* QUANT_BANDS */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue