Eliminate the ec_int32 and ec_uint32 typedefs.
[opus.git] / libcelt / celt.c
index 8c30af9..47697c0 100644 (file)
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
    
-   - Neither the name of the Xiph.org Foundation nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-   
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -104,6 +100,7 @@ struct CELTEncoder {
    int stream_channels;
    
    int force_intra;
+   int clip;
    int disable_pf;
    int complexity;
    int upsample;
@@ -116,7 +113,7 @@ struct CELTEncoder {
    /* Everything beyond this point gets cleared on a reset */
 #define ENCODER_RESET_START rng
 
-   ec_uint32 rng;
+   celt_uint32 rng;
    int spread_decision;
    int delayedIntra;
    int tonal_average;
@@ -230,6 +227,7 @@ CELTEncoder *celt_encoder_init_custom(CELTEncoder *st, const CELTMode *mode, int
    st->start = 0;
    st->end = st->mode->effEBands;
    st->constrained_vbr = 1;
+   st->clip = 1;
 
    st->bitrate = 255000*channels;
    st->vbr = 0;
@@ -319,9 +317,9 @@ static int transient_analysis(const celt_word32 * restrict in, int len, int C,
    for (i=0;i<N;i++)
    {
       int j;
-      float max_abs=0;
+      celt_word16 max_abs=0;
       for (j=0;j<block;j++)
-         max_abs = MAX32(max_abs, tmp[i*block+j]);
+         max_abs = MAX16(max_abs, ABS16(tmp[i*block+j]));
       bins[i] = max_abs;
    }
    for (i=0;i<N;i++)
@@ -689,8 +687,8 @@ static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM,
    int tf_select_rsv;
    int tf_changed;
    int logp;
-   ec_uint32 budget;
-   ec_uint32 tell;
+   celt_uint32 budget;
+   celt_uint32 tell;
    budget = enc->storage*8;
    tell = ec_tell(enc);
    logp = isTransient ? 2 : 4;
@@ -729,8 +727,8 @@ static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM,
    int tf_select_rsv;
    int tf_changed;
    int logp;
-   ec_uint32 budget;
-   ec_uint32 tell;
+   celt_uint32 budget;
+   celt_uint32 tell;
 
    budget = dec->storage*8;
    tell = ec_tell(dec);
@@ -774,7 +772,7 @@ static void init_caps(const CELTMode *m,int *cap,int LM,int C)
 }
 
 static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
-      const celt_word16 *bandLogE, int nbEBands, int LM, int C, int N0)
+      const celt_word16 *bandLogE, int end, int LM, int C, int N0)
 {
    int i;
    celt_word32 diff=0;
@@ -806,12 +804,12 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
 
    /* Estimate spectral tilt */
    c=0; do {
-      for (i=0;i<nbEBands-1;i++)
+      for (i=0;i<end-1;i++)
       {
-         diff += bandLogE[i+c*nbEBands]*(celt_int32)(2+2*i-nbEBands);
+         diff += bandLogE[i+c*m->nbEBands]*(celt_int32)(2+2*i-m->nbEBands);
       }
    } while (++c<0);
-   diff /= C*(nbEBands-1);
+   diff /= C*(end-1);
    /*printf("%f\n", diff);*/
    if (diff > QCONST16(2.f, DB_SHIFT))
       trim_index--;
@@ -870,7 +868,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
 {
 #endif
    int i, c, N;
-   int bits;
+   celt_int32 bits;
    ec_enc _enc;
    VARDECL(celt_sig, in);
    VARDECL(celt_sig, freq);
@@ -922,6 +920,8 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
    if (nbCompressedBytes<2 || pcm==NULL)
      return CELT_BAD_ARG;
 
+   /* Can't produce more than 1275 output bytes */
+   nbCompressedBytes = IMIN(nbCompressedBytes,1275);
    frame_size *= st->upsample;
    for (LM=0;LM<=st->mode->maxLM;LM++)
       if (st->mode->shortMdctSize<<LM==frame_size)
@@ -952,7 +952,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
    {
       celt_int32 den=st->mode->Fs>>BITRES;
       vbr_rate=(st->bitrate*frame_size+(den>>1))/den;
-      effectiveBytes = vbr_rate>>3;
+      effectiveBytes = vbr_rate>>(3+BITRES);
    } else {
       celt_int32 tmp;
       vbr_rate = 0;
@@ -1009,7 +1009,6 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
       VARDECL(celt_sig, _pre);
       celt_sig *pre[2];
       SAVE_STACK;
-      c = 0;
       ALLOC(_pre, CC*(N+COMBFILTER_MAXPERIOD), celt_sig);
 
       pre[0] = _pre;
@@ -1026,6 +1025,10 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
             celt_sig x, tmp;
 
             x = SCALEIN(*pcmp);
+#ifndef FIXED_POINT
+            if (st->clip)
+               x = MAX32(-65536.f, MIN32(65536.f,x));
+#endif
             if (++count==st->upsample)
             {
                count=0;
@@ -1145,11 +1148,17 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
 #endif /* ENABLE_POSTFILTER */
 
       c=0; do {
+         int offset = st->mode->shortMdctSize-st->mode->overlap;
          st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
          CELT_COPY(in+c*(N+st->overlap), st->in_mem+c*(st->overlap), st->overlap);
 #ifdef ENABLE_POSTFILTER
-         comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD,
-               st->prefilter_period, pitch_index, N, -st->prefilter_gain, -gain1,
+         if (offset)
+            comb_filter(in+c*(N+st->overlap)+st->overlap, pre[c]+COMBFILTER_MAXPERIOD,
+                  st->prefilter_period, st->prefilter_period, offset, -st->prefilter_gain, -st->prefilter_gain,
+                  st->prefilter_tapset, st->prefilter_tapset, NULL, 0);
+
+         comb_filter(in+c*(N+st->overlap)+st->overlap+offset, pre[c]+COMBFILTER_MAXPERIOD+offset,
+               st->prefilter_period, pitch_index, N-offset, -st->prefilter_gain, -gain1,
                st->prefilter_tapset, prefilter_tapset, st->mode->window, st->mode->overlap);
 #endif /* ENABLE_POSTFILTER */
          CELT_COPY(st->in_mem+c*(st->overlap), in+c*(N+st->overlap)+N, st->overlap);
@@ -1267,7 +1276,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
          t1 = 2;
          t2 = 4;
       }
-      for (i=1;i<st->mode->nbEBands-1;i++)
+      for (i=st->start+1;i<st->end-1;i++)
       {
          celt_word32 d2;
          d2 = 2*bandLogE[i]-bandLogE[i-1]-bandLogE[i+1];
@@ -1318,7 +1327,7 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
    if (tell+(6<<BITRES) <= total_bits - total_boost)
    {
       alloc_trim = alloc_trim_analysis(st->mode, X, bandLogE,
-            st->mode->nbEBands, LM, C, N);
+            st->end, LM, C, N);
       ec_enc_icdf(enc, alloc_trim, trim_icdf, 7);
       tell = ec_tell_frac(enc);
    }
@@ -1432,8 +1441,8 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
    ALLOC(pulses, st->mode->nbEBands, int);
    ALLOC(fine_priority, st->mode->nbEBands, int);
 
-   /* bits =   packet size        -       where we are         - safety*/
-   bits = (nbCompressedBytes*8<<BITRES) - ec_tell_frac(enc) - 1;
+   /* bits =           packet size                    - where we are - safety*/
+   bits = ((celt_int32)nbCompressedBytes*8<<BITRES) - ec_tell_frac(enc) - 1;
    anti_collapse_rsv = isTransient&&LM>=2&&bits>=(LM+2<<BITRES) ? (1<<BITRES) : 0;
    bits -= anti_collapse_rsv;
    codedBands = compute_allocation(st->mode, st->start, st->end, offsets, cap,
@@ -1532,19 +1541,13 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
       c=0; do {
          st->prefilter_period=IMAX(st->prefilter_period, COMBFILTER_MINPERIOD);
          st->prefilter_period_old=IMAX(st->prefilter_period_old, COMBFILTER_MINPERIOD);
+         comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, st->mode->shortMdctSize,
+               st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset,
+               st->mode->window, st->overlap);
          if (LM!=0)
-         {
-            comb_filter(out_mem[c], out_mem[c], st->prefilter_period, st->prefilter_period, st->overlap,
-                  st->prefilter_gain, st->prefilter_gain, st->prefilter_tapset, st->prefilter_tapset,
-                  NULL, 0);
-            comb_filter(out_mem[c]+st->overlap, out_mem[c]+st->overlap, st->prefilter_period, pitch_index, N-st->overlap,
+            comb_filter(out_mem[c]+st->mode->shortMdctSize, out_mem[c]+st->mode->shortMdctSize, st->prefilter_period, pitch_index, N-st->mode->shortMdctSize,
                   st->prefilter_gain, gain1, st->prefilter_tapset, prefilter_tapset,
                   st->mode->window, st->mode->overlap);
-         } else {
-            comb_filter(out_mem[c], out_mem[c], st->prefilter_period_old, st->prefilter_period, N,
-                  st->prefilter_gain_old, st->prefilter_gain, st->prefilter_tapset_old, st->prefilter_tapset,
-                  st->mode->window, st->mode->overlap);
-         }
       } while (++c<CC);
 #endif /* ENABLE_POSTFILTER */
 
@@ -1558,6 +1561,14 @@ int celt_encode_with_ec_float(CELTEncoder * restrict st, const celt_sig * pcm, i
    st->prefilter_period = pitch_index;
    st->prefilter_gain = gain1;
    st->prefilter_tapset = prefilter_tapset;
+#ifdef RESYNTH
+   if (LM!=0)
+   {
+      st->prefilter_period_old = st->prefilter_period;
+      st->prefilter_gain_old = st->prefilter_gain;
+      st->prefilter_tapset_old = st->prefilter_tapset;
+   }
+#endif
 
    if (CC==2&&C==1) {
       for (i=0;i<st->mode->nbEBands;i++)
@@ -1735,6 +1746,7 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
          celt_int32 value = va_arg(ap, celt_int32);
          if (value<=500)
             goto bad_arg;
+         value = IMIN(value, 260000*st->channels);
          st->bitrate = value;
       }
       break;
@@ -1757,6 +1769,12 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
          st->tonal_average = QCONST16(1.f,8);
       }
       break;
+      case CELT_SET_INPUT_CLIPPING_REQUEST:
+      {
+         celt_int32 value = va_arg(ap, celt_int32);
+         st->clip = value;
+      }
+      break;
       default:
          goto bad_request;
    }
@@ -1792,7 +1810,7 @@ struct CELTDecoder {
    /* Everything beyond this point gets cleared on a reset */
 #define DECODER_RESET_START rng
 
-   ec_uint32 rng;
+   celt_uint32 rng;
    int last_pitch_index;
    int loss_count;
    int postfilter_period;
@@ -1916,6 +1934,7 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
    celt_word16 *lpc;
    celt_word32 *out_syn[2];
    celt_word16 *oldBandE, *oldLogE2, *backgroundLogE;
+   int plc=1;
    SAVE_STACK;
    
    c=0; do {
@@ -1948,19 +1967,29 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
       log2Amp(st->mode, st->start, st->end, bandE, backgroundLogE, C);
 
       seed = st->rng;
-      for (i=0;i<C*N;i++)
+      for (c=0;c<C;c++)
       {
-            seed = lcg_rand(seed);
-            X[i] = (celt_int32)(seed)>>20;
+         for (i=0;i<st->mode->effEBands;i++)
+         {
+            int j;
+            int boffs;
+            int blen;
+            boffs = N*c+(st->mode->eBands[i]<<LM);
+            blen = (st->mode->eBands[i+1]-st->mode->eBands[i])<<LM;
+            for (j=0;j<blen;j++)
+            {
+               seed = lcg_rand(seed);
+               X[boffs+j] = (celt_int32)(seed)>>20;
+            }
+            renormalise_vector(X+boffs, blen, Q15ONE);
+         }
       }
       st->rng = seed;
-      for (c=0;c<C;c++)
-         for (i=0;i<st->mode->nbEBands;i++)
-            renormalise_vector(X+N*c+(st->mode->eBands[i]<<LM), (st->mode->eBands[i+1]-st->mode->eBands[i])<<LM, Q15ONE);
 
-      denormalise_bands(st->mode, X, freq, bandE, st->mode->nbEBands, C, 1<<LM);
+      denormalise_bands(st->mode, X, freq, bandE, st->mode->effEBands, C, 1<<LM);
 
       compute_inv_mdcts(st->mode, 0, freq, out_syn, overlap_mem, C, LM);
+      plc = 0;
    } else if (st->loss_count == 0)
    {
       celt_word16 pitch_buf[MAX_PERIOD>>1];
@@ -1978,141 +2007,144 @@ static void celt_decode_lost(CELTDecoder * restrict st, celt_word16 * restrict p
       fade = QCONST16(.8f,15);
    }
 
-   c=0; do {
-      /* FIXME: This is more memory than necessary */
-      celt_word32 e[2*MAX_PERIOD];
-      celt_word16 exc[2*MAX_PERIOD];
-      celt_word32 ac[LPC_ORDER+1];
-      celt_word16 decay = 1;
-      celt_word32 S1=0;
-      celt_word16 mem[LPC_ORDER]={0};
-
-      offset = MAX_PERIOD-pitch_index;
-      for (i=0;i<MAX_PERIOD;i++)
-         exc[i] = ROUND16(out_mem[c][i], SIG_SHIFT);
-
-      if (st->loss_count == 0)
-      {
-         _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
-                        LPC_ORDER, MAX_PERIOD);
+   if (plc)
+   {
+      c=0; do {
+         /* FIXME: This is more memory than necessary */
+         celt_word32 e[2*MAX_PERIOD];
+         celt_word16 exc[2*MAX_PERIOD];
+         celt_word32 ac[LPC_ORDER+1];
+         celt_word16 decay = 1;
+         celt_word32 S1=0;
+         celt_word16 mem[LPC_ORDER]={0};
+
+         offset = MAX_PERIOD-pitch_index;
+         for (i=0;i<MAX_PERIOD;i++)
+            exc[i] = ROUND16(out_mem[c][i], SIG_SHIFT);
+
+         if (st->loss_count == 0)
+         {
+            _celt_autocorr(exc, ac, st->mode->window, st->mode->overlap,
+                  LPC_ORDER, MAX_PERIOD);
 
-         /* Noise floor -40 dB */
+            /* Noise floor -40 dB */
 #ifdef FIXED_POINT
-         ac[0] += SHR32(ac[0],13);
+            ac[0] += SHR32(ac[0],13);
 #else
-         ac[0] *= 1.0001f;
+            ac[0] *= 1.0001f;
 #endif
-         /* Lag windowing */
-         for (i=1;i<=LPC_ORDER;i++)
-         {
-            /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
+            /* Lag windowing */
+            for (i=1;i<=LPC_ORDER;i++)
+            {
+               /*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
 #ifdef FIXED_POINT
-            ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
+               ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
 #else
-            ac[i] -= ac[i]*(.008f*i)*(.008f*i);
+               ac[i] -= ac[i]*(.008f*i)*(.008f*i);
 #endif
-         }
+            }
 
-         _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
-      }
-      for (i=0;i<LPC_ORDER;i++)
-         mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
-      fir(exc, lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
-      /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
-      /* Check if the waveform is decaying (and if so how fast) */
-      {
-         celt_word32 E1=1, E2=1;
-         int period;
-         if (pitch_index <= MAX_PERIOD/2)
-            period = pitch_index;
-         else
-            period = MAX_PERIOD/2;
-         for (i=0;i<period;i++)
+            _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
+         }
+         for (i=0;i<LPC_ORDER;i++)
+            mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
+         fir(exc, lpc+c*LPC_ORDER, exc, MAX_PERIOD, LPC_ORDER, mem);
+         /*for (i=0;i<MAX_PERIOD;i++)printf("%d ", exc[i]); printf("\n");*/
+         /* Check if the waveform is decaying (and if so how fast) */
          {
-            E1 += SHR32(MULT16_16(exc[MAX_PERIOD-period+i],exc[MAX_PERIOD-period+i]),8);
-            E2 += SHR32(MULT16_16(exc[MAX_PERIOD-2*period+i],exc[MAX_PERIOD-2*period+i]),8);
+            celt_word32 E1=1, E2=1;
+            int period;
+            if (pitch_index <= MAX_PERIOD/2)
+               period = pitch_index;
+            else
+               period = MAX_PERIOD/2;
+            for (i=0;i<period;i++)
+            {
+               E1 += SHR32(MULT16_16(exc[MAX_PERIOD-period+i],exc[MAX_PERIOD-period+i]),8);
+               E2 += SHR32(MULT16_16(exc[MAX_PERIOD-2*period+i],exc[MAX_PERIOD-2*period+i]),8);
+            }
+            if (E1 > E2)
+               E1 = E2;
+            decay = celt_sqrt(frac_div32(SHR(E1,1),E2));
          }
-         if (E1 > E2)
-            E1 = E2;
-         decay = celt_sqrt(frac_div32(SHR(E1,1),E2));
-      }
 
-      /* Copy excitation, taking decay into account */
-      for (i=0;i<len+st->mode->overlap;i++)
-      {
-         celt_word16 tmp;
-         if (offset+i >= MAX_PERIOD)
+         /* Copy excitation, taking decay into account */
+         for (i=0;i<len+st->mode->overlap;i++)
          {
-            offset -= pitch_index;
-            decay = MULT16_16_Q15(decay, decay);
+            celt_word16 tmp;
+            if (offset+i >= MAX_PERIOD)
+            {
+               offset -= pitch_index;
+               decay = MULT16_16_Q15(decay, decay);
+            }
+            e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT);
+            tmp = ROUND16(out_mem[c][offset+i],SIG_SHIFT);
+            S1 += SHR32(MULT16_16(tmp,tmp),8);
          }
-         e[i] = SHL32(EXTEND32(MULT16_16_Q15(decay, exc[offset+i])), SIG_SHIFT);
-         tmp = ROUND16(out_mem[c][offset+i],SIG_SHIFT);
-         S1 += SHR32(MULT16_16(tmp,tmp),8);
-      }
-      for (i=0;i<LPC_ORDER;i++)
-         mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
-      for (i=0;i<len+st->mode->overlap;i++)
-         e[i] = MULT16_32_Q15(fade, e[i]);
-      iir(e, lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
+         for (i=0;i<LPC_ORDER;i++)
+            mem[i] = ROUND16(out_mem[c][MAX_PERIOD-1-i], SIG_SHIFT);
+         for (i=0;i<len+st->mode->overlap;i++)
+            e[i] = MULT16_32_Q15(fade, e[i]);
+         iir(e, lpc+c*LPC_ORDER, e, len+st->mode->overlap, LPC_ORDER, mem);
 
-      {
-         celt_word32 S2=0;
-         for (i=0;i<len+overlap;i++)
          {
-            celt_word16 tmp = ROUND16(e[i],SIG_SHIFT);
-            S2 += SHR32(MULT16_16(tmp,tmp),8);
-         }
-         /* This checks for an "explosion" in the synthesis */
+            celt_word32 S2=0;
+            for (i=0;i<len+overlap;i++)
+            {
+               celt_word16 tmp = ROUND16(e[i],SIG_SHIFT);
+               S2 += SHR32(MULT16_16(tmp,tmp),8);
+            }
+            /* This checks for an "explosion" in the synthesis */
 #ifdef FIXED_POINT
-         if (!(S1 > SHR32(S2,2)))
+            if (!(S1 > SHR32(S2,2)))
 #else
-         /* Float test is written this way to catch NaNs at the same time */
-         if (!(S1 > 0.2f*S2))
+               /* Float test is written this way to catch NaNs at the same time */
+               if (!(S1 > 0.2f*S2))
 #endif
-         {
-            for (i=0;i<len+overlap;i++)
-               e[i] = 0;
-         } else if (S1 < S2)
-         {
-            celt_word16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
-            for (i=0;i<len+overlap;i++)
-               e[i] = MULT16_32_Q15(ratio, e[i]);
+               {
+                  for (i=0;i<len+overlap;i++)
+                     e[i] = 0;
+               } else if (S1 < S2)
+               {
+                  celt_word16 ratio = celt_sqrt(frac_div32(SHR32(S1,1)+1,S2+1));
+                  for (i=0;i<len+overlap;i++)
+                     e[i] = MULT16_32_Q15(ratio, e[i]);
+               }
          }
-      }
 
 #ifdef ENABLE_POSTFILTER
-      /* Apply post-filter to the MDCT overlap of the previous frame */
-      comb_filter(out_mem[c]+MAX_PERIOD, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap,
-                  st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
-                  NULL, 0);
+         /* Apply post-filter to the MDCT overlap of the previous frame */
+         comb_filter(out_mem[c]+MAX_PERIOD, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap,
+               st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
+               NULL, 0);
 #endif /* ENABLE_POSTFILTER */
 
-      for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
-         out_mem[c][i] = out_mem[c][N+i];
+         for (i=0;i<MAX_PERIOD+st->mode->overlap-N;i++)
+            out_mem[c][i] = out_mem[c][N+i];
 
-      /* Apply TDAC to the concealed audio so that it blends with the
+         /* Apply TDAC to the concealed audio so that it blends with the
          previous and next frames */
-      for (i=0;i<overlap/2;i++)
-      {
-         celt_word32 tmp;
-         tmp = MULT16_32_Q15(st->mode->window[i],           e[N+overlap-1-i]) +
-               MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i          ]);
-         out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp);
-         out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(st->mode->window[i], tmp);
-      }
-      for (i=0;i<N;i++)
-         out_mem[c][MAX_PERIOD-N+i] = e[i];
+         for (i=0;i<overlap/2;i++)
+         {
+            celt_word32 tmp;
+            tmp = MULT16_32_Q15(st->mode->window[i],           e[N+overlap-1-i]) +
+                  MULT16_32_Q15(st->mode->window[overlap-i-1], e[N+i          ]);
+            out_mem[c][MAX_PERIOD+i] = MULT16_32_Q15(st->mode->window[overlap-i-1], tmp);
+            out_mem[c][MAX_PERIOD+overlap-i-1] = MULT16_32_Q15(st->mode->window[i], tmp);
+         }
+         for (i=0;i<N;i++)
+            out_mem[c][MAX_PERIOD-N+i] = e[i];
 
 #ifdef ENABLE_POSTFILTER
-      /* Apply pre-filter to the MDCT overlap for the next frame (post-filter will be applied then) */
-      comb_filter(e, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap,
-                  -st->postfilter_gain, -st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
-                  NULL, 0);
+         /* Apply pre-filter to the MDCT overlap for the next frame (post-filter will be applied then) */
+         comb_filter(e, out_mem[c]+MAX_PERIOD, st->postfilter_period, st->postfilter_period, st->overlap,
+               -st->postfilter_gain, -st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
+               NULL, 0);
 #endif /* ENABLE_POSTFILTER */
-      for (i=0;i<overlap;i++)
-         out_mem[c][MAX_PERIOD+i] = e[i];
-   } while (++c<C);
+         for (i=0;i<overlap;i++)
+            out_mem[c][MAX_PERIOD+i] = e[i];
+      } while (++c<C);
+   }
 
    deemphasis(out_syn, pcm, N, C, st->downsample, st->mode->preemph, st->preemph_memD);
    
@@ -2132,7 +2164,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
 #endif
    int c, i, N;
    int spread_decision;
-   int bits;
+   celt_int32 bits;
    ec_dec _dec;
    VARDECL(celt_sig, freq);
    VARDECL(celt_norm, X);
@@ -2175,7 +2207,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
 
    SAVE_STACK;
 
-   if (pcm==NULL)
+   if (len<0 || len>1275 || pcm==NULL)
       return CELT_BAD_ARG;
 
    frame_size *= st->downsample;
@@ -2348,7 +2380,7 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
    alloc_trim = tell+(6<<BITRES) <= total_bits ?
          ec_dec_icdf(dec, trim_icdf, 7) : 5;
 
-   bits = (len*8<<BITRES) - ec_tell_frac(dec) - 1;
+   bits = ((celt_int32)len*8<<BITRES) - ec_tell_frac(dec) - 1;
    anti_collapse_rsv = isTransient&&LM>=2&&bits>=(LM+2<<BITRES) ? (1<<BITRES) : 0;
    bits -= anti_collapse_rsv;
    codedBands = compute_allocation(st->mode, st->start, st->end, offsets, cap,
@@ -2421,19 +2453,14 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
    c=0; do {
       st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
       st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
+      comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, st->mode->shortMdctSize,
+            st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
+            st->mode->window, st->overlap);
       if (LM!=0)
-      {
-         comb_filter(out_syn[c], out_syn[c], st->postfilter_period, st->postfilter_period, st->overlap,
-               st->postfilter_gain, st->postfilter_gain, st->postfilter_tapset, st->postfilter_tapset,
-               NULL, 0);
-         comb_filter(out_syn[c]+st->overlap, out_syn[c]+st->overlap, st->postfilter_period, postfilter_pitch, N-st->overlap,
+         comb_filter(out_syn[c]+st->mode->shortMdctSize, out_syn[c]+st->mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-st->mode->shortMdctSize,
                st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
                st->mode->window, st->mode->overlap);
-      } else {
-         comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, N-st->overlap,
-               st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
-               st->mode->window, st->mode->overlap);
-      }
+
    } while (++c<CC);
    st->postfilter_period_old = st->postfilter_period;
    st->postfilter_gain_old = st->postfilter_gain;
@@ -2441,6 +2468,12 @@ int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *da
    st->postfilter_period = postfilter_pitch;
    st->postfilter_gain = postfilter_gain;
    st->postfilter_tapset = postfilter_tapset;
+   if (LM!=0)
+   {
+      st->postfilter_period_old = st->postfilter_period;
+      st->postfilter_gain_old = st->postfilter_gain;
+      st->postfilter_tapset_old = st->postfilter_tapset;
+   }
 #endif /* ENABLE_POSTFILTER */
 
    if (CC==2&&C==1) {
@@ -2570,7 +2603,7 @@ int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
       case CELT_SET_END_BAND_REQUEST:
       {
          celt_int32 value = va_arg(ap, celt_int32);
-         if (value<0 || value>=st->mode->nbEBands)
+         if (value<1 || value>st->mode->nbEBands)
             goto bad_arg;
          st->end = value;
       }