shithub: opus

Download patch

ref: bf2398b0490acfab8bbd8472c9d2fae6de96b61e
parent: 6a9780228032bcc7c7b701df6d156e194c05b099
author: Jean-Marc Valin <[email protected]>
date: Thu Oct 15 03:28:19 EDT 2009

first step for removing the number of channels from the mode

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -43,17 +43,14 @@
 #include "mathops.h"
 #include "rate.h"
 
-const celt_word16_t sqrtC_1[2] = {QCONST16(1.f, 14), QCONST16(1.414214f, 14)};
 
-
-
 #ifdef FIXED_POINT
 /* Compute the amplitude (sqrt energy) in each of the bands */
-void compute_band_energies(const CELTMode *m, const celt_sig_t *X, celt_ener_t *bank)
+void compute_band_energies(const CELTMode *m, const celt_sig_t *X, celt_ener_t *bank, int _C)
 {
    int i, c, N;
    const celt_int16_t *eBands = m->eBands;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    N = FRAMESIZE(m);
    for (c=0;c<C;c++)
    {
@@ -88,11 +85,11 @@
 }
 
 /* Normalise each band such that the energy is one. */
-void normalise_bands(const CELTMode *m, const celt_sig_t * restrict freq, celt_norm_t * restrict X, const celt_ener_t *bank)
+void normalise_bands(const CELTMode *m, const celt_sig_t * restrict freq, celt_norm_t * restrict X, const celt_ener_t *bank, int _C)
 {
    int i, c, N;
    const celt_int16_t *eBands = m->eBands;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    N = FRAMESIZE(m);
    for (c=0;c<C;c++)
    {
@@ -112,11 +109,11 @@
 
 #else /* FIXED_POINT */
 /* Compute the amplitude (sqrt energy) in each of the bands */
-void compute_band_energies(const CELTMode *m, const celt_sig_t *X, celt_ener_t *bank)
+void compute_band_energies(const CELTMode *m, const celt_sig_t *X, celt_ener_t *bank, int _C)
 {
    int i, c, N;
    const celt_int16_t *eBands = m->eBands;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    N = FRAMESIZE(m);
    for (c=0;c<C;c++)
    {
@@ -134,11 +131,11 @@
 }
 
 #ifdef EXP_PSY
-void compute_noise_energies(const CELTMode *m, const celt_sig_t *X, const celt_word16_t *tonality, celt_ener_t *bank)
+void compute_noise_energies(const CELTMode *m, const celt_sig_t *X, const celt_word16_t *tonality, celt_ener_t *bank, int _C)
 {
    int i, c, N;
    const celt_int16_t *eBands = m->eBands;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    N = FRAMESIZE(m);
    for (c=0;c<C;c++)
    {
@@ -157,11 +154,11 @@
 #endif
 
 /* Normalise each band such that the energy is one. */
-void normalise_bands(const CELTMode *m, const celt_sig_t * restrict freq, celt_norm_t * restrict X, const celt_ener_t *bank)
+void normalise_bands(const CELTMode *m, const celt_sig_t * restrict freq, celt_norm_t * restrict X, const celt_ener_t *bank, int _C)
 {
    int i, c, N;
    const celt_int16_t *eBands = m->eBands;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    N = FRAMESIZE(m);
    for (c=0;c<C;c++)
    {
@@ -177,11 +174,11 @@
 
 #endif /* FIXED_POINT */
 
-void renormalise_bands(const CELTMode *m, celt_norm_t * restrict X)
+void renormalise_bands(const CELTMode *m, celt_norm_t * restrict X, int _C)
 {
    int i, c;
    const celt_int16_t *eBands = m->eBands;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    for (c=0;c<C;c++)
    {
       i=0; do {
@@ -191,11 +188,11 @@
 }
 
 /* De-normalise the energy to produce the synthesis from the unit-energy bands */
-void denormalise_bands(const CELTMode *m, const celt_norm_t * restrict X, celt_sig_t * restrict freq, const celt_ener_t *bank)
+void denormalise_bands(const CELTMode *m, const celt_norm_t * restrict X, celt_sig_t * restrict freq, const celt_ener_t *bank, int _C)
 {
    int i, c, N;
    const celt_int16_t *eBands = m->eBands;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    N = FRAMESIZE(m);
    if (C>2)
       celt_fatal("denormalise_bands() not implemented for >2 channels");
@@ -214,12 +211,12 @@
    }
 }
 
-int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *P, int norm_rate, int *gain_id)
+int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *P, int norm_rate, int *gain_id, int _C)
 {
    int j, c;
    celt_word16_t g;
    celt_word16_t delta;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    celt_word32_t Sxy=0, Sxx=0, Syy=0;
    int len = m->pitchEnd;
    const int N = FRAMESIZE(m);
@@ -295,12 +292,12 @@
    }
 }
 
-void apply_pitch(const CELTMode *m, celt_sig_t *X, const celt_sig_t *P, int gain_id, int pred)
+void apply_pitch(const CELTMode *m, celt_sig_t *X, const celt_sig_t *P, int gain_id, int pred, int _C)
 {
    int j, c, N;
    celt_word16_t gain;
    celt_word16_t delta;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    int len = m->pitchEnd;
 
    N = FRAMESIZE(m);
@@ -359,12 +356,12 @@
 
 #endif /* DISABLE_STEREO */
 
-int folding_decision(const CELTMode *m, celt_norm_t *X, celt_word16_t *average, int *last_decision)
+int folding_decision(const CELTMode *m, celt_norm_t *X, celt_word16_t *average, int *last_decision, int _C)
 {
    int i, c, N0;
    int NR=0;
    celt_word32_t ratio = EPSILON;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    const celt_int16_t * restrict eBands = m->eBands;
    
    N0 = FRAMESIZE(m);
--- a/libcelt/bands.h
+++ b/libcelt/bands.h
@@ -43,9 +43,9 @@
  * @param X Spectrum
  * @param bands Square root of the energy for each band (returned)
  */
-void compute_band_energies(const CELTMode *m, const celt_sig_t *X, celt_ener_t *bands);
+void compute_band_energies(const CELTMode *m, const celt_sig_t *X, celt_ener_t *bands, int _C);
 
-void compute_noise_energies(const CELTMode *m, const celt_sig_t *X, const celt_word16_t *tonality, celt_ener_t *bank);
+/*void compute_noise_energies(const CELTMode *m, const celt_sig_t *X, const celt_word16_t *tonality, celt_ener_t *bank);*/
 
 /** Normalise each band of X such that the energy in each band is 
     equal to 1
@@ -53,9 +53,9 @@
  * @param X Spectrum (returned normalised)
  * @param bands Square root of the energy for each band
  */
-void normalise_bands(const CELTMode *m, const celt_sig_t * restrict freq, celt_norm_t * restrict X, const celt_ener_t *bands);
+void normalise_bands(const CELTMode *m, const celt_sig_t * restrict freq, celt_norm_t * restrict X, const celt_ener_t *bands, int _C);
 
-void renormalise_bands(const CELTMode *m, celt_norm_t * restrict X);
+void renormalise_bands(const CELTMode *m, celt_norm_t * restrict X, int _C);
 
 /** Denormalise each band of X to restore full amplitude
  * @param m Mode data 
@@ -62,7 +62,7 @@
  * @param X Spectrum (returned de-normalised)
  * @param bands Square root of the energy for each band
  */
-void denormalise_bands(const CELTMode *m, const celt_norm_t * restrict X, celt_sig_t * restrict freq, const celt_ener_t *bands);
+void denormalise_bands(const CELTMode *m, const celt_norm_t * restrict X, celt_sig_t * restrict freq, const celt_ener_t *bands, int _C);
 
 /** Compute the pitch predictor gain for each pitch band
  * @param m Mode data 
@@ -71,11 +71,11 @@
  * @param gains Gain computed for each pitch band (returned)
  * @param bank Square root of the energy for each band
  */
-int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *P, int norm_rate, int *gain_id);
+int compute_pitch_gain(const CELTMode *m, const celt_sig_t *X, const celt_sig_t *P, int norm_rate, int *gain_id, int _C);
 
-void apply_pitch(const CELTMode *m, celt_sig_t *X, const celt_sig_t *P, int gain_id, int pred);
+void apply_pitch(const CELTMode *m, celt_sig_t *X, const celt_sig_t *P, int gain_id, int pred, int _C);
 
-int folding_decision(const CELTMode *m, celt_norm_t *X, celt_word16_t *average, int *last_decision);
+int folding_decision(const CELTMode *m, celt_norm_t *X, celt_word16_t *average, int *last_decision, int _C);
 
 /** Quantisation/encoding of the residual spectrum
  * @param m Mode data 
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -284,9 +284,9 @@
 
 /** Apply window and compute the MDCT for all sub-frames and 
     all channels in a frame */
-static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t * restrict in, celt_sig_t * restrict out)
+static void compute_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t * restrict in, celt_sig_t * restrict out, int _C)
 {
-   const int C = CHANNELS(mode);
+   const int C = CHANNELS(_C);
    if (C==1 && !shortBlocks)
    {
       const mdct_lookup *lookup = MDCT(mode);
@@ -328,10 +328,10 @@
 
 /** Compute the IMDCT and apply window for all sub-frames and 
     all channels in a frame */
-static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t *X, int transient_time, int transient_shift, celt_sig_t * restrict out_mem)
+static void compute_inv_mdcts(const CELTMode *mode, int shortBlocks, celt_sig_t *X, int transient_time, int transient_shift, celt_sig_t * restrict out_mem, int _C)
 {
    int c, N4;
-   const int C = CHANNELS(mode);
+   const int C = CHANNELS(_C);
    const int N = FRAMESIZE(mode);
    const int overlap = OVERLAP(mode);
    N4 = (N-overlap)>>1;
@@ -461,8 +461,9 @@
    /*printf ("dec %d: %d %d %d %d\n", flag_bits, *intra_ener, *has_pitch, *shortBlocks, *has_fold);*/
 }
 
-static void deemphasis(celt_sig_t *in, celt_word16_t *pcm, int N, int C, celt_word16_t coef, celt_sig_t *mem)
+static void deemphasis(celt_sig_t *in, celt_word16_t *pcm, int N, int _C, celt_word16_t coef, celt_sig_t *mem)
 {
+   const int C = CHANNELS(_C);
    int c;
    for (c=0;c<C;c++)
    {
@@ -478,10 +479,10 @@
 
 }
 
-static void mdct_shape(const CELTMode *mode, celt_norm_t *X, int start, int end, int N, int nbShortMdcts, int mdct_weight_shift)
+static void mdct_shape(const CELTMode *mode, celt_norm_t *X, int start, int end, int N, int nbShortMdcts, int mdct_weight_shift, int _C)
 {
    int m, i, c;
-   const int C = CHANNELS(mode);
+   const int C = CHANNELS(_C);
    for (c=0;c<C;c++)
       for (m=start;m<end;m++)
          for (i=m+c*N;i<(c+1)*N;i+=nbShortMdcts)
@@ -490,7 +491,7 @@
 #else
             X[i] = (1.f/(1<<mdct_weight_shift))*X[i];
 #endif
-   renormalise_bands(mode, X);
+   renormalise_bands(mode, X, C);
 }
 
 
@@ -524,7 +525,7 @@
    int shortBlocks=0;
    int transient_time;
    int transient_shift;
-   const int C = CHANNELS(st->mode);
+   const int C = MCHANNELS(st->mode);
    int mdct_weight_shift = 0;
    int mdct_weight_pos=0;
    int gain_id=0;
@@ -605,7 +606,7 @@
    ALLOC(bandE,st->mode->nbEBands*C, celt_ener_t);
    ALLOC(bandLogE,st->mode->nbEBands*C, celt_word16_t);
    /* Compute MDCTs */
-   compute_mdcts(st->mode, shortBlocks, in, freq);
+   compute_mdcts(st->mode, shortBlocks, in, freq, C);
 
 
    norm_rate = (nbCompressedBytes-5)*8*(celt_uint32_t)st->mode->Fs/(C*N)>>10;
@@ -617,7 +618,7 @@
             && norm_rate < 50;
    if (has_pitch)
    {
-      find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, NULL, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index);
+      find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, in, st->out_mem, st->mode->window, NULL, 2*N-2*N4, MAX_PERIOD-(2*N-2*N4), &pitch_index, C);
    }
 
    /* Deferred allocation after find_spectral_pitch() to reduce 
@@ -628,20 +629,20 @@
    if (has_pitch)
    {
       
-      compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq);
-      has_pitch = compute_pitch_gain(st->mode, freq, pitch_freq, norm_rate, &gain_id);
+      compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
+      has_pitch = compute_pitch_gain(st->mode, freq, pitch_freq, norm_rate, &gain_id, C);
    }
    
    if (has_pitch)
-      apply_pitch(st->mode, freq, pitch_freq, gain_id, 1);
+      apply_pitch(st->mode, freq, pitch_freq, gain_id, 1, C);
 
-   compute_band_energies(st->mode, freq, bandE);
+   compute_band_energies(st->mode, freq, bandE, C);
    for (i=0;i<st->mode->nbEBands*C;i++)
       bandLogE[i] = amp2Log(bandE[i]);
    
    /* Band normalisation */
-   normalise_bands(st->mode, freq, X, bandE);
-   if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision))
+   normalise_bands(st->mode, freq, X, bandE, C);
+   if (!shortBlocks && !folding_decision(st->mode, X, &st->tonal_average, &st->fold_decision, C))
       has_fold = 0;
 
    /* Don't use intra energy when we're operating at low bit-rate */
@@ -696,8 +697,8 @@
 #endif
       if (mdct_weight_shift)
       {
-         mdct_shape(st->mode, X, mdct_weight_pos+1, st->mode->nbShortMdcts, N, st->mode->nbShortMdcts, mdct_weight_shift);
-         renormalise_bands(st->mode, X);
+         mdct_shape(st->mode, X, mdct_weight_pos+1, st->mode->nbShortMdcts, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
+         renormalise_bands(st->mode, X, C);
       }
    }
 
@@ -726,7 +727,7 @@
 
    /* Bit allocation */
    ALLOC(error, C*st->mode->nbEBands, celt_word16_t);
-   coarse_needed = quant_coarse_energy(st->mode, bandLogE, st->oldBandE, nbCompressedBytes*8/3, intra_ener, st->mode->prob, error, &enc);
+   coarse_needed = quant_coarse_energy(st->mode, bandLogE, st->oldBandE, nbCompressedBytes*8/3, intra_ener, st->mode->prob, error, &enc, C);
    coarse_needed = ((coarse_needed*3-1)>>3)+1;
 
    /* Variable bitrate */
@@ -758,9 +759,9 @@
    for (i=0;i<st->mode->nbEBands;i++)
       offsets[i] = 0;
    bits = nbCompressedBytes*8 - ec_enc_tell(&enc, 0) - 1;
-   compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority);
+   compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
 
-   quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &enc);
+   quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &enc, C);
 
    /* Residual quantisation */
    if (C==1)
@@ -770,7 +771,7 @@
       quant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, &enc);
 #endif
 
-   quant_energy_finalise(st->mode, bandE, st->oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(&enc, 0), &enc);
+   quant_energy_finalise(st->mode, bandE, st->oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_enc_tell(&enc, 0), &enc, C);
 
    /* Re-synthesis of the coded audio if required */
    if (st->pitch_available>0 || optional_synthesis!=NULL)
@@ -780,18 +781,18 @@
 
       if (mdct_weight_shift)
       {
-         mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, st->mode->nbShortMdcts, mdct_weight_shift);
+         mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
       }
 
       /* Synthesis */
-      denormalise_bands(st->mode, X, freq, bandE);
+      denormalise_bands(st->mode, X, freq, bandE, C);
 
       CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->overlap-N));
 
       if (has_pitch)
-         apply_pitch(st->mode, freq, pitch_freq, gain_id, 0);
+         apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
       
-      compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem);
+      compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
 
       /* De-emphasis and put everything back at the right place 
          in the synthesis history */
@@ -824,7 +825,7 @@
    if (pcm==NULL)
       return CELT_BAD_ARG;
 
-   C = CHANNELS(st->mode);
+   C = MCHANNELS(st->mode);
    N = st->block_size;
    ALLOC(in, C*N, celt_int16_t);
 
@@ -859,7 +860,7 @@
    if (pcm==NULL)
       return CELT_BAD_ARG;
 
-   C=CHANNELS(st->mode);
+   C=MCHANNELS(st->mode);
    N=st->block_size;
    ALLOC(in, C*N, celt_sig_t);
    for (j=0;j<C*N;j++) {
@@ -1039,7 +1040,7 @@
       return NULL;
 
    N = mode->mdctSize;
-   C = CHANNELS(mode);
+   C = MCHANNELS(mode);
    st = celt_alloc(sizeof(CELTDecoder));
 
    if (st==NULL)
@@ -1118,7 +1119,7 @@
    celt_word16_t fade = Q15ONE;
    int i, len;
    VARDECL(celt_sig_t, freq);
-   const int C = CHANNELS(st->mode);
+   const int C = MCHANNELS(st->mode);
    int offset;
    SAVE_STACK;
    N = st->block_size;
@@ -1128,7 +1129,7 @@
    
    if (st->loss_count == 0)
    {
-      find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, NULL, len, MAX_PERIOD-len-100, &pitch_index);
+      find_spectral_pitch(st->mode, st->mode->fft, &st->mode->psy, st->out_mem+MAX_PERIOD-len, st->out_mem, st->mode->window, NULL, len, MAX_PERIOD-len-100, &pitch_index, C);
       pitch_index = MAX_PERIOD-len-pitch_index;
       st->last_pitch_index = pitch_index;
    } else {
@@ -1142,13 +1143,13 @@
    offset = MAX_PERIOD-pitch_index;
    while (offset+len >= MAX_PERIOD)
       offset -= pitch_index;
-   compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq);
+   compute_mdcts(st->mode, 0, st->out_mem+offset*C, freq, C);
    for (i=0;i<C*N;i++)
       freq[i] = ADD32(VERY_SMALL, MULT16_32_Q15(fade,freq[i]));
 
    CELT_MOVE(st->out_mem, st->out_mem+C*N, C*(MAX_PERIOD+st->mode->overlap-N));
    /* Compute inverse MDCTs */
-   compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem);
+   compute_inv_mdcts(st->mode, 0, freq, -1, 0, st->out_mem, C);
 
    for (c=0;c<C;c++)
    {
@@ -1195,7 +1196,7 @@
    int transient_time;
    int transient_shift;
    int mdct_weight_shift=0;
-   const int C = CHANNELS(st->mode);
+   const int C = MCHANNELS(st->mode);
    int mdct_weight_pos=0;
    int gain_id=0;
    SAVE_STACK;
@@ -1261,7 +1262,7 @@
 
    ALLOC(fine_quant, st->mode->nbEBands, int);
    /* Get band energies */
-   unquant_coarse_energy(st->mode, bandE, st->oldBandE, len*8/3, intra_ener, st->mode->prob, &dec);
+   unquant_coarse_energy(st->mode, bandE, st->oldBandE, len*8/3, intra_ener, st->mode->prob, &dec, C);
    
    ALLOC(pulses, st->mode->nbEBands, int);
    ALLOC(offsets, st->mode->nbEBands, int);
@@ -1271,17 +1272,17 @@
       offsets[i] = 0;
 
    bits = len*8 - ec_dec_tell(&dec, 0) - 1;
-   compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority);
+   compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
    /*bits = ec_dec_tell(&dec, 0);
    compute_fine_allocation(st->mode, fine_quant, (20*C+len*8/5-(ec_dec_tell(&dec, 0)-bits))/C);*/
    
-   unquant_fine_energy(st->mode, bandE, st->oldBandE, fine_quant, &dec);
+   unquant_fine_energy(st->mode, bandE, st->oldBandE, fine_quant, &dec, C);
 
    ALLOC(pitch_freq, C*N, celt_sig_t); /**< Interleaved signal MDCTs */
    if (has_pitch) 
    {
       /* Pitch MDCT */
-      compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq);
+      compute_mdcts(st->mode, 0, st->out_mem+pitch_index*C, pitch_freq, C);
    }
 
    /* Decode fixed codebook and merge with pitch */
@@ -1291,24 +1292,24 @@
    else
       unquant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, &dec);
 #endif
-   unquant_energy_finalise(st->mode, bandE, st->oldBandE, fine_quant, fine_priority, len*8-ec_dec_tell(&dec, 0), &dec);
+   unquant_energy_finalise(st->mode, bandE, st->oldBandE, fine_quant, fine_priority, len*8-ec_dec_tell(&dec, 0), &dec, C);
    
    if (mdct_weight_shift)
    {
-      mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, st->mode->nbShortMdcts, mdct_weight_shift);
+      mdct_shape(st->mode, X, 0, mdct_weight_pos+1, N, st->mode->nbShortMdcts, mdct_weight_shift, C);
    }
 
    /* Synthesis */
-   denormalise_bands(st->mode, X, freq, bandE);
+   denormalise_bands(st->mode, X, freq, bandE, C);
 
 
    CELT_MOVE(st->decode_mem, st->decode_mem+C*N, C*(DECODE_BUFFER_SIZE+st->overlap-N));
 
    if (has_pitch)
-      apply_pitch(st->mode, freq, pitch_freq, gain_id, 0);
+      apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
 
    /* Compute inverse MDCTs */
-   compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem);
+   compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
 
    deemphasis(st->out_mem, pcm, N, C, preemph, st->preemph_memD);
 
@@ -1333,7 +1334,7 @@
    if (pcm==NULL)
       return CELT_BAD_ARG;
 
-   C = CHANNELS(st->mode);
+   C = MCHANNELS(st->mode);
    N = st->block_size;
    
    ALLOC(out, C*N, celt_int16_t);
@@ -1361,7 +1362,7 @@
    if (pcm==NULL)
       return CELT_BAD_ARG;
 
-   C = CHANNELS(st->mode);
+   C = MCHANNELS(st->mode);
    N = st->block_size;
    ALLOC(out, C*N, celt_sig_t);
 
--- a/libcelt/modes.h
+++ b/libcelt/modes.h
@@ -47,11 +47,19 @@
 
 #define MAX_PERIOD 1024
 
+#ifndef MCHANNELS
+# ifdef DISABLE_STEREO
+#  define MCHANNELS(mode) (1)
+# else
+#  define MCHANNELS(mode) ((mode)->nbChannels)
+# endif
+#endif
+
 #ifndef CHANNELS
 # ifdef DISABLE_STEREO
-#  define CHANNELS(mode) (1)
+#  define CHANNELS(_C) (1)
 # else
-#  define CHANNELS(mode) ((mode)->nbChannels)
+#  define CHANNELS(_C) (_C)
 # endif
 #endif
 
--- a/libcelt/pitch.c
+++ b/libcelt/pitch.c
@@ -104,7 +104,7 @@
 
 #define INPUT_SHIFT 15
 
-void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t * restrict x, const celt_sig_t * restrict y, const celt_word16_t * restrict window, celt_word16_t * restrict spectrum, int len, int max_pitch, int *pitch)
+void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t * restrict x, const celt_sig_t * restrict y, const celt_word16_t * restrict window, celt_word16_t * restrict spectrum, int len, int max_pitch, int *pitch, int _C)
 {
    int c, i;
    VARDECL(celt_word16_t, _X);
@@ -118,7 +118,7 @@
    const celt_sig_t * restrict yptr;
    int n2;
    int L2;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    const int overlap = OVERLAP(m);
    const int lag = MAX_PERIOD;
    SAVE_STACK;
--- a/libcelt/pitch.h
+++ b/libcelt/pitch.h
@@ -48,6 +48,6 @@
 /** Find the optimal delay for the pitch prediction. Computation is
     done in the frequency domain, both to save time and to make it
     easier to apply psychoacoustic weighting */
-void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t *x, const celt_sig_t *y, const celt_word16_t *window, celt_word16_t * restrict X, int len, int max_pitch, int *pitch);
+void find_spectral_pitch(const CELTMode *m, kiss_fftr_cfg fft, const struct PsyDecay *decay, const celt_sig_t *x, const celt_sig_t *y, const celt_word16_t *window, celt_word16_t * restrict X, int len, int max_pitch, int *pitch, int _C);
 
 #endif
--- a/libcelt/quant_bands.c
+++ b/libcelt/quant_bands.c
@@ -47,6 +47,7 @@
 const celt_word16_t eMeans[24] = {7.5f, -1.33f, -2.f, -0.42f, 0.17f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
 #endif
 
+/* FIXME: Implement for stereo */
 int intra_decision(celt_word16_t *eBands, celt_word16_t *oldEBands, int len)
 {
    int i;
@@ -84,7 +85,7 @@
    celt_free(freq);
 }
 
-unsigned quant_coarse_energy(const CELTMode *m, celt_word16_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, celt_word16_t *error, ec_enc *enc)
+unsigned quant_coarse_energy(const CELTMode *m, celt_word16_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, celt_word16_t *error, ec_enc *enc, int _C)
 {
    int i, c;
    unsigned bits;
@@ -92,7 +93,7 @@
    celt_word16_t prev[2] = {0,0};
    celt_word16_t coef = m->ePredCoef;
    celt_word16_t beta;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
 
    if (intra)
    {
@@ -143,10 +144,10 @@
    return bits_used;
 }
 
-void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc)
+void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc, int _C)
 {
    int i, c;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
 
    /* Encode finer resolution */
    for (i=0;i<m->nbEBands;i++)
@@ -182,10 +183,10 @@
       eBands[i] = log2Amp(oldEBands[i]);
 }
 
-void quant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc)
+void quant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int _C)
 {
    int i, prio, c;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
 
    /* Use up the remaining bits */
    for (prio=0;prio<2;prio++)
@@ -218,7 +219,7 @@
    }
 }
 
-void unquant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, ec_dec *dec)
+void unquant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, ec_dec *dec, int _C)
 {
    int i, c;
    unsigned bits;
@@ -225,7 +226,7 @@
    celt_word16_t prev[2] = {0, 0};
    celt_word16_t coef = m->ePredCoef;
    celt_word16_t beta;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
 
    if (intra)
    {
@@ -258,10 +259,10 @@
    }
 }
 
-void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec)
+void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec, int _C)
 {
    int i, c;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    /* Decode finer resolution */
    for (i=0;i<m->nbEBands;i++)
    {
@@ -284,10 +285,10 @@
       eBands[i] = log2Amp(oldEBands[i]);
 }
 
-void unquant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant,  int *fine_priority, int bits_left, ec_dec *dec)
+void unquant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant,  int *fine_priority, int bits_left, ec_dec *dec, int _C)
 {
    int i, prio, c;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
 
    /* Use up the remaining bits */
    for (prio=0;prio<2;prio++)
--- a/libcelt/quant_bands.h
+++ b/libcelt/quant_bands.h
@@ -55,16 +55,16 @@
 
 int intra_decision(celt_word16_t *eBands, celt_word16_t *oldEBands, int len);
 
-unsigned quant_coarse_energy(const CELTMode *m, celt_word16_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, celt_word16_t *error, ec_enc *enc);
+unsigned quant_coarse_energy(const CELTMode *m, celt_word16_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, celt_word16_t *error, ec_enc *enc, int _C);
 
-void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc);
+void quant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, ec_enc *enc, int _C);
 
-void quant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc);
+void quant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, celt_word16_t *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int _C);
 
-void unquant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, ec_dec *dec);
+void unquant_coarse_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int budget, int intra, int *prob, ec_dec *dec, int _C);
 
-void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec);
+void unquant_fine_energy(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, ec_dec *dec, int _C);
 
-void unquant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec);
+void unquant_energy_finalise(const CELTMode *m, celt_ener_t *eBands, celt_word16_t *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int _C);
 
 #endif /* QUANT_BANDS */
--- a/libcelt/rate.c
+++ b/libcelt/rate.c
@@ -101,12 +101,12 @@
 
 
 
-static void interp_bits2pulses(const CELTMode *m, int *bits1, int *bits2, int total, int *bits, int *ebits, int *fine_priority, int len)
+static void interp_bits2pulses(const CELTMode *m, int *bits1, int *bits2, int total, int *bits, int *ebits, int *fine_priority, int len, int _C)
 {
    int psum;
    int lo, hi;
    int j;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    SAVE_STACK;
    lo = 0;
    hi = 1<<BITRES;
@@ -172,10 +172,10 @@
    RESTORE_STACK;
 }
 
-void compute_allocation(const CELTMode *m, int *offsets, int total, int *pulses, int *ebits, int *fine_priority)
+void compute_allocation(const CELTMode *m, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C)
 {
    int lo, hi, len, j;
-   const int C = CHANNELS(m);
+   const int C = CHANNELS(_C);
    VARDECL(int, bits1);
    VARDECL(int, bits2);
    SAVE_STACK;
@@ -215,7 +215,7 @@
       if (bits2[j] < 0)
          bits2[j] = 0;
    }
-   interp_bits2pulses(m, bits1, bits2, total, pulses, ebits, fine_priority, len);
+   interp_bits2pulses(m, bits1, bits2, total, pulses, ebits, fine_priority, len, C);
    RESTORE_STACK;
 }
 
--- a/libcelt/rate.h
+++ b/libcelt/rate.h
@@ -165,7 +165,7 @@
  @param pulses Number of pulses per band (returned)
  @return Total number of bits allocated
 */
-void compute_allocation(const CELTMode *m, int *offsets, int total, int *pulses, int *ebits, int *fine_priority);
+void compute_allocation(const CELTMode *m, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C);
 
 
 #endif