Optimisation: caching the divisions used in the Laplace encoder.
authorJean-Marc Valin <Jean-Marc.Valin@csiro.au>
Wed, 23 Apr 2008 03:42:10 +0000 (13:42 +1000)
committerJean-Marc Valin <Jean-Marc.Valin@csiro.au>
Wed, 23 Apr 2008 03:42:10 +0000 (13:42 +1000)
libcelt/celt.c
libcelt/dump_modes.c
libcelt/laplace.c
libcelt/laplace.h
libcelt/modes.c
libcelt/modes.h
libcelt/pitch.c
libcelt/quant_bands.c
libcelt/quant_bands.h

index cc09c39..a6e4cb0 100644 (file)
@@ -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(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)
    {
@@ -573,7 +573,7 @@ int EXPORT celt_decode(CELTDecoder * restrict st, unsigned char *data, int len,
    ec_dec_init(&dec,&buf);
    
    /* 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 */
    has_pitch = unquant_pitch(gains, st->mode->nbPBands, &dec);
index eeac8e6..86885bd 100644 (file)
@@ -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, "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, "0x%x,\t/* marker */\n", 0xa110ca7e);
       fprintf(file, "};\n");
    }
index 14fd726..b48bfe7 100644 (file)
 
 #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);
 }
 
-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 fl, fs, ft;
+   int fl, ft;
    int s = 0;
    if (value < 0)
    {
@@ -51,7 +51,6 @@ void ec_laplace_encode(ec_enc *enc, int value, int decay)
       value = -value;
    }
    ft = 32767;
-   fs = ec_laplace_get_start_freq(decay);
    fl = -fs;
    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);
 }
 
-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 fl, fh, fs, ft, fm;
+   int fl, fh, ft, fm;
    fl = 0;
    ft = 32767;
-   fs = ec_laplace_get_start_freq(decay);
    fh = fs;
    fm = ec_decode(dec, ft);
    /*DEBUG*/
@@ -113,4 +118,8 @@ int ec_laplace_decode(ec_dec *dec, int decay)
    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);
+}
index faeda67..7220a3f 100644 (file)
@@ -32,6 +32,8 @@
 #include "entenc.h"
 #include "entdec.h"
 
+int ec_laplace_get_start_freq(int decay);
+
 /** Encode a value that is assumed to be the realisation of a
     Laplace-distributed random process
  @param enc Entropy encoder state
@@ -40,6 +42,8 @@
 */
 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
     Laplace-distributed random process
  @param dec Entropy decoder state
@@ -47,3 +51,5 @@ void ec_laplace_encode(ec_enc *enc, int value, int decay);
  @return Value decoded
  */
 int ec_laplace_decode(ec_dec *dec, int decay);
+
+int ec_laplace_decode_start(ec_dec *dec, int decay, int fs);
index c6cbe23..533dc74 100644 (file)
@@ -38,6 +38,7 @@
 #include "rate.h"
 #include "os_support.h"
 #include "stack_alloc.h"
+#include "quant_bands.h"
 
 #ifdef STATIC_MODES
 #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;
 #endif /* !STATIC_MODES */
    mdct_init(&mode->mdct, 2*mode->mdctSize);
+   mode->prob = quant_prob_alloc(mode);
    if (error)
       *error = CELT_OK;
    return mode;
@@ -353,6 +355,7 @@ void EXPORT celt_mode_destroy(CELTMode *mode)
 #endif
 #endif
    mdct_clear(&mode->mdct);
+   quant_prob_free(mode->prob);
    celt_free((CELTMode *)mode);
 }
 
index faa4bfa..fe29f13 100644 (file)
@@ -93,6 +93,8 @@ struct CELTMode {
 
    struct PsyDecay psy;
 
+   int *prob;
+   
    celt_uint32_t marker_end;
 };
 
index 7b5181c..422f1d2 100644 (file)
@@ -115,6 +115,7 @@ void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyD
 #endif
    celt_word16_t * restrict X, * restrict Y;
    celt_word16_t * restrict Xptr, * restrict Yptr;
+   const celt_sig_t * restrict yptr;
    int n2;
    int L2;
    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 */
    ALLOC(_Y, lag, celt_word16_t);
    Y = _Y;
-   CELT_MEMSET(Y,0,lag);
-   /* Sum all channels of the past audio and copy into Y in bit-reverse order */
-   for (c=0;c<C;c++)
+   yptr = &y[0];
+   /* Copy first channel of the past audio into Y in bit-reverse order */
+   for (i=0;i<n2;i++)
+   {
+      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++)
    {
-      const celt_sig_t * restrict yptr = &y[c];
+      yptr = &y[c];
       for (i=0;i<n2;i++)
       {
          Y[2*BITREV(fft,i)] += SHR32(*yptr,INPUT_SHIFT);
index d9d101c..6bd7ca5 100644 (file)
@@ -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 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;
    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)
          qi = -1;
       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;
       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;
 }
 
-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;
    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)
          qi = -1;
       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;
       
       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;
    SAVE_STACK;
@@ -257,7 +275,7 @@ void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBan
    C = m->nbChannels;
 
    if (C==1)
-      quant_energy_mono(m, eBands, oldEBands, budget, enc);
+      quant_energy_mono(m, eBands, oldEBands, budget, prob, enc);
    else 
 #if 1
    {
@@ -269,7 +287,7 @@ void quant_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBan
          int i;
          for (i=0;i<m->nbEBands;i++)
             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++)
             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;   
    SAVE_STACK;
    C = m->nbChannels;
 
    if (C==1)
-      unquant_energy_mono(m, eBands, oldEBands, budget, dec);
+      unquant_energy_mono(m, eBands, oldEBands, budget, prob, dec);
    else {
       int c;
       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++)
       {
          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++)
             eBands[C*i+c] = E[i];
       }
index 3bed486..d3cd201 100644 (file)
 #include "entenc.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 */