shithub: opus

Download patch

ref: 3a0bc3d95c8a844d4f39e793a93567b02131d4a7
parent: 5378bf82530b1d431c34010f693637cb826fbc51
author: Jean-Marc Valin <[email protected]>
date: Sun Feb 21 10:10:22 EST 2010

Allowing CELT to skip the low frequencies

--- a/libcelt/bands.c
+++ b/libcelt/bands.c
@@ -441,7 +441,7 @@
 }
 
 /* Quantisation of the residual */
-void quant_bands(const CELTMode *m, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int shortBlocks, int fold, int total_bits, int encode, void *enc_dec)
+void quant_bands(const CELTMode *m, int start, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int shortBlocks, int fold, int total_bits, int encode, void *enc_dec)
 {
    int i, j, remaining_bits, balance;
    const celt_int16 * restrict eBands = m->eBands;
@@ -455,7 +455,7 @@
    norm = _norm;
 
    balance = 0;
-   for (i=0;i<m->nbEBands;i++)
+   for (i=start;i<m->nbEBands;i++)
    {
       int tell;
       int N;
@@ -501,7 +501,7 @@
          else
             alg_unquant(X+eBands[i], eBands[i+1]-eBands[i], q, spread, enc_dec);
       } else {
-         intra_fold(m, eBands[i+1]-eBands[i], norm, X+eBands[i], eBands[i], B);
+         intra_fold(m, start, eBands[i+1]-eBands[i], norm, X+eBands[i], eBands[i], B);
       }
       for (j=eBands[i];j<eBands[i+1];j++)
          norm[j] = MULT16_16_Q15(n,X[j]);
@@ -511,7 +511,7 @@
 
 #ifndef DISABLE_STEREO
 
-void quant_bands_stereo(const CELTMode *m, celt_norm *_X, const celt_ener *bandE, int *pulses, int shortBlocks, int fold, int total_bits, ec_enc *enc)
+void quant_bands_stereo(const CELTMode *m, int start, celt_norm *_X, const celt_ener *bandE, int *pulses, int shortBlocks, int fold, int total_bits, ec_enc *enc)
 {
    int i, j, remaining_bits, balance;
    const celt_int16 * restrict eBands = m->eBands;
@@ -526,7 +526,7 @@
    norm = _norm;
 
    balance = 0;
-   for (i=0;i<m->nbEBands;i++)
+   for (i=start;i<m->nbEBands;i++)
    {
       int tell;
       int q1, q2;
@@ -705,7 +705,7 @@
             int spread = fold ? B : 0;
             alg_quant(X, N, q1, spread, enc);
          } else {
-            intra_fold(m, eBands[i+1]-eBands[i], norm, X, eBands[i], B);
+            intra_fold(m, start, eBands[i+1]-eBands[i], norm, X, eBands[i], B);
          }
          if (q2 > 0) {
             int spread = fold ? B : 0;
@@ -743,7 +743,7 @@
 
 #ifndef DISABLE_STEREO
 
-void unquant_bands_stereo(const CELTMode *m, celt_norm *_X, const celt_ener *bandE, int *pulses, int shortBlocks, int fold, int total_bits, ec_dec *dec)
+void unquant_bands_stereo(const CELTMode *m, int start, celt_norm *_X, const celt_ener *bandE, int *pulses, int shortBlocks, int fold, int total_bits, ec_dec *dec)
 {
    int i, j, remaining_bits, balance;
    const celt_int16 * restrict eBands = m->eBands;
@@ -758,7 +758,7 @@
    norm = _norm;
 
    balance = 0;
-   for (i=0;i<m->nbEBands;i++)
+   for (i=start;i<m->nbEBands;i++)
    {
       int tell;
       int q1, q2;
@@ -913,7 +913,7 @@
             int spread = fold ? B : 0;
             alg_unquant(X, N, q1, spread, dec);
          } else
-            intra_fold(m, eBands[i+1]-eBands[i], norm, X, eBands[i], B);
+            intra_fold(m, start, eBands[i+1]-eBands[i], norm, X, eBands[i], B);
          if (q2 > 0)
          {
             int spread = fold ? B : 0;
--- a/libcelt/bands.h
+++ b/libcelt/bands.h
@@ -85,9 +85,9 @@
  * @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
  * @param enc Entropy encoder
  */
-void quant_bands(const CELTMode *m, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int time_domain, int fold, int total_bits, int encode, void *enc_dec);
+void quant_bands(const CELTMode *m, int start, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int time_domain, int fold, int total_bits, int encode, void *enc_dec);
 
-void quant_bands_stereo(const CELTMode *m, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int time_domain, int fold, int total_bits, ec_enc *enc);
+void quant_bands_stereo(const CELTMode *m, int start, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int time_domain, int fold, int total_bits, ec_enc *enc);
 
 /** Decoding of the residual spectrum
  * @param m Mode data 
@@ -95,9 +95,7 @@
  * @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
  * @param dec Entropy decoder
 */
-void unquant_bands(const CELTMode *m, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int time_domain, int fold, int total_bits, ec_dec *dec);
-
-void unquant_bands_stereo(const CELTMode *m, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int time_domain, int fold, int total_bits, ec_dec *dec);
+void unquant_bands_stereo(const CELTMode *m, int start, celt_norm * restrict X, const celt_ener *bandE, int *pulses, int time_domain, int fold, int total_bits, ec_dec *dec);
 
 void stereo_decision(const CELTMode *m, celt_norm * restrict X, int *stereo_mode, int len);
 
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -560,6 +560,7 @@
    int mdct_weight_pos=0;
    int gain_id=0;
    int norm_rate;
+   int start=0;
    SAVE_STACK;
 
    if (check_encoder(st) != CELT_OK)
@@ -774,7 +775,7 @@
 
    /* Bit allocation */
    ALLOC(error, C*st->mode->nbEBands, celt_word16);
-   coarse_needed = quant_coarse_energy(st->mode, bandLogE, st->oldBandE, nbCompressedBytes*4-8, intra_ener, st->mode->prob, error, &enc, C);
+   coarse_needed = quant_coarse_energy(st->mode, start, bandLogE, st->oldBandE, nbCompressedBytes*4-8, intra_ener, st->mode->prob, error, &enc, C);
    coarse_needed = ((coarse_needed*3-1)>>3)+1;
    if (coarse_needed > nbCompressedBytes)
       coarse_needed = nbCompressedBytes;
@@ -841,19 +842,19 @@
    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, C);
+   compute_allocation(st->mode, start, offsets, bits, pulses, fine_quant, fine_priority, C);
 
-   quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &enc, C);
+   quant_fine_energy(st->mode, start, bandE, st->oldBandE, error, fine_quant, &enc, C);
 
    /* Residual quantisation */
    if (C==1)
-      quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, 1, &enc);
+      quant_bands(st->mode, start, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, 1, &enc);
 #ifndef DISABLE_STEREO
    else
-      quant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, nbCompressedBytes*8, &enc);
+      quant_bands_stereo(st->mode, start, 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, C);
+   quant_energy_finalise(st->mode, start, 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)
@@ -1433,6 +1434,7 @@
    const int C = CHANNELS(st->channels);
    int mdct_weight_pos=0;
    int gain_id=0;
+   int start=0;
    SAVE_STACK;
 
    if (check_decoder(st) != CELT_OK)
@@ -1494,7 +1496,7 @@
 
    ALLOC(fine_quant, st->mode->nbEBands, int);
    /* Get band energies */
-   unquant_coarse_energy(st->mode, bandE, st->oldBandE, len*4-8, intra_ener, st->mode->prob, &dec, C);
+   unquant_coarse_energy(st->mode, start, bandE, st->oldBandE, len*4-8, intra_ener, st->mode->prob, &dec, C);
    
    ALLOC(pulses, st->mode->nbEBands, int);
    ALLOC(offsets, st->mode->nbEBands, int);
@@ -1504,11 +1506,11 @@
       offsets[i] = 0;
 
    bits = len*8 - ec_dec_tell(&dec, 0) - 1;
-   compute_allocation(st->mode, offsets, bits, pulses, fine_quant, fine_priority, C);
+   compute_allocation(st->mode, start, 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, C);
+   unquant_fine_energy(st->mode, start, bandE, st->oldBandE, fine_quant, &dec, C);
 
    ALLOC(pitch_freq, C*N, celt_sig); /**< Interleaved signal MDCTs */
    if (has_pitch) 
@@ -1519,12 +1521,12 @@
 
    /* Decode fixed codebook and merge with pitch */
    if (C==1)
-      quant_bands(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, 0, &dec);
+      quant_bands(st->mode, start, X, bandE, pulses, shortBlocks, has_fold, len*8, 0, &dec);
 #ifndef DISABLE_STEREO
    else
-      unquant_bands_stereo(st->mode, X, bandE, pulses, shortBlocks, has_fold, len*8, &dec);
+      unquant_bands_stereo(st->mode, start, 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, C);
+   unquant_energy_finalise(st->mode, start, bandE, st->oldBandE, fine_quant, fine_priority, len*8-ec_dec_tell(&dec, 0), &dec, C);
    
    if (mdct_weight_shift)
    {
@@ -1539,6 +1541,9 @@
 
    if (has_pitch)
       apply_pitch(st->mode, freq, pitch_freq, gain_id, 0, C);
+
+   for (i=0;i<st->mode->eBands[start];i++)
+      freq[i] = 0;
 
    /* Compute inverse MDCTs */
    compute_inv_mdcts(st->mode, shortBlocks, freq, transient_time, transient_shift, st->out_mem, C);
--- a/libcelt/quant_bands.c
+++ b/libcelt/quant_bands.c
@@ -88,7 +88,7 @@
    celt_free(freq);
 }
 
-unsigned quant_coarse_energy(const CELTMode *m, celt_word16 *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, celt_word16 *error, ec_enc *enc, int _C)
+unsigned quant_coarse_energy(const CELTMode *m, int start, celt_word16 *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, celt_word16 *error, ec_enc *enc, int _C)
 {
    int i, c;
    unsigned bits_used = 0;
@@ -106,7 +106,7 @@
    beta = MULT16_16_Q15(QCONST16(.8f,15),coef);
 
    /* Encode at a fixed coarse resolution */
-   for (i=0;i<m->nbEBands;i++)
+   for (i=start;i<m->nbEBands;i++)
    {
       c=0;
       do {
@@ -145,13 +145,13 @@
    return bits_used;
 }
 
-void quant_fine_energy(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, ec_enc *enc, int _C)
+void quant_fine_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, ec_enc *enc, int _C)
 {
    int i, c;
    const int C = CHANNELS(_C);
 
    /* Encode finer resolution */
-   for (i=0;i<m->nbEBands;i++)
+   for (i=start;i<m->nbEBands;i++)
    {
       celt_int16 frac = 1<<fine_quant[i];
       if (fine_quant[i] <= 0)
@@ -180,11 +180,11 @@
          /*printf ("%f ", error[i] - offset);*/
       } while (++c < C);
    }
-   for (i=0;i<C*m->nbEBands;i++)
+   for (i=start;i<C*m->nbEBands;i++)
       eBands[i] = log2Amp(oldEBands[i]);
 }
 
-void quant_energy_finalise(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int _C)
+void quant_energy_finalise(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int _C)
 {
    int i, prio, c;
    const int C = CHANNELS(_C);
@@ -192,7 +192,7 @@
    /* Use up the remaining bits */
    for (prio=0;prio<2;prio++)
    {
-      for (i=0;i<m->nbEBands && bits_left>=C ;i++)
+      for (i=start;i<m->nbEBands && bits_left>=C ;i++)
       {
          if (fine_quant[i] >= 7 || fine_priority[i]!=prio)
             continue;
@@ -212,7 +212,7 @@
          } while (++c < C);
       }
    }
-   for (i=0;i<C*m->nbEBands;i++)
+   for (i=start;i<C*m->nbEBands;i++)
    {
       eBands[i] = log2Amp(oldEBands[i]);
       if (oldEBands[i] < -QCONST16(7.f,8))
@@ -220,7 +220,7 @@
    }
 }
 
-void unquant_coarse_energy(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, ec_dec *dec, int _C)
+void unquant_coarse_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, ec_dec *dec, int _C)
 {
    int i, c;
    celt_word16 prev[2] = {0, 0};
@@ -237,7 +237,7 @@
    beta = MULT16_16_Q15(QCONST16(.8f,15),coef);
 
    /* Decode at a fixed coarse resolution */
-   for (i=0;i<m->nbEBands;i++)
+   for (i=start;i<m->nbEBands;i++)
    {
       c=0; 
       do {
@@ -258,12 +258,12 @@
    }
 }
 
-void unquant_fine_energy(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant, ec_dec *dec, int _C)
+void unquant_fine_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant, ec_dec *dec, int _C)
 {
    int i, c;
    const int C = CHANNELS(_C);
    /* Decode finer resolution */
-   for (i=0;i<m->nbEBands;i++)
+   for (i=start;i<m->nbEBands;i++)
    {
       if (fine_quant[i] <= 0)
          continue;
@@ -280,11 +280,11 @@
          oldEBands[i+c*m->nbEBands] += offset;
       } while (++c < C);
    }
-   for (i=0;i<C*m->nbEBands;i++)
+   for (i=start;i<C*m->nbEBands;i++)
       eBands[i] = log2Amp(oldEBands[i]);
 }
 
-void unquant_energy_finalise(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant,  int *fine_priority, int bits_left, ec_dec *dec, int _C)
+void unquant_energy_finalise(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant,  int *fine_priority, int bits_left, ec_dec *dec, int _C)
 {
    int i, prio, c;
    const int C = CHANNELS(_C);
@@ -292,7 +292,7 @@
    /* Use up the remaining bits */
    for (prio=0;prio<2;prio++)
    {
-      for (i=0;i<m->nbEBands && bits_left>=C ;i++)
+      for (i=start;i<m->nbEBands && bits_left>=C ;i++)
       {
          if (fine_quant[i] >= 7 || fine_priority[i]!=prio)
             continue;
@@ -311,7 +311,7 @@
          } while (++c < C);
       }
    }
-   for (i=0;i<C*m->nbEBands;i++)
+   for (i=start;i<C*m->nbEBands;i++)
    {
       eBands[i] = log2Amp(oldEBands[i]);
       if (oldEBands[i] < -QCONST16(7.f,8))
--- a/libcelt/quant_bands.h
+++ b/libcelt/quant_bands.h
@@ -56,16 +56,16 @@
 
 int intra_decision(celt_word16 *eBands, celt_word16 *oldEBands, int len);
 
-unsigned quant_coarse_energy(const CELTMode *m, celt_word16 *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, celt_word16 *error, ec_enc *enc, int _C);
+unsigned quant_coarse_energy(const CELTMode *m, int start, celt_word16 *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, celt_word16 *error, ec_enc *enc, int _C);
 
-void quant_fine_energy(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, ec_enc *enc, int _C);
+void quant_fine_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, ec_enc *enc, int _C);
 
-void quant_energy_finalise(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int _C);
+void quant_energy_finalise(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int _C);
 
-void unquant_coarse_energy(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, ec_dec *dec, int _C);
+void unquant_coarse_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, int budget, int intra, int *prob, ec_dec *dec, int _C);
 
-void unquant_fine_energy(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant, ec_dec *dec, int _C);
+void unquant_fine_energy(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant, ec_dec *dec, int _C);
 
-void unquant_energy_finalise(const CELTMode *m, celt_ener *eBands, celt_word16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int _C);
+void unquant_energy_finalise(const CELTMode *m, int start, celt_ener *eBands, celt_word16 *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
@@ -102,7 +102,7 @@
 
 
 
-static void interp_bits2pulses(const CELTMode *m, int *bits1, int *bits2, int total, int *bits, int *ebits, int *fine_priority, int len, int _C)
+static void interp_bits2pulses(const CELTMode *m, int start, int *bits1, int *bits2, int total, int *bits, int *ebits, int *fine_priority, int len, int _C)
 {
    int psum;
    int lo, hi;
@@ -115,7 +115,7 @@
    {
       int mid = (lo+hi)>>1;
       psum = 0;
-      for (j=0;j<len;j++)
+      for (j=start;j<len;j++)
          psum += ((1<<BITRES)-mid)*bits1[j] + mid*bits2[j];
       if (psum > (total<<BITRES))
          hi = mid;
@@ -124,7 +124,7 @@
    }
    psum = 0;
    /*printf ("interp bisection gave %d\n", lo);*/
-   for (j=0;j<len;j++)
+   for (j=start;j<len;j++)
    {
       bits[j] = ((1<<BITRES)-lo)*bits1[j] + lo*bits2[j];
       psum += bits[j];
@@ -133,14 +133,14 @@
    {
       int left, perband;
       left = (total<<BITRES)-psum;
-      perband = left/len;
-      for (j=0;j<len;j++)
+      perband = left/(len-start);
+      for (j=start;j<len;j++)
          bits[j] += perband;
       left = left-len*perband;
-      for (j=0;j<left;j++)
+      for (j=start;j<start+left;j++)
          bits[j]++;
    }
-   for (j=0;j<len;j++)
+   for (j=start;j<len;j++)
    {
       int N, d;
       int offset;
@@ -173,7 +173,7 @@
    RESTORE_STACK;
 }
 
-void compute_allocation(const CELTMode *m, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C)
+void compute_allocation(const CELTMode *m, int start, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C)
 {
    int lo, hi, len, j;
    const int C = CHANNELS(_C);
@@ -191,7 +191,7 @@
    {
       int psum = 0;
       int mid = (lo+hi) >> 1;
-      for (j=0;j<len;j++)
+      for (j=start;j<len;j++)
       {
          bits1[j] = (C*m->allocVectors[mid*len+j] + offsets[j])<<BITRES;
          if (bits1[j] < 0)
@@ -207,7 +207,7 @@
       /*printf ("lo = %d, hi = %d\n", lo, hi);*/
    }
    /*printf ("interp between %d and %d\n", lo, hi);*/
-   for (j=0;j<len;j++)
+   for (j=start;j<len;j++)
    {
       bits1[j] = C*m->allocVectors[lo*len+j] + offsets[j];
       bits2[j] = C*m->allocVectors[hi*len+j] + offsets[j];
@@ -216,7 +216,7 @@
       if (bits2[j] < 0)
          bits2[j] = 0;
    }
-   interp_bits2pulses(m, bits1, bits2, total, pulses, ebits, fine_priority, len, C);
+   interp_bits2pulses(m, start, bits1, bits2, total, pulses, ebits, fine_priority, len, C);
    RESTORE_STACK;
 }
 
--- a/libcelt/rate.h
+++ b/libcelt/rate.h
@@ -166,7 +166,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, int _C);
+void compute_allocation(const CELTMode *m, int start, int *offsets, int total, int *pulses, int *ebits, int *fine_priority, int _C);
 
 
 #endif
--- a/libcelt/vq.c
+++ b/libcelt/vq.c
@@ -336,10 +336,12 @@
    return rE;
 }
 
-static void fold(const CELTMode *m, int N, const celt_norm * restrict Y, celt_norm * restrict P, int N0, int B)
+static void fold(const CELTMode *m, int start, int N, const celt_norm * restrict Y, celt_norm * restrict P, int N0, int B)
 {
    int j;
    int id = N0 % B;
+   while (id < m->eBands[start])
+      id += B;
    /* Here, we assume that id will never be greater than N0, i.e. that 
       no band is wider than N0. In the unlikely case it happens, we set
       everything to zero */
@@ -361,9 +363,9 @@
          P[j] = Y[id++];
 }
 
-void intra_fold(const CELTMode *m, int N, const celt_norm * restrict Y, celt_norm * restrict P, int N0, int B)
+void intra_fold(const CELTMode *m, int start, int N, const celt_norm * restrict Y, celt_norm * restrict P, int N0, int B)
 {
-   fold(m, N, Y, P, N0, B);
+   fold(m, start, N, Y, P, N0, B);
    renormalise_vector(P, Q15ONE, N, 1);
 }
 
--- a/libcelt/vq.h
+++ b/libcelt/vq.h
@@ -75,6 +75,6 @@
  * @param B Stride (number of channels multiplied by the number of MDCTs per frame)
  * @param N0 Number of valid offsets
  */
-void intra_fold(const CELTMode *m, int N, const celt_norm * restrict Y, celt_norm * restrict P, int N0, int B);
+void intra_fold(const CELTMode *m, int start, int N, const celt_norm * restrict Y, celt_norm * restrict P, int N0, int B);
 
 #endif /* VQ_H */