Add a SET_LTP call to allow on the fly activation/deactivation of the long term
[opus.git] / libcelt / celt.c
index bdf96e1..9ebd8df 100644 (file)
@@ -77,6 +77,7 @@ struct CELTEncoder {
    int channels;
    
    int pitch_enabled;
+   int pitch_available;
 
    celt_word16_t * restrict preemph_memE; /* Input is 16-bit, so why bother with 32 */
    celt_sig_t    * restrict preemph_memD;
@@ -109,6 +110,7 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode)
    st->overlap = mode->overlap;
 
    st->pitch_enabled = 1;
+   st->pitch_available = 1;
 
    st->in_mem = celt_alloc(st->overlap*C*sizeof(celt_sig_t));
    st->out_mem = celt_alloc((MAX_PERIOD+st->overlap)*C*sizeof(celt_sig_t));
@@ -372,12 +374,12 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si
 #endif
    int i, c, N, N4;
    int has_pitch;
+   int id;
    int pitch_index;
    int bits;
    int has_fold=1;
    ec_byte_buffer buf;
    ec_enc         enc;
-   celt_word32_t curr_power, pitch_power=0;
    VARDECL(celt_sig_t, in);
    VARDECL(celt_sig_t, freq);
    VARDECL(celt_norm_t, X);
@@ -476,6 +478,8 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si
    }
 
    /* Pitch analysis: we do it early to save on the peak stack space */
+   /* Don't use pitch if there isn't enough data available yet, or if we're using shortBlocks */
+   has_pitch = st->pitch_enabled && (st->pitch_available >= MAX_PERIOD) && (!shortBlocks);
 #ifdef EXP_PSY
    ALLOC(tonality, MAX_PERIOD/4, celt_word16_t);
    {
@@ -485,7 +489,7 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si
       compute_tonality(st->mode, X, st->psy_mem, MAX_PERIOD, tonality, MAX_PERIOD/4);
    }
 #else
-   if (st->pitch_enabled && !shortBlocks)
+   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);
    }
@@ -540,8 +544,9 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si
 #endif
 
    /* Compute MDCTs of the pitch part */
-   if (st->pitch_enabled && !shortBlocks)
+   if (has_pitch)
    {
+      celt_word32_t curr_power, pitch_power=0;
       /* Normalise the pitch vector as well (discard the energies) */
       VARDECL(celt_ener_t, bandEp);
       
@@ -550,31 +555,27 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si
       compute_band_energies(st->mode, freq, bandEp);
       normalise_bands(st->mode, freq, P, bandEp);
       pitch_power = bandEp[0]+bandEp[1]+bandEp[2];
-   }
-
-   /* Check if we can safely use the pitch (i.e. effective gain isn't too high) */
-   curr_power = bandE[0]+bandE[1]+bandE[2];
-   if (st->pitch_enabled && !shortBlocks && (MULT16_32_Q15(QCONST16(.1f, 15),curr_power) + QCONST32(10.f,ENER_SHIFT) < pitch_power))
-   {
-      int id;
-
-      /* Pitch prediction */
-      compute_pitch_gain(st->mode, X, P, gains);
-      id = quant_pitch(gains, st->mode->nbPBands, &enc);
-      if (id != -1)
-         has_pitch = 1;
-      else
+      /* Check if we can safely use the pitch (i.e. effective gain isn't too high) */
+      curr_power = bandE[0]+bandE[1]+bandE[2];
+      id=-1;
+      if ((MULT16_32_Q15(QCONST16(.1f, 15),curr_power) + QCONST32(10.f,ENER_SHIFT) < pitch_power))
+      {
+         /* Pitch prediction */
+         compute_pitch_gain(st->mode, X, P, gains);
+         id = quant_pitch(gains, st->mode->nbPBands);
+      } 
+      if (id == -1)
          has_pitch = 0;
+   }
+   
+   if (has_pitch) 
+   {  
+      unquant_pitch(id, gains, st->mode->nbPBands);
       ec_enc_bits(&enc, has_pitch, 1); /* Pitch flag */
-      if (has_pitch)
-      {
-         ec_enc_bits(&enc, has_fold, 1); /* Folding flag */
-         ec_enc_bits(&enc, id, 7);
-         ec_enc_uint(&enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
-      } else if (st->mode->nbShortMdcts > 1) {
-         ec_enc_bits(&enc, 0, 1); /* Transient off */
-         has_fold = 1;
-      }
+      ec_enc_bits(&enc, has_fold, 1); /* Folding flag */
+      ec_enc_bits(&enc, id, 7);
+      ec_enc_uint(&enc, pitch_index, MAX_PERIOD-(2*N-2*N4));
+      pitch_quant_bands(st->mode, P, gains);
    } else {
       if (!shortBlocks)
       {
@@ -624,14 +625,15 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si
 
    quant_fine_energy(st->mode, bandE, st->oldBandE, error, fine_quant, &enc);
 
-   pitch_quant_bands(st->mode, P, gains);
-
    /* Residual quantisation */
    quant_bands(st->mode, X, P, NULL, bandE, stereo_mode, pulses, shortBlocks, has_fold, nbCompressedBytes*8, &enc);
 
    /* Re-synthesis of the coded audio if required */
-   if (st->pitch_enabled || optional_synthesis!=NULL)
+   if (st->pitch_available>0 || optional_synthesis!=NULL)
    {
+      if (st->pitch_available>0 && st->pitch_available<MAX_PERIOD)
+        st->pitch_available+=st->frame_size;
+
       if (C==2)
          renormalise_bands(st->mode, X);
       /* Synthesis */
@@ -701,8 +703,7 @@ int celt_encode_float(CELTEncoder * restrict st, const float * pcm, float * opti
 
    if (optional_synthesis != NULL) {
      ret=celt_encode(st,in,in,compressed,nbCompressedBytes);
-   /*Converts backwards for inplace operation*/
-      for (j=0;j=C*N;j++)
+      for (j=0;j<C*N;j++)
          optional_synthesis[j]=in[j]*(1/32768.);
    } else {
      ret=celt_encode(st,in,NULL,compressed,nbCompressedBytes);
@@ -748,7 +749,22 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
          int value = va_arg(ap, int);
          if (value<0 || value>10)
             goto bad_arg;
-         if (value<=2)
+         if (value<=2) {
+            st->pitch_enabled = 0; 
+            st->pitch_available = 0;
+         } else {
+              st->pitch_enabled = 1;
+              if (st->pitch_available<1)
+                st->pitch_available = 1;
+         }   
+      }
+      break;
+      case CELT_SET_LTP_REQUEST:
+      {
+         int value = va_arg(ap, int);
+         if (value<0 || value>1 || (value==1 && st->pitch_available==0))
+            goto bad_arg;
+         if (value==0)
             st->pitch_enabled = 0;
          else
             st->pitch_enabled = 1;
@@ -973,16 +989,16 @@ int celt_decode_float(CELTDecoder * restrict st, unsigned char *data, int len, c
       transient_time = -1;
       transient_shift = 0;
    }
-   /* Get the pitch gains */
    
-   /* Get the pitch index */
    if (has_pitch)
    {
-      has_pitch = unquant_pitch(gains, st->mode->nbPBands, &dec);
+      int id;
+      /* Get the pitch gains and index */
+      id = ec_dec_bits(&dec, 7);
+      unquant_pitch(id, gains, st->mode->nbPBands);
       pitch_index = ec_dec_uint(&dec, MAX_PERIOD-(2*N-2*N4));
       st->last_pitch_index = pitch_index;
    } else {
-      /* FIXME: We could be more intelligent here and just not compute the MDCT */
       pitch_index = 0;
       for (i=0;i<st->mode->nbPBands;i++)
          gains[i] = 0;
@@ -1017,14 +1033,13 @@ int celt_decode_float(CELTDecoder * restrict st, unsigned char *data, int len, c
       ALLOC(bandEp, st->mode->nbEBands*C, celt_ener_t);
       compute_band_energies(st->mode, freq, bandEp);
       normalise_bands(st->mode, freq, P, bandEp);
+      /* Apply pitch gains */
+      pitch_quant_bands(st->mode, P, gains);
    } else {
       for (i=0;i<C*N;i++)
          P[i] = 0;
    }
 
-   /* Apply pitch gains */
-   pitch_quant_bands(st->mode, P, gains);
-
    /* Decode fixed codebook and merge with pitch */
    unquant_bands(st->mode, X, P, bandE, stereo_mode, pulses, shortBlocks, has_fold, len*8, &dec);