Example #1
0
void celt_fir_c(
         const opus_val16 *_x,
         const opus_val16 *num,
         opus_val16 *_y,
         int N,
         int ord,
         opus_val16 *mem,
         int arch)
{
   int i,j;
   VARDECL(opus_val16, rnum);
   VARDECL(opus_val16, x);
   SAVE_STACK;

   ALLOC(rnum, ord, opus_val16);
   ALLOC(x, N+ord, opus_val16);
   for(i=0;i<ord;i++)
      rnum[i] = num[ord-i-1];
   for(i=0;i<ord;i++)
      x[i] = mem[ord-i-1];
   for (i=0;i<N;i++)
      x[i+ord]=_x[i];
   for(i=0;i<ord;i++)
      mem[i] = _x[N-i-1];
#ifdef SMALL_FOOTPRINT
   (void)arch;
   for (i=0;i<N;i++)
   {
      opus_val32 sum = SHL32(EXTEND32(_x[i]), SIG_SHIFT);
      for (j=0;j<ord;j++)
      {
         sum = MAC16_16(sum,rnum[j],x[i+j]);
      }
      _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
   }
#else
   for (i=0;i<N-3;i+=4)
   {
      opus_val32 sum[4]={0,0,0,0};
      xcorr_kernel(rnum, x+i, sum, ord, arch);
      _y[i  ] = SATURATE16(ADD32(EXTEND32(_x[i  ]), PSHR32(sum[0], SIG_SHIFT)));
      _y[i+1] = SATURATE16(ADD32(EXTEND32(_x[i+1]), PSHR32(sum[1], SIG_SHIFT)));
      _y[i+2] = SATURATE16(ADD32(EXTEND32(_x[i+2]), PSHR32(sum[2], SIG_SHIFT)));
      _y[i+3] = SATURATE16(ADD32(EXTEND32(_x[i+3]), PSHR32(sum[3], SIG_SHIFT)));
   }
   for (;i<N;i++)
   {
      opus_val32 sum = 0;
      for (j=0;j<ord;j++)
         sum = MAC16_16(sum,rnum[j],x[i+j]);
      _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT)));
   }
#endif
   RESTORE_STACK;
}
Example #2
0
static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opus_val32 *y, opus_val32 S[3], int subframe, int offset, int c1, int c2, int C, int Fs)
{
   VARDECL(opus_val32, tmp);
   opus_val32 scale;
   int j;
   opus_val32 ret = 0;
   SAVE_STACK;

   if (subframe==0) return 0;
   if (Fs == 48000)
   {
      subframe *= 2;
      offset *= 2;
   } else if (Fs == 16000) {
      subframe = subframe*2/3;
      offset = offset*2/3;
   }
   ALLOC(tmp, subframe, opus_val32);

   downmix(_x, tmp, subframe, offset, c1, c2, C);
#ifdef FIXED_POINT
   scale = (1<<SIG_SHIFT);
#else
   scale = 1.f/32768;
#endif
   if (c2==-2)
      scale /= C;
   else if (c2>-1)
      scale /= 2;
   for (j=0;j<subframe;j++)
      tmp[j] *= scale;
   if (Fs == 48000)
   {
      ret = silk_resampler_down2_hp(S, y, tmp, subframe);
   } else if (Fs == 24000) {
      OPUS_COPY(y, tmp, subframe);
   } else if (Fs == 16000) {
      VARDECL(opus_val32, tmp3x);
      ALLOC(tmp3x, 3*subframe, opus_val32);
      /* Don't do this at home! This resampler is horrible and it's only (barely)
         usable for the purpose of the analysis because we don't care about all
         the aliasing between 8 kHz and 12 kHz. */
      for (j=0;j<subframe;j++)
      {
         tmp3x[3*j] = tmp[j];
         tmp3x[3*j+1] = tmp[j];
         tmp3x[3*j+2] = tmp[j];
      }
      silk_resampler_down2_hp(S, y, tmp3x, 3*subframe);
   }
   RESTORE_STACK;
   return ret;
}
Example #3
0
int opus_decode_float(OpusDecoder *st, const unsigned char *data,
                      opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
    VARDECL(opus_int16, out);
    int ret, i;
    int nb_samples;
    ALLOC_STACK;

    if(frame_size<=0)
    {
        RESTORE_STACK;
        return OPUS_BAD_ARG;
    }
    if (data != NULL && len > 0 && !decode_fec)
    {
        nb_samples = opus_decoder_get_nb_samples(st, data, len);
        if (nb_samples>0)
            frame_size = IMIN(frame_size, nb_samples);
        else
            return OPUS_INVALID_PACKET;
    }
    ALLOC(out, frame_size*st->channels, opus_int16);

    ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0);
    if (ret > 0)
    {
        for (i=0; i<ret*st->channels; i++)
            pcm[i] = (1.f/32768.f)*(out[i]);
    }
    RESTORE_STACK;
    return ret;
}
Example #4
0
static void compute_weighted_codebook(const signed char *shape_cb, const spx_word16_t *r, spx_word16_t *resp, spx_word16_t *resp2, spx_word32_t *E, int shape_cb_size, int subvect_size, char *stack)
{
   int i, j, k;
   VARDECL(spx_word16_t *shape);
   ALLOC(shape, subvect_size, spx_word16_t);
   for (i=0;i<shape_cb_size;i++)
   {
      spx_word16_t *res;
      
      res = resp+i*subvect_size;
      for (k=0;k<subvect_size;k++)
         shape[k] = (spx_word16_t)shape_cb[i*subvect_size+k];
      E[i]=0;

      /* Compute codeword response using convolution with impulse response */
      for(j=0;j<subvect_size;j++)
      {
         spx_word32_t resj=0;
         spx_word16_t res16;
         for (k=0;k<=j;k++)
            resj = MAC16_16(resj,shape[k],r[j-k]);
#ifdef FIXED_POINT
         res16 = EXTRACT16(SHR32(resj, 13));
#else
         res16 = 0.03125f*resj;
#endif
         /* Compute codeword energy */
         E[i]=MAC16_16(E[i],res16,res16);
         res[j] = res16;
         /*printf ("%d\n", (int)res[j]);*/
      }
   }

}
Example #5
0
void noise_codebook_quant(
spx_word16_t target[],			/* target vector */
spx_coef_t ak[],			/* LPCs for this subframe */
spx_coef_t awk1[],			/* Weighted LPCs for this subframe */
spx_coef_t awk2[],			/* Weighted LPCs for this subframe */
const void *par,                      /* Codebook/search parameters*/
int   p,                        /* number of LPC coeffs */
int   nsf,                      /* number of samples in subframe */
spx_sig_t *exc,
spx_word16_t *r,
SpeexBits *bits,
char *stack,
int   complexity,
int   update_target
)
{
   int i;
   VARDECL(spx_word16_t *tmp);
   ALLOC(tmp, nsf, spx_word16_t);
   residue_percep_zero16(target, ak, awk1, awk2, tmp, nsf, p, stack);

   for (i=0;i<nsf;i++)
      exc[i]+=SHL32(EXTEND32(tmp[i]),8);
   SPEEX_MEMSET(target, 0, nsf);
}
Example #6
0
File: lsp.c Project: VoxOx/VoxOx
static inline spx_word32_t cheb_poly_eva(spx_word32_t *coef,spx_word16_t x,int m,char *stack)
/*  float coef[]  	coefficients of the polynomial to be evaluated 	*/
/*  float x   		the point where polynomial is to be evaluated 	*/
/*  int m 		order of the polynomial 			*/
{
    int i;
    VARDECL(spx_word16_t *T);
    spx_word32_t sum;
    int m2=m>>1;
    VARDECL(spx_word16_t *coefn);

    /*Prevents overflows*/
    if (x>16383)
       x = 16383;
    if (x<-16383)
       x = -16383;

    /* Allocate memory for Chebyshev series formulation */
    ALLOC(T, m2+1, spx_word16_t);
    ALLOC(coefn, m2+1, spx_word16_t);

    for (i=0;i<m2+1;i++)
    {
       coefn[i] = coef[i];
       /*printf ("%f ", coef[i]);*/
    }
    /*printf ("\n");*/

    /* Initialise values */
    T[0]=16384;
    T[1]=x;

    /* Evaluate Chebyshev series formulation using iterative approach  */
    /* Evaluate polynomial and return value also free memory space */
    sum = ADD32(coefn[m2], MULT16_16_P14(coefn[m2-1],x));
    /*x *= 2;*/
    for(i=2;i<=m2;i++)
    {
       T[i] = SUB16(MULT16_16_Q13(x,T[i-1]), T[i-2]);
       sum = ADD32(sum, MULT16_16_P14(coefn[m2-i],T[i]));
       /*printf ("%f ", sum);*/
    }
    
    /*printf ("\n");*/
    return sum;
}
/* Resample with a 2nd order AR filter followed by FIR interpolation */
void silk_resampler_private_down_FIR(
    void                            *SS,            /* I/O  Resampler state             */
    opus_int16                      out[],          /* O    Output signal               */
    const opus_int16                in[],           /* I    Input signal                */
    opus_int32                      inLen           /* I    Number of input samples     */
)
{
    silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
    opus_int32 nSamplesIn;
    opus_int32 max_index_Q16, index_increment_Q16;
    VARDECL( opus_int32, buf );
    const opus_int16 *FIR_Coefs;
    SAVE_STACK;

    ALLOC( buf, S->batchSize + S->FIR_Order, opus_int32 );

    /* Copy buffered samples to start of buffer */
    silk_memcpy( buf, S->sFIR.i32, S->FIR_Order * sizeof( opus_int32 ) );

    FIR_Coefs = &S->Coefs[ 2 ];

    /* Iterate over blocks of frameSizeIn input samples */
    index_increment_Q16 = S->invRatio_Q16;
    while( 1 ) {
        nSamplesIn = silk_min( inLen, S->batchSize );

        /* Second-order AR filter (output in Q8) */
        silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, S->Coefs, nSamplesIn );

        max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 );

        /* Interpolate filtered signal */
        out = silk_resampler_private_down_FIR_INTERPOL( out, buf, FIR_Coefs, S->FIR_Order,
            S->FIR_Fracs, max_index_Q16, index_increment_Q16 );

        in += nSamplesIn;
        inLen -= nSamplesIn;

        if( inLen > 1 ) {
            /* More iterations to do; copy last part of filtered signal to beginning of buffer */
            silk_memcpy( buf, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
        } else {
            break;
        }
    }

    /* Copy last part of filtered signal to the state for the next call */
    silk_memcpy( S->sFIR.i32, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
    RESTORE_STACK;
}
Example #8
0
int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
  int channels, int streams, int coupled_streams,
  unsigned char *demixing_matrix, opus_int32 demixing_matrix_size)
{
  int nb_input_streams;
  opus_int32 expected_matrix_size;
  int i, ret;
  unsigned char mapping[255];
  VARDECL(opus_int16, buf);
  ALLOC_STACK;

  /* Verify supplied matrix size. */
  nb_input_streams = streams + coupled_streams;
  expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
  if (expected_matrix_size != demixing_matrix_size)
  {
    RESTORE_STACK;
    return OPUS_BAD_ARG;
  }

  /* Convert demixing matrix input into internal format. */
  ALLOC(buf, nb_input_streams * channels, opus_int16);
  for (i = 0; i < nb_input_streams * channels; i++)
  {
    int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
    s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
    buf[i] = (opus_int16)s;
  }

  /* Assign demixing matrix. */
  st->demixing_matrix_size_in_bytes =
    mapping_matrix_get_size(channels, nb_input_streams);
  if (!st->demixing_matrix_size_in_bytes)
  {
    RESTORE_STACK;
    return OPUS_BAD_ARG;
  }

  mapping_matrix_init(get_demixing_matrix(st), channels, nb_input_streams, 0,
    buf, demixing_matrix_size);

  /* Set trivial mapping so each input channel pairs with a matrix column. */
  for (i = 0; i < channels; i++)
    mapping[i] = i;

  ret = opus_multistream_decoder_init(
    get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
  RESTORE_STACK;
  return ret;
}
Example #9
0
void _celt_autocorr(
                   const opus_val16 *x,   /*  in: [0...n-1] samples x   */
                   opus_val32       *ac,  /* out: [0...lag-1] ac values */
                   const opus_val16       *window,
                   int          overlap,
                   int          lag,
                   int          n
                  )
{
   opus_val32 d;
   int i;
   VARDECL(opus_val16, xx);
   SAVE_STACK;
   ALLOC(xx, n, opus_val16);
   celt_assert(n>0);
   celt_assert(overlap>=0);
   for (i=0;i<n;i++)
      xx[i] = x[i];
   for (i=0;i<overlap;i++)
   {
      xx[i] = MULT16_16_Q15(x[i],window[i]);
      xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
   }
#ifdef FIXED_POINT
   {
      opus_val32 ac0=0;
      int shift;
      for(i=0;i<n;i++)
         ac0 += SHR32(MULT16_16(xx[i],xx[i]),9);
      ac0 += 1+n;

      shift = celt_ilog2(ac0)-30+10;
      shift = (shift+1)/2;
      for(i=0;i<n;i++)
         xx[i] = VSHR32(xx[i], shift);
   }
#endif
   while (lag>=0)
   {
      for (i = lag, d = 0; i < n; i++)
         d += xx[i] * xx[i-lag];
      ac[lag] = d;
      /*printf ("%f ", ac[lag]);*/
      lag--;
   }
   /*printf ("\n");*/
   ac[0] += 10;

   RESTORE_STACK;
}
Example #10
0
static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
{
   int pitch_index;
   VARDECL( opus_val16, lp_pitch_buf );
   SAVE_STACK;
   ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
   pitch_downsample(decode_mem, lp_pitch_buf,
         DECODE_BUFFER_SIZE, C, arch);
   pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
         DECODE_BUFFER_SIZE-PLC_PITCH_LAG_MAX,
         PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, arch);
   pitch_index = PLC_PITCH_LAG_MAX-pitch_index;
   RESTORE_STACK;
   return pitch_index;
}
Example #11
0
/** Forced pitch delay and gain */
int forced_pitch_quant(
spx_word16_t target[],                 /* Target vector */
spx_word16_t *sw,
spx_coef_t ak[],                     /* LPCs for this subframe */
spx_coef_t awk1[],                   /* Weighted LPCs #1 for this subframe */
spx_coef_t awk2[],                   /* Weighted LPCs #2 for this subframe */
spx_sig_t exc[],                    /* Excitation */
const void *par,
int   start,                    /* Smallest pitch value allowed */
int   end,                      /* Largest pitch value allowed */
spx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
int   p,                        /* Number of LPC coeffs */
int   nsf,                      /* Number of samples in subframe */
SpeexBits *bits,
char *stack,
spx_word16_t *exc2,
spx_word16_t *r,
int complexity,
int cdbk_offset,
int plc_tuning,
spx_word32_t *cumul_gain
)
{
   int i;
   VARDECL(spx_word16_t *res);
   ALLOC(res, nsf, spx_word16_t);
#ifdef FIXED_POINT
   if (pitch_coef>63)
      pitch_coef=63;
#else
   if (pitch_coef>.99)
      pitch_coef=.99;
#endif
   for (i=0;i<nsf&&i<start;i++)
   {
      exc[i]=MULT16_16(SHL16(pitch_coef, 7),exc2[i-start]);
   }
   for (;i<nsf;i++)
   {
      exc[i]=MULT16_32_Q15(SHL16(pitch_coef, 9),exc[i-start]);
   }
   for (i=0;i<nsf;i++)
      res[i] = EXTRACT16(PSHR32(exc[i], SIG_SHIFT-1));
   syn_percep_zero16(res, ak, awk1, awk2, res, nsf, p, stack);
   for (i=0;i<nsf;i++)
      target[i]=EXTRACT16(SATURATE(SUB32(EXTEND32(target[i]),EXTEND32(res[i])),32700));
   return start;
}
Example #12
0
void silk_noise_shape_analysis_FIX(
    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state FIX                                                           */
    silk_encoder_control_FIX        *psEncCtrl,                             /* I/O  Encoder control FIX                                                         */
    const opus_int16                *pitch_res,                             /* I    LPC residual from pitch analysis                                            */
    const opus_int16                *x,                                     /* I    Input signal [ frame_length + la_shape ]                                    */
    int                              arch                                   /* I    Run-time architecture                                                       */
)
{
    silk_shape_state_FIX *psShapeSt = &psEnc->sShape;
    opus_int     k, i, nSamples, Qnrg, b_Q14, warping_Q16, scale = 0;
    opus_int32   SNR_adj_dB_Q7, HarmBoost_Q16, HarmShapeGain_Q16, Tilt_Q16, tmp32;
    opus_int32   nrg, pre_nrg_Q30, log_energy_Q7, log_energy_prev_Q7, energy_variation_Q7;
    opus_int32   delta_Q16, BWExp1_Q16, BWExp2_Q16, gain_mult_Q16, gain_add_Q16, strength_Q16, b_Q8;
    opus_int32   auto_corr[     MAX_SHAPE_LPC_ORDER + 1 ];
    opus_int32   refl_coef_Q16[ MAX_SHAPE_LPC_ORDER ];
    opus_int32   AR1_Q24[       MAX_SHAPE_LPC_ORDER ];
    opus_int32   AR2_Q24[       MAX_SHAPE_LPC_ORDER ];
    VARDECL( opus_int16, x_windowed );
    const opus_int16 *x_ptr, *pitch_res_ptr;
    SAVE_STACK;

    /* Point to start of first LPC analysis block */
    x_ptr = x - psEnc->sCmn.la_shape;

    /****************/
    /* GAIN CONTROL */
    /****************/
    SNR_adj_dB_Q7 = psEnc->sCmn.SNR_dB_Q7;

    /* Input quality is the average of the quality in the lowest two VAD bands */
    psEncCtrl->input_quality_Q14 = ( opus_int )silk_RSHIFT( (opus_int32)psEnc->sCmn.input_quality_bands_Q15[ 0 ]
        + psEnc->sCmn.input_quality_bands_Q15[ 1 ], 2 );

    /* Coding quality level, between 0.0_Q0 and 1.0_Q0, but in Q14 */
    psEncCtrl->coding_quality_Q14 = silk_RSHIFT( silk_sigm_Q15( silk_RSHIFT_ROUND( SNR_adj_dB_Q7 -
        SILK_FIX_CONST( 20.0, 7 ), 4 ) ), 1 );

    /* Reduce coding SNR during low speech activity */
    if( psEnc->sCmn.useCBR == 0 ) {
        b_Q8 = SILK_FIX_CONST( 1.0, 8 ) - psEnc->sCmn.speech_activity_Q8;
        b_Q8 = silk_SMULWB( silk_LSHIFT( b_Q8, 8 ), b_Q8 );
        SNR_adj_dB_Q7 = silk_SMLAWB( SNR_adj_dB_Q7,
            silk_SMULBB( SILK_FIX_CONST( -BG_SNR_DECR_dB, 7 ) >> ( 4 + 1 ), b_Q8 ),                                       /* Q11*/
            silk_SMULWB( SILK_FIX_CONST( 1.0, 14 ) + psEncCtrl->input_quality_Q14, psEncCtrl->coding_quality_Q14 ) );     /* Q12*/
    }
Example #13
0
File: celt.c Project: tzhuan/llcon
static int transient_analysis(celt_word32_t *in, int len, int C, int *transient_time, int *transient_shift)
{
   int c, i, n;
   celt_word32_t ratio;
   VARDECL(celt_word32_t, begin);
   SAVE_STACK;
   ALLOC(begin, len, celt_word32_t);
   for (i=0;i<len;i++)
      begin[i] = ABS32(SHR32(in[C*i],SIG_SHIFT));
   for (c=1;c<C;c++)
   {
      for (i=0;i<len;i++)
         begin[i] = MAX32(begin[i], ABS32(SHR32(in[C*i+c],SIG_SHIFT)));
   }
   for (i=1;i<len;i++)
      begin[i] = MAX32(begin[i-1],begin[i]);
   n = -1;
   for (i=8;i<len-8;i++)
   {
      if (begin[i] < MULT16_32_Q15(QCONST16(.2f,15),begin[len-1]))
         n=i;
   }
   if (n<32)
   {
      n = -1;
      ratio = 0;
   } else {
      ratio = DIV32(begin[len-1],1+begin[n-16]);
   }
   if (ratio < 0)
      ratio = 0;
   if (ratio > 1000)
      ratio = 1000;
   ratio *= ratio;
   
   if (ratio > 2048)
      *transient_shift = 3;
   else
      *transient_shift = 0;
   
   *transient_time = n;
   
   RESTORE_STACK;
   return ratio > 20;
}
Example #14
0
int opus_decode_float(OpusDecoder *st, const unsigned char *data,
      opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
   VARDECL(opus_int16, out);
   int ret, i;
   ALLOC_STACK;

   ALLOC(out, frame_size*st->channels, opus_int16);

   ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0);
   if (ret > 0)
   {
      for (i=0;i<ret*st->channels;i++)
         pcm[i] = (1.f/32768.f)*(out[i]);
   }
   RESTORE_STACK;
   return ret;
}
Example #15
0
/* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */
void silk_resampler_private_IIR_FIR(
    void                            *SS,            /* I/O  Resampler state             */
    opus_int16                      out[],          /* O    Output signal               */
    const opus_int16                in[],           /* I    Input signal                */
    opus_int32                      inLen           /* I    Number of input samples     */
)
{
    silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
    opus_int32 nSamplesIn;
    opus_int32 max_index_Q16, index_increment_Q16;
    VARDECL( opus_int16, buf );
    SAVE_STACK;

    ALLOC( buf, 2 * S->batchSize + RESAMPLER_ORDER_FIR_12, opus_int16 );

    /* Copy buffered samples to start of buffer */
    silk_memcpy( buf, S->sFIR.i16, RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );

    /* Iterate over blocks of frameSizeIn input samples */
    index_increment_Q16 = S->invRatio_Q16;
    while( 1 ) {
        nSamplesIn = silk_min( inLen, S->batchSize );

        /* Upsample 2x */
        silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_12 ], in, nSamplesIn );

        max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + 1 );         /* + 1 because 2x upsampling */
        out = silk_resampler_private_IIR_FIR_INTERPOL( out, buf, max_index_Q16, index_increment_Q16 );
        in += nSamplesIn;
        inLen -= nSamplesIn;

        if( inLen > 0 ) {
            /* More iterations to do; copy last part of filtered signal to beginning of buffer */
            silk_memcpy( buf, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );
        } else {
            break;
        }
    }

    /* Copy last part of filtered signal to the state for the next call */
    silk_memcpy( S->sFIR.i16, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) );
    RESTORE_STACK;
}
Example #16
0
int opus_multistream_encode_float(
    OpusMSEncoder *st,
    const float *pcm,
    int frame_size,
    unsigned char *data,
    opus_int32 max_data_bytes
)
{
   int i, ret;
   VARDECL(opus_int16, in);
   ALLOC_STACK;

   ALLOC(in, frame_size*st->layout.nb_channels, opus_int16);

   for (i=0;i<frame_size*st->layout.nb_channels;i++)
      in[i] = FLOAT2INT16(pcm[i]);
   ret = opus_multistream_encode(st, in, frame_size, data, max_data_bytes);
   RESTORE_STACK;
   return ret;
}
Example #17
0
/* Solves Ax = b, assuming A is symmetric */
void silk_solve_LDL_FIX(
    opus_int32                      *A,                                     /* I    Pointer to symetric square matrix A                                         */
    opus_int                        M,                                      /* I    Size of matrix                                                              */
    const opus_int32                *b,                                     /* I    Pointer to b vector                                                         */
    opus_int32                      *x_Q16                                  /* O    Pointer to x solution vector                                                */
)
{
    VARDECL( opus_int32, L_Q16 );
    opus_int32 Y[      MAX_MATRIX_SIZE ];
    inv_D_t   inv_D[  MAX_MATRIX_SIZE ];
    SAVE_STACK;

    silk_assert( M <= MAX_MATRIX_SIZE );
    ALLOC( L_Q16, M * M, opus_int32 );

    /***************************************************
    Factorize A by LDL such that A = L*D*L',
    where L is lower triangular with ones on diagonal
    ****************************************************/
    silk_LDL_factorize_FIX( A, M, L_Q16, inv_D );

    /****************************************************
    * substitute D*L'*x = Y. ie:
    L*D*L'*x = b => L*Y = b <=> Y = inv(L)*b
    ******************************************************/
    silk_LS_SolveFirst_FIX( L_Q16, M, b, Y );

    /****************************************************
    D*L'*x = Y <=> L'*x = inv(D)*Y, because D is
    diagonal just multiply with 1/d_i
    ****************************************************/
    silk_LS_divide_Q16_FIX( Y, inv_D, M );

    /****************************************************
    x = inv(L') * inv(D) * Y
    *****************************************************/
    silk_LS_SolveLast_FIX( L_Q16, M, Y, x_Q16 );
    RESTORE_STACK;
}
Example #18
0
static OPUS_INLINE void silk_PLC_energy(opus_int32 *energy1, opus_int *shift1, opus_int32 *energy2, opus_int *shift2,
      const opus_int32 *exc_Q14, const opus_int32 *prevGain_Q10, int subfr_length, int nb_subfr)
{
    int i, k;
    VARDECL( opus_int16, exc_buf );
    opus_int16 *exc_buf_ptr;
    SAVE_STACK;
    ALLOC( exc_buf, 2*subfr_length, opus_int16 );
    /* Find random noise component */
    /* Scale previous excitation signal */
    exc_buf_ptr = exc_buf;
    for( k = 0; k < 2; k++ ) {
        for( i = 0; i < subfr_length; i++ ) {
            exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
                silk_SMULWW( exc_Q14[ i + ( k + nb_subfr - 2 ) * subfr_length ], prevGain_Q10[ k ] ), 8 ) );
        }
        exc_buf_ptr += subfr_length;
    }
    /* Find the subframe with lowest energy of the last two and use that as random noise generator */
    silk_sum_sqr_shift( energy1, shift1, exc_buf,                  subfr_length );
    silk_sum_sqr_shift( energy2, shift2, &exc_buf[ subfr_length ], subfr_length );
    RESTORE_STACK;
}
Example #19
0
static OPUS_INLINE void silk_PLC_conceal(
    silk_decoder_state                  *psDec,             /* I/O Decoder state        */
    silk_decoder_control                *psDecCtrl,         /* I/O Decoder control      */
    opus_int16                          frame[],            /* O LPC residual signal    */
    int                                 arch                /* I Run-time architecture  */
)
{
    opus_int   i, j, k;
    opus_int   lag, idx, sLTP_buf_idx, shift1, shift2;
    opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30;
    opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
    opus_int32 LPC_pred_Q10, LTP_pred_Q12;
    opus_int16 rand_scale_Q14;
    opus_int16 *B_Q14;
    opus_int32 *sLPC_Q14_ptr;
    opus_int16 A_Q12[ MAX_LPC_ORDER ];
#ifdef SMALL_FOOTPRINT
    opus_int16 *sLTP;
#else
    VARDECL( opus_int16, sLTP );
#endif
    VARDECL( opus_int32, sLTP_Q14 );
    silk_PLC_struct *psPLC = &psDec->sPLC;
    opus_int32 prevGain_Q10[2];
    SAVE_STACK;

    ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
#ifdef SMALL_FOOTPRINT
    /* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */
    sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length;
#else
    ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
#endif

    prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6);
    prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6);

    if( psDec->first_frame_after_reset ) {
       silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) );
    }

    silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr);

    if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
        /* First sub-frame has lowest energy */
        rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ];
    } else {
        /* Second sub-frame has lowest energy */
        rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
    }

    /* Set up Gain to random noise component */
    B_Q14          = psPLC->LTPCoef_Q14;
    rand_scale_Q14 = psPLC->randScale_Q14;

    /* Set up attenuation gains */
    harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
    if( psDec->prevSignalType == TYPE_VOICED ) {
        rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[  silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
    } else {
        rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
    }

    /* LPC concealment. Apply BWE to previous LPC */
    silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );

    /* Preload LPC coeficients to array on stack. Gives small performance gain */
    silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );

    /* First Lost frame */
    if( psDec->lossCnt == 0 ) {
        rand_scale_Q14 = 1 << 14;

        /* Reduce random noise Gain for voiced frames */
        if( psDec->prevSignalType == TYPE_VOICED ) {
            for( i = 0; i < LTP_ORDER; i++ ) {
                rand_scale_Q14 -= B_Q14[ i ];
            }
            rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
            rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
        } else {
            /* Reduce random noise for unvoiced frames with high LPC gain */
            opus_int32 invGain_Q30, down_scale_Q30;

            invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );

            down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
            down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
            down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );

            rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
        }
    }

    rand_seed    = psPLC->rand_seed;
    lag          = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
    sLTP_buf_idx = psDec->ltp_mem_length;

    /* Rewhiten LTP state */
    idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
    silk_assert( idx > 0 );
    silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
    /* Scale LTP state */
    inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
    inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 );
    for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) {
        sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] );
    }

    /***************************/
    /* LTP synthesis filtering */
    /***************************/
    for( k = 0; k < psDec->nb_subfr; k++ ) {
        /* Set up pointer */
        pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
        for( i = 0; i < psDec->subfr_length; i++ ) {
            /* Unrolled loop */
            /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
            LTP_pred_Q12 = 2;
            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[  0 ], B_Q14[ 0 ] );
            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
            LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
            pred_lag_ptr++;

            /* Generate LPC excitation */
            rand_seed = silk_RAND( rand_seed );
            idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
            sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 );
            sLTP_buf_idx++;
        }

        /* Gradually reduce LTP gain */
        for( j = 0; j < LTP_ORDER; j++ ) {
            B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
        }
        if ( psDec->indices.signalType != TYPE_NO_VOICE_ACTIVITY ) {
            /* Gradually reduce excitation gain */
            rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
        }

        /* Slowly increase pitch lag */
        psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
        psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
        lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
    }

    /***************************/
    /* LPC synthesis filtering */
    /***************************/
    sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ];

    /* Copy LPC state */
    silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );

    silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
    for( i = 0; i < psDec->frame_length; i++ ) {
        /* partly unrolled */
        /* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
        LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  1 ], A_Q12[ 0 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  2 ], A_Q12[ 1 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  3 ], A_Q12[ 2 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  4 ], A_Q12[ 3 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  5 ], A_Q12[ 4 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  6 ], A_Q12[ 5 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  7 ], A_Q12[ 6 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  8 ], A_Q12[ 7 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i -  9 ], A_Q12[ 8 ] );
        LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
        for( j = 10; j < psDec->LPC_order; j++ ) {
            LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] );
        }

        /* Add prediction to LPC excitation */
        sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ],
                                            silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ));

        /* Scale with Gain */
        frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
    }

    /* Save LPC state */
    silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );

    /**************************************/
    /* Update states                      */
    /**************************************/
    psPLC->rand_seed     = rand_seed;
    psPLC->randScale_Q14 = rand_scale_Q14;
    for( i = 0; i < MAX_NB_SUBFR; i++ ) {
        psDecCtrl->pitchL[ i ] = lag;
    }
    RESTORE_STACK;
}
Example #20
0
int _celt_autocorr(
                   const opus_val16 *x,   /*  in: [0...n-1] samples x   */
                   opus_val32       *ac,  /* out: [0...lag-1] ac values */
                   const opus_val16       *window,
                   int          overlap,
                   int          lag,
                   int          n,
                   int          arch
                  )
{
   opus_val32 d;
   int i, k;
   int fastN=n-lag;
   int shift;
   const opus_val16 *xptr;
   VARDECL(opus_val16, xx);
   SAVE_STACK;
   ALLOC(xx, n, opus_val16);
   celt_assert(n>0);
   celt_assert(overlap>=0);
   if (overlap == 0)
   {
      xptr = x;
   } else {
      for (i=0;i<n;i++)
         xx[i] = x[i];
      for (i=0;i<overlap;i++)
      {
         xx[i] = MULT16_16_Q15(x[i],window[i]);
         xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
      }
      xptr = xx;
   }
   shift=0;
#ifdef OPUS_FIXED_POINT
   {
      opus_val32 ac0;
      ac0 = 1+(n<<7);
      if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9);
      for(i=(n&1);i<n;i+=2)
      {
         ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9);
         ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9);
      }

      shift = celt_ilog2(ac0)-30+10;
      shift = (shift)/2;
      if (shift>0)
      {
         for(i=0;i<n;i++)
            xx[i] = PSHR32(xptr[i], shift);
         xptr = xx;
      } else
         shift = 0;
   }
#endif
   celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch);
   for (k=0;k<=lag;k++)
   {
      for (i = k+fastN, d = 0; i < n; i++)
         d = MAC16_16(d, xptr[i], xptr[i-k]);
      ac[k] += d;
   }
#ifdef OPUS_FIXED_POINT
   shift = 2*shift;
   if (shift<=0)
      ac[0] += SHL32((opus_int32)1, -shift);
   if (ac[0] < 268435456)
   {
      int shift2 = 29 - EC_ILOG(ac[0]);
      for (i=0;i<=lag;i++)
         ac[i] = SHL32(ac[i], shift2);
      shift -= shift2;
   } else if (ac[0] >= 536870912)
   {
      int shift2=1;
      if (ac[0] >= 1073741824)
         shift2++;
      for (i=0;i<=lag;i++)
         ac[i] = SHR32(ac[i], shift2);
      shift += shift2;
   }
#endif

   RESTORE_STACK;
   return shift;
}
Example #21
0
void celt_iir(const opus_val32 *_x,
         const opus_val16 *den,
         opus_val32 *_y,
         int N,
         int ord,
         opus_val16 *mem,
         int arch)
{
#ifdef SMALL_FOOTPRINT
   int i,j;
   (void)arch;
   for (i=0;i<N;i++)
   {
      opus_val32 sum = _x[i];
      for (j=0;j<ord;j++)
      {
         sum -= MULT16_16(den[j],mem[j]);
      }
      for (j=ord-1;j>=1;j--)
      {
         mem[j]=mem[j-1];
      }
      mem[0] = ROUND16(sum,SIG_SHIFT);
      _y[i] = sum;
   }
#else
   int i,j;
   VARDECL(opus_val16, rden);
   VARDECL(opus_val16, y);
   SAVE_STACK;

   celt_assert((ord&3)==0);
   ALLOC(rden, ord, opus_val16);
   ALLOC(y, N+ord, opus_val16);
   for(i=0;i<ord;i++)
      rden[i] = den[ord-i-1];
   for(i=0;i<ord;i++)
      y[i] = -mem[ord-i-1];
   for(;i<N+ord;i++)
      y[i]=0;
   for (i=0;i<N-3;i+=4)
   {
      /* Unroll by 4 as if it were an FIR filter */
      opus_val32 sum[4];
      sum[0]=_x[i];
      sum[1]=_x[i+1];
      sum[2]=_x[i+2];
      sum[3]=_x[i+3];
      xcorr_kernel(rden, y+i, sum, ord, arch);

      /* Patch up the result to compensate for the fact that this is an IIR */
      y[i+ord  ] = -ROUND16(sum[0],SIG_SHIFT);
      _y[i  ] = sum[0];
      sum[1] = MAC16_16(sum[1], y[i+ord  ], den[0]);
      y[i+ord+1] = -ROUND16(sum[1],SIG_SHIFT);
      _y[i+1] = sum[1];
      sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
      sum[2] = MAC16_16(sum[2], y[i+ord  ], den[1]);
      y[i+ord+2] = -ROUND16(sum[2],SIG_SHIFT);
      _y[i+2] = sum[2];

      sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
      sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
      sum[3] = MAC16_16(sum[3], y[i+ord  ], den[2]);
      y[i+ord+3] = -ROUND16(sum[3],SIG_SHIFT);
      _y[i+3] = sum[3];
   }
   for (;i<N;i++)
   {
      opus_val32 sum = _x[i];
      for (j=0;j<ord;j++)
         sum -= MULT16_16(rden[j],y[i+j]);
      y[i+ord] = ROUND16(sum,SIG_SHIFT);
      _y[i] = sum;
   }
   for(i=0;i<ord;i++)
      mem[i] = _y[N-i-1];
   RESTORE_STACK;
#endif
}
Example #22
0
opus_int silk_decode_frame(
    silk_decoder_state          *psDec,                         /* I/O  Pointer to Silk decoder state               */
    ec_dec                      *psRangeDec,                    /* I/O  Compressor data structure                   */
    opus_int16                  pOut[],                         /* O    Pointer to output speech frame              */
    opus_int32                  *pN,                            /* O    Pointer to size of output frame             */
    opus_int                    lostFlag,                       /* I    0: no loss, 1 loss, 2 decode fec            */
    opus_int                    condCoding                      /* I    The type of conditional coding to use       */
)
{
    VARDECL( silk_decoder_control, psDecCtrl );
    opus_int         L, mv_len, ret = 0;
    VARDECL( opus_int, pulses );
    SAVE_STACK;

    L = psDec->frame_length;
    ALLOC( psDecCtrl, 1, silk_decoder_control );
    ALLOC( pulses, (L + SHELL_CODEC_FRAME_LENGTH - 1) &
                   ~(SHELL_CODEC_FRAME_LENGTH - 1), opus_int );
    psDecCtrl->LTP_scale_Q14 = 0;

    /* Safety checks */
    silk_assert( L > 0 && L <= MAX_FRAME_LENGTH );

    if(   lostFlag == FLAG_DECODE_NORMAL ||
        ( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
    {
        /*********************************************/
        /* Decode quantization indices of side info  */
        /*********************************************/
        silk_decode_indices( psDec, psRangeDec, psDec->nFramesDecoded, lostFlag, condCoding );

        /*********************************************/
        /* Decode quantization indices of excitation */
        /*********************************************/
        silk_decode_pulses( psRangeDec, pulses, psDec->indices.signalType,
                psDec->indices.quantOffsetType, psDec->frame_length );

        /********************************************/
        /* Decode parameters and pulse signal       */
        /********************************************/
        silk_decode_parameters( psDec, psDecCtrl, condCoding );

        /********************************************************/
        /* Run inverse NSQ                                      */
        /********************************************************/
        silk_decode_core( psDec, psDecCtrl, pOut, pulses );

        /********************************************************/
        /* Update PLC state                                     */
        /********************************************************/
        silk_PLC( psDec, psDecCtrl, pOut, 0 );

        psDec->lossCnt = 0;
        psDec->prevSignalType = psDec->indices.signalType;
        silk_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );

        /* A frame has been decoded without errors */
        psDec->first_frame_after_reset = 0;
    } else {
        /* Handle packet loss by extrapolation */
        silk_PLC( psDec, psDecCtrl, pOut, 1 );
    }

    /*************************/
    /* Update output buffer. */
    /*************************/
    silk_assert( psDec->ltp_mem_length >= psDec->frame_length );
    mv_len = psDec->ltp_mem_length - psDec->frame_length;
    silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
    silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );

    /************************************************/
    /* Comfort noise generation / estimation        */
    /************************************************/
    silk_CNG( psDec, psDecCtrl, pOut, L );

    /****************************************************************/
    /* Ensure smooth connection of extrapolated and good frames     */
    /****************************************************************/
    silk_PLC_glue_frames( psDec, pOut, L );

    /* Update some decoder state variables */
    psDec->lagPrev = psDecCtrl->pitchL[ psDec->nb_subfr - 1 ];

    /* Set output frame length */
    *pN = L;

    RESTORE_STACK;
    return ret;
}
Example #23
0
opus_int silk_VAD_GetSA_Q8(                                     /* O    Return value, 0 if success                  */
    silk_encoder_state          *psEncC,                        /* I/O  Encoder state                               */
    const opus_int16            pIn[]                           /* I    PCM input                                   */
)
{
    opus_int   SA_Q15, pSNR_dB_Q7, input_tilt;
    opus_int   decimated_framelength1, decimated_framelength2;
    opus_int   decimated_framelength;
    opus_int   dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
    opus_int32 sumSquared, smooth_coef_Q16;
    opus_int16 HPstateTmp;
    VARDECL( opus_int16, X );
    opus_int32 Xnrg[ VAD_N_BANDS ];
    opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
    opus_int32 speech_nrg, x_tmp;
    opus_int   X_offset[ VAD_N_BANDS ];
    opus_int   ret = 0;
    silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
    SAVE_STACK;

    /* Safety checks */
    silk_assert( VAD_N_BANDS == 4 );
    silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
    silk_assert( psEncC->frame_length <= 512 );
    silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );

    /***********************/
    /* Filter and Decimate */
    /***********************/
    decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 );
    decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 );
    decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
    /* Decimate into 4 bands:
       0       L      3L       L              3L                             5L
               -      --       -              --                             --
               8       8       2               4                              4

       [0-1 kHz| temp. |1-2 kHz|    2-4 kHz    |            4-8 kHz           |

       They're arranged to allow the minimal ( frame_length / 4 ) extra
       scratch space during the downsampling process */
    X_offset[ 0 ] = 0;
    X_offset[ 1 ] = decimated_framelength + decimated_framelength2;
    X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength;
    X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2;
    ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 );

    /* 0-8 kHz to 0-4 kHz and 4-8 kHz */
    silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[  0 ],
        X, &X[ X_offset[ 3 ] ], psEncC->frame_length );

    /* 0-4 kHz to 0-2 kHz and 2-4 kHz */
    silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ],
        X, &X[ X_offset[ 2 ] ], decimated_framelength1 );

    /* 0-2 kHz to 0-1 kHz and 1-2 kHz */
    silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ],
        X, &X[ X_offset[ 1 ] ], decimated_framelength2 );

    /*********************************************/
    /* HP filter on lowest band (differentiator) */
    /*********************************************/
    X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 );
    HPstateTmp = X[ decimated_framelength - 1 ];
    for( i = decimated_framelength - 1; i > 0; i-- ) {
        X[ i - 1 ]  = silk_RSHIFT( X[ i - 1 ], 1 );
        X[ i ]     -= X[ i - 1 ];
    }
    X[ 0 ] -= psSilk_VAD->HPstate;
    psSilk_VAD->HPstate = HPstateTmp;

    /*************************************/
    /* Calculate the energy in each band */
    /*************************************/
    for( b = 0; b < VAD_N_BANDS; b++ ) {
        /* Find the decimated framelength in the non-uniformly divided bands */
        decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) );

        /* Split length into subframe lengths */
        dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
        dec_subframe_offset = 0;

        /* Compute energy per sub-frame */
        /* initialize with summed energy of last subframe */
        Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
        for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
            sumSquared = 0;
            for( i = 0; i < dec_subframe_length; i++ ) {
                /* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2.            */
                /* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128)  */
                x_tmp = silk_RSHIFT(
                    X[ X_offset[ b ] + i + dec_subframe_offset ], 3 );
                sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp );

                /* Safety check */
                silk_assert( sumSquared >= 0 );
            }

            /* Add/saturate summed energy of current subframe */
            if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
                Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
            } else {
                /* Look-ahead subframe */
                Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) );
            }

            dec_subframe_offset += dec_subframe_length;
        }
        psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
    }

    /********************/
    /* Noise estimation */
    /********************/
    silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );

    /***********************************************/
    /* Signal-plus-noise to noise ratio estimation */
    /***********************************************/
    sumSquared = 0;
    input_tilt = 0;
    for( b = 0; b < VAD_N_BANDS; b++ ) {
        speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
        if( speech_nrg > 0 ) {
            /* Divide, with sufficient resolution */
            if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
                NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
            } else {
                NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
            }

            /* Convert to log domain */
            SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;

            /* Sum-of-squares */
            sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 );          /* Q14 */

            /* Tilt measure */
            if( speech_nrg < ( (opus_int32)1 << 20 ) ) {
                /* Scale down SNR value for small subband speech energies */
                SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
            }
            input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
        } else {
            NrgToNoiseRatio_Q8[ b ] = 256;
        }
    }

    /* Mean-of-squares */
    sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */

    /* Root-mean-square approximation, scale to dBs, and write to output pointer */
    pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */

    /*********************************/
    /* Speech Probability Estimation */
    /*********************************/
    SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 );

    /**************************/
    /* Frequency Tilt Measure */
    /**************************/
    psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 );

    /**************************************************/
    /* Scale the sigmoid output based on power levels */
    /**************************************************/
    speech_nrg = 0;
    for( b = 0; b < VAD_N_BANDS; b++ ) {
        /* Accumulate signal-without-noise energies, higher frequency bands have more weight */
        speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
    }

    /* Power scaling */
    if( speech_nrg <= 0 ) {
        SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
    } else if( speech_nrg < 32768 ) {
        if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
            speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
        } else {
            speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
        }

        /* square-root */
        speech_nrg = silk_SQRT_APPROX( speech_nrg );
        SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 );
    }

    /* Copy the resulting speech activity in Q8 */
    psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX );

    /***********************************/
    /* Energy Level and SNR estimation */
    /***********************************/
    /* Smoothing coefficient */
    smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) );

    if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
        smooth_coef_Q16 >>= 1;
    }
Example #24
0
void lsp_to_lpc(const spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
/*  float *freq 	array of LSP frequencies in the x domain	*/
/*  float *ak 		array of LPC coefficients 			*/
/*  int lpcrdr  	order of LPC coefficients 			*/
{
    int i,j;
    spx_word32_t xout1,xout2,xin;
    spx_word32_t mult, a;
    VARDECL(spx_word16_t *freqn);
    VARDECL(spx_word32_t **xp);
    VARDECL(spx_word32_t *xpmem);
    VARDECL(spx_word32_t **xq);
    VARDECL(spx_word32_t *xqmem);
    int m = lpcrdr>>1;

    /* 
    
       Reconstruct P(z) and Q(z) by cascading second order polynomials
       in form 1 - 2cos(w)z(-1) + z(-2), where w is the LSP frequency.
       In the time domain this is:

       y(n) = x(n) - 2cos(w)x(n-1) + x(n-2)
    
       This is what the ALLOCS below are trying to do:

         int xp[m+1][lpcrdr+1+2]; // P matrix in QIMP
         int xq[m+1][lpcrdr+1+2]; // Q matrix in QIMP

       These matrices store the output of each stage on each row.  The
       final (m-th) row has the output of the final (m-th) cascaded
       2nd order filter.  The first row is the impulse input to the
       system (not written as it is known).

       The version below takes advantage of the fact that a lot of the
       outputs are zero or known, for example if we put an inpulse
       into the first section the "clock" it 10 times only the first 3
       outputs samples are non-zero (it's an FIR filter).
    */

    ALLOC(xp, (m+1), spx_word32_t*);
    ALLOC(xpmem, (m+1)*(lpcrdr+1+2), spx_word32_t);

    ALLOC(xq, (m+1), spx_word32_t*);
    ALLOC(xqmem, (m+1)*(lpcrdr+1+2), spx_word32_t);
    
    for(i=0; i<=m; i++) {
      xp[i] = xpmem + i*(lpcrdr+1+2);
      xq[i] = xqmem + i*(lpcrdr+1+2);
    }

    /* work out 2cos terms in Q14 */

    ALLOC(freqn, lpcrdr, spx_word16_t);
    for (i=0;i<lpcrdr;i++) 
       freqn[i] = ANGLE2X(freq[i]);

    #define QIMP  21   /* scaling for impulse */

    xin = SHL32(EXTEND32(1), (QIMP-1)); /* 0.5 in QIMP format */
   
    /* first col and last non-zero values of each row are trivial */
    
    for(i=0;i<=m;i++) {
     xp[i][1] = 0;
     xp[i][2] = xin;
     xp[i][2+2*i] = xin;
     xq[i][1] = 0;
     xq[i][2] = xin;
     xq[i][2+2*i] = xin;
    }

    /* 2nd row (first output row) is trivial */

    xp[1][3] = -MULT16_32_Q14(freqn[0],xp[0][2]);
    xq[1][3] = -MULT16_32_Q14(freqn[1],xq[0][2]);

    xout1 = xout2 = 0;

    /* now generate remaining rows */

    for(i=1;i<m;i++) {

      for(j=1;j<2*(i+1)-1;j++) {
	mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
	xp[i+1][j+2] = ADD32(SUB32(xp[i][j+2], mult), xp[i][j]);
	mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
	xq[i+1][j+2] = ADD32(SUB32(xq[i][j+2], mult), xq[i][j]);
      }

      /* for last col xp[i][j+2] = xq[i][j+2] = 0 */

      mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
      xp[i+1][j+2] = SUB32(xp[i][j], mult);
      mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
      xq[i+1][j+2] = SUB32(xq[i][j], mult);
    }

    /* process last row to extra a{k} */

    for(j=1;j<=lpcrdr;j++) {
      int shift = QIMP-13;

      /* final filter sections */
      a = PSHR32(xp[m][j+2] + xout1 + xq[m][j+2] - xout2, shift); 
      xout1 = xp[m][j+2];
      xout2 = xq[m][j+2];
      
      /* hard limit ak's to +/- 32767 */

      if (a < -32767) a = -32767;
      if (a > 32767) a = 32767;
      ak[j-1] = (short)a;
     
    }

}
int lpc_to_lsp (spx_coef_t *a,int lpcrdr,spx_lsp_t *freq,int nb,spx_word16_t delta, char *stack)
/*  float *a                  lpc coefficients            */
/*  int lpcrdr            order of LPC coefficients (10)         */
/*  float *freq               LSP frequencies in the x domain           */
/*  int nb            number of sub-intervals (4)         */
/*  float delta            grid spacing interval (0.02)         */


{
    spx_word16_t temp_xr,xl,xr,xm=0;
    spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/;
    int i,j,m,flag,k;
#ifndef FIXED_LPC_SIZE
    VARDECL(spx_word32_t *Q);                     /* ptrs for memory allocation         */
    VARDECL(spx_word32_t *P);
    VARDECL(spx_word16_t *Q16);         /* ptrs for memory allocation         */
    VARDECL(spx_word16_t *P16);
#else
    spx_word32_t Q[(FIXED_LPC_SIZE/2)+1];         /* ptrs for memory allocation         */
    spx_word32_t P[(FIXED_LPC_SIZE/2)+1];
    spx_word16_t Q16[(FIXED_LPC_SIZE/2)+1];       /* ptrs for memory allocation         */
    spx_word16_t P16[(FIXED_LPC_SIZE/2)+1];
#endif
    spx_word32_t *px;                    /* ptrs of respective P'(z) & Q'(z)    */
    spx_word32_t *qx;
    spx_word32_t *p;
    spx_word32_t *q;
    spx_word16_t *pt;                    /* ptr used for cheb_poly_eval()
                whether P' or Q'             */
    int roots=0;                  /* DR 8/2/94: number of roots found     */
    flag = 1;                    /*  program is searching for a root when,
                1 else has found one             */
    m = lpcrdr/2;                /* order of P'(z) & Q'(z) polynomials     */

#ifndef FIXED_LPC_SIZE
    /* Allocate memory space for polynomials */
    ALLOC(Q, (m+1), spx_word32_t);
    ALLOC(P, (m+1), spx_word32_t);
#endif

    /* determine P'(z)'s and Q'(z)'s coefficients where
      P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */

    px = P;                      /* initialise ptrs             */
    qx = Q;
    p = px;
    q = qx;

#ifdef FIXED_POINT
    *px++ = LPC_SCALING;
    *qx++ = LPC_SCALING;
#ifndef FIXED_LPC_SIZE
    for(i=0;i<m;i++){
       *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *p++);
       *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *q++);
    }
#else
    for(i=0;i<(FIXED_LPC_SIZE/2);i++){
       *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[FIXED_LPC_SIZE-i-1])), *p++);
       *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[FIXED_LPC_SIZE-i-1])), *q++);
    }
#endif
    px = P;
    qx = Q;
    for(i=0;i<m;i++)
    {
       /*if (fabs(*px)>=32768)
          speex_warning_int("px", *px);
       if (fabs(*qx)>=32768)
       speex_warning_int("qx", *qx);*/
       *px = PSHR32(*px,2);
       *qx = PSHR32(*qx,2);
       px++;
       qx++;
    }
    /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */
    P[m] = PSHR32(P[m],3);
    Q[m] = PSHR32(Q[m],3);
#else
    *px++ = LPC_SCALING;
    *qx++ = LPC_SCALING;
    for(i=0;i<m;i++){
       *px++ = (a[i]+a[lpcrdr-1-i]) - *p++;
       *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++;
    }
    px = P;
    qx = Q;
    for(i=0;i<m;i++){
       *px = 2**px;
       *qx = 2**qx;
       px++;
       qx++;
    }
#endif

    px = P;                 /* re-initialise ptrs             */
    qx = Q;

    /* now that we have computed P and Q convert to 16 bits to
       speed up cheb_poly_eval */

#ifndef FIXED_LPC_SIZE
    ALLOC(P16, m+1, spx_word16_t);
    ALLOC(Q16, m+1, spx_word16_t);
#endif

    for (i=0;i<m+1;i++)
    {
       P16[i] = P[i];
       Q16[i] = Q[i];
    }

    /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z).
    Keep alternating between the two polynomials as each zero is found     */

    xr = 0;                 /* initialise xr to zero         */
    xl = FREQ_SCALE;                   /* start at point xl = 1         */

    for(j=0;j<lpcrdr;j++){
    if(j&1)                /* determines whether P' or Q' is eval. */
        pt = Q16;
    else
        pt = P16;

    psuml = cheb_poly_eva(pt,xl,m,stack);    /* evals poly. at xl     */
    flag = 1;
    while(flag && (xr >= -FREQ_SCALE)){
           spx_word16_t dd;
           /* Modified by JMV to provide smaller steps around x=+-1 */
#ifdef FIXED_POINT
           dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000)));
           if (psuml<512 && psuml>-512)
              dd = PSHR16(dd,1);
#else
           dd=delta*(1-.9*xl*xl);
           if (fabs(psuml)<.2)
              dd *= .5;
#endif
           xr = SUB16(xl, dd);                            /* interval spacing     */
        psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x)     */
        temp_psumr = psumr;
        temp_xr = xr;

    /* if no sign change increment xr and re-evaluate poly(xr). Repeat til
    sign change.
    if a sign change has occurred the interval is bisected and then
    checked again for a sign change which determines in which
    interval the zero lies in.
    If there is no sign change between poly(xm) and poly(xl) set interval
    between xm and xr else set interval between xl and xr and repeat till
    root is located within the specified limits             */

        if(SIGN_CHANGE(psumr,psuml))
            {
        roots++;

        psumm=psuml;
        for(k=0;k<=nb;k++){
#ifdef FIXED_POINT
            xm = ADD16(PSHR16(xl,1),PSHR16(xr,1));            /* bisect the interval     */
#else
                    xm = .5*(xl+xr);            /* bisect the interval     */
#endif
            psumm=cheb_poly_eva(pt,xm,m,stack);
            /*if(psumm*psuml>0.)*/
            if(!SIGN_CHANGE(psumm,psuml))
                    {
            psuml=psumm;
            xl=xm;
            } else {
            psumr=psumm;
            xr=xm;
            }
        }

           /* once zero is found, reset initial interval to xr     */
           freq[j] = X2ANGLE(xm);
           xl = xm;
           flag = 0;               /* reset flag for next search     */
        }
        else{
        psuml=temp_psumr;
        xl=temp_xr;
        }
    }
    }
    return(roots);
}
Example #26
0
void split_cb_search_shape_sign(
spx_word16_t target[],			/* target vector */
spx_coef_t ak[],			/* LPCs for this subframe */
spx_coef_t awk1[],			/* Weighted LPCs for this subframe */
spx_coef_t awk2[],			/* Weighted LPCs for this subframe */
const void *par,                      /* Codebook/search parameters*/
int   p,                        /* number of LPC coeffs */
int   nsf,                      /* number of samples in subframe */
spx_sig_t *exc,
spx_word16_t *r,
SpeexBits *bits,
char *stack,
int   complexity,
int   update_target
)
{
   int i,j,k,m,n,q;
   VARDECL(spx_word16_t *resp);
#ifdef _USE_SSE
   VARDECL(__m128 *resp2);
   VARDECL(__m128 *E);
#else
   spx_word16_t *resp2;
   VARDECL(spx_word32_t *E);
#endif
   VARDECL(spx_word16_t *t);
   VARDECL(spx_sig_t *e);
   VARDECL(spx_word16_t *tmp);
   VARDECL(spx_word32_t *ndist);
   VARDECL(spx_word32_t *odist);
   VARDECL(int *itmp);
   VARDECL(spx_word16_t **ot2);
   VARDECL(spx_word16_t **nt2);
   spx_word16_t **ot, **nt;
   VARDECL(int **nind);
   VARDECL(int **oind);
   VARDECL(int *ind);
   const signed char *shape_cb;
   int shape_cb_size, subvect_size, nb_subvect;
   const split_cb_params *params;
   int N=2;
   VARDECL(int *best_index);
   VARDECL(spx_word32_t *best_dist);
   VARDECL(int *best_nind);
   VARDECL(int *best_ntarget);
   int have_sign;
   N=complexity;
   if (N>10)
      N=10;
   /* Complexity isn't as important for the codebooks as it is for the pitch */
   N=(2*N)/3;
   if (N<1)
      N=1;
   if (N==1)
   {
      split_cb_search_shape_sign_N1(target,ak,awk1,awk2,par,p,nsf,exc,r,bits,stack,update_target);
      return;
   }
   ALLOC(ot2, N, spx_word16_t*);
   ALLOC(nt2, N, spx_word16_t*);
   ALLOC(oind, N, int*);
   ALLOC(nind, N, int*);

   params = (const split_cb_params *) par;
   subvect_size = params->subvect_size;
   nb_subvect = params->nb_subvect;
   shape_cb_size = 1<<params->shape_bits;
   shape_cb = params->shape_cb;
   have_sign = params->have_sign;
   ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t);
#ifdef _USE_SSE
   ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128);
   ALLOC(E, shape_cb_size>>2, __m128);
#else
   resp2 = resp;
   ALLOC(E, shape_cb_size, spx_word32_t);
#endif
   ALLOC(t, nsf, spx_word16_t);
   ALLOC(e, nsf, spx_sig_t);
   ALLOC(ind, nb_subvect, int);

   ALLOC(tmp, 2*N*nsf, spx_word16_t);
   for (i=0;i<N;i++)
   {
      ot2[i]=tmp+2*i*nsf;
      nt2[i]=tmp+(2*i+1)*nsf;
   }
   ot=ot2;
   nt=nt2;
   ALLOC(best_index, N, int);
   ALLOC(best_dist, N, spx_word32_t);
   ALLOC(best_nind, N, int);
   ALLOC(best_ntarget, N, int);
   ALLOC(ndist, N, spx_word32_t);
   ALLOC(odist, N, spx_word32_t);
   
   ALLOC(itmp, 2*N*nb_subvect, int);
   for (i=0;i<N;i++)
   {
      nind[i]=itmp+2*i*nb_subvect;
      oind[i]=itmp+(2*i+1)*nb_subvect;
   }
   
   SPEEX_COPY(t, target, nsf);

   for (j=0;j<N;j++)
      SPEEX_COPY(&ot[j][0], t, nsf);

   /* Pre-compute codewords response and energy */
   compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack);

   for (j=0;j<N;j++)
      odist[j]=0;
   
   /*For all subvectors*/
   for (i=0;i<nb_subvect;i++)
   {
      /*"erase" nbest list*/
      for (j=0;j<N;j++)
         ndist[j]=VERY_LARGE32;
      /* This is not strictly necessary, but it provides an additonal safety 
         to prevent crashes in case something goes wrong in the previous
         steps (e.g. NaNs) */
      for (j=0;j<N;j++)
         best_nind[j] = best_ntarget[j] = 0;
      /*For all n-bests of previous subvector*/
      for (j=0;j<N;j++)
      {
         spx_word16_t *x=ot[j]+subvect_size*i;
         spx_word32_t tener = 0;
         for (m=0;m<subvect_size;m++)
            tener = MAC16_16(tener, x[m],x[m]);
#ifdef FIXED_POINT
         tener = SHR32(tener,1);
#else
         tener *= .5;
#endif
         /*Find new n-best based on previous n-best j*/
#ifndef DISABLE_WIDEBAND
         if (have_sign)
            vq_nbest_sign(x, resp2, subvect_size, shape_cb_size, E, N, best_index, best_dist, stack);
         else
#endif /* DISABLE_WIDEBAND */
            vq_nbest(x, resp2, subvect_size, shape_cb_size, E, N, best_index, best_dist, stack);

         /*For all new n-bests*/
         for (k=0;k<N;k++)
         {
            /* Compute total distance (including previous sub-vectors */
            spx_word32_t err = ADD32(ADD32(odist[j],best_dist[k]),tener);
            
            /*update n-best list*/
            if (err<ndist[N-1])
            {
               for (m=0;m<N;m++)
               {
                  if (err < ndist[m])
                  {
                     for (n=N-1;n>m;n--)
                     {
                        ndist[n] = ndist[n-1];
                        best_nind[n] = best_nind[n-1];
                        best_ntarget[n] = best_ntarget[n-1];
                     }
                     /* n is equal to m here, so they're interchangeable */
                     ndist[m] = err;
                     best_nind[n] = best_index[k];
                     best_ntarget[n] = j;
                     break;
                  }
               }
            }
         }
         if (i==0)
            break;
      }
      for (j=0;j<N;j++)
      {
         /*previous target (we don't care what happened before*/
         for (m=(i+1)*subvect_size;m<nsf;m++)
            nt[j][m]=ot[best_ntarget[j]][m];
         
         /* New code: update the rest of the target only if it's worth it */
         for (m=0;m<subvect_size;m++)
         {
            spx_word16_t g;
            int rind;
            spx_word16_t sign=1;
            rind = best_nind[j];
            if (rind>=shape_cb_size)
            {
               sign=-1;
               rind-=shape_cb_size;
            }

            q=subvect_size-m;
#ifdef FIXED_POINT
            g=sign*shape_cb[rind*subvect_size+m];
#else
            g=sign*0.03125*shape_cb[rind*subvect_size+m];
#endif
            target_update(nt[j]+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1));
         }

         for (q=0;q<nb_subvect;q++)
            nind[j][q]=oind[best_ntarget[j]][q];
         nind[j][i]=best_nind[j];
      }

      /*update old-new data*/
      /* just swap pointers instead of a long copy */
      {
         spx_word16_t **tmp2;
         tmp2=ot;
         ot=nt;
         nt=tmp2;
      }
      for (j=0;j<N;j++)
         for (m=0;m<nb_subvect;m++)
            oind[j][m]=nind[j][m];
      for (j=0;j<N;j++)
         odist[j]=ndist[j];
   }

   /*save indices*/
   for (i=0;i<nb_subvect;i++)
   {
      ind[i]=nind[0][i];
      speex_bits_pack(bits,ind[i],params->shape_bits+have_sign);
   }
   
   /* Put everything back together */
   for (i=0;i<nb_subvect;i++)
   {
      int rind;
      spx_word16_t sign=1;
      rind = ind[i];
      if (rind>=shape_cb_size)
      {
         sign=-1;
         rind-=shape_cb_size;
      }
#ifdef FIXED_POINT
      if (sign==1)
      {
         for (j=0;j<subvect_size;j++)
            e[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5);
      } else {
         for (j=0;j<subvect_size;j++)
            e[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5));
      }
#else
      for (j=0;j<subvect_size;j++)
         e[subvect_size*i+j]=sign*0.03125*shape_cb[rind*subvect_size+j];
#endif
   }   
   /* Update excitation */
   for (j=0;j<nsf;j++)
      exc[j]=ADD32(exc[j],e[j]);
   
   /* Update target: only update target if necessary */
   if (update_target)
   {
      VARDECL(spx_word16_t *r2);
      ALLOC(r2, nsf, spx_word16_t);
      for (j=0;j<nsf;j++)
         r2[j] = EXTRACT16(PSHR32(e[j] ,6));
      syn_percep_zero16(r2, ak, awk1, awk2, r2, nsf,p, stack);
      for (j=0;j<nsf;j++)
         target[j]=SUB16(target[j],PSHR16(r2[j],2));
   }
}
Example #27
0
static void split_cb_search_shape_sign_N1(
spx_word16_t target[],			/* target vector */
spx_coef_t ak[],			/* LPCs for this subframe */
spx_coef_t awk1[],			/* Weighted LPCs for this subframe */
spx_coef_t awk2[],			/* Weighted LPCs for this subframe */
const void *par,                      /* Codebook/search parameters*/
int   p,                        /* number of LPC coeffs */
int   nsf,                      /* number of samples in subframe */
spx_sig_t *exc,
spx_word16_t *r,
SpeexBits *bits,
char *stack,
int   update_target
)
{
   int i,j,m,q;
   VARDECL(spx_word16_t *resp);
#ifdef _USE_SSE
   VARDECL(__m128 *resp2);
   VARDECL(__m128 *E);
#else
   spx_word16_t *resp2;
   VARDECL(spx_word32_t *E);
#endif
   VARDECL(spx_word16_t *t);
   VARDECL(spx_sig_t *e);
   const signed char *shape_cb;
   int shape_cb_size, subvect_size, nb_subvect;
   const split_cb_params *params;
   int best_index;
   spx_word32_t best_dist;
   int have_sign;
   
   params = (const split_cb_params *) par;
   subvect_size = params->subvect_size;
   nb_subvect = params->nb_subvect;
   shape_cb_size = 1<<params->shape_bits;
   shape_cb = params->shape_cb;
   have_sign = params->have_sign;
   ALLOC(resp, shape_cb_size*subvect_size, spx_word16_t);
#ifdef _USE_SSE
   ALLOC(resp2, (shape_cb_size*subvect_size)>>2, __m128);
   ALLOC(E, shape_cb_size>>2, __m128);
#else
   resp2 = resp;
   ALLOC(E, shape_cb_size, spx_word32_t);
#endif
   ALLOC(t, nsf, spx_word16_t);
   ALLOC(e, nsf, spx_sig_t);
   
   /* FIXME: Do we still need to copy the target? */
   SPEEX_COPY(t, target, nsf);

   compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack);

   for (i=0;i<nb_subvect;i++)
   {
      spx_word16_t *x=t+subvect_size*i;
      /*Find new n-best based on previous n-best j*/
#ifndef DISABLE_WIDEBAND
      if (have_sign)
         vq_nbest_sign(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack);
      else
#endif /* DISABLE_WIDEBAND */
         vq_nbest(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack);
      
      speex_bits_pack(bits,best_index,params->shape_bits+have_sign);
      
      {
         int rind;
         spx_word16_t *res;
         spx_word16_t sign=1;
         rind = best_index;
         if (rind>=shape_cb_size)
         {
            sign=-1;
            rind-=shape_cb_size;
         }
         res = resp+rind*subvect_size;
         if (sign>0)
            for (m=0;m<subvect_size;m++)
               t[subvect_size*i+m] = SUB16(t[subvect_size*i+m], res[m]);
         else
            for (m=0;m<subvect_size;m++)
               t[subvect_size*i+m] = ADD16(t[subvect_size*i+m], res[m]);

#ifdef FIXED_POINT
         if (sign==1)
         {
            for (j=0;j<subvect_size;j++)
               e[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5);
         } else {
            for (j=0;j<subvect_size;j++)
               e[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[rind*subvect_size+j]),SIG_SHIFT-5));
         }
#else
         for (j=0;j<subvect_size;j++)
            e[subvect_size*i+j]=sign*0.03125*shape_cb[rind*subvect_size+j];
#endif
      
      }
            
      for (m=0;m<subvect_size;m++)
      {
         spx_word16_t g;
         int rind;
         spx_word16_t sign=1;
         rind = best_index;
         if (rind>=shape_cb_size)
         {
            sign=-1;
            rind-=shape_cb_size;
         }
         
         q=subvect_size-m;
#ifdef FIXED_POINT
         g=sign*shape_cb[rind*subvect_size+m];
#else
         g=sign*0.03125*shape_cb[rind*subvect_size+m];
#endif
         target_update(t+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1));
      }
   }

   /* Update excitation */
   /* FIXME: We could update the excitation directly above */
   for (j=0;j<nsf;j++)
      exc[j]=ADD32(exc[j],e[j]);
   
   /* Update target: only update target if necessary */
   if (update_target)
   {
      VARDECL(spx_word16_t *r2);
      ALLOC(r2, nsf, spx_word16_t);
      for (j=0;j<nsf;j++)
         r2[j] = EXTRACT16(PSHR32(e[j] ,6));
      syn_percep_zero16(r2, ak, awk1, awk2, r2, nsf,p, stack);
      for (j=0;j<nsf;j++)
         target[j]=SUB16(target[j],PSHR16(r2[j],2));
   }
}
void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
/*  float *freq     array of LSP frequencies in the x domain    */
/*  float *ak         array of LPC coefficients             */
/*  int lpcrdr      order of LPC coefficients             */
{
    int i,j;
    spx_word32_t xout1,xout2,xin;
    spx_word32_t mult, a;
    VARDECL(spx_word32_t *xpmem);
    VARDECL(spx_word32_t *xqmem);
#ifndef FIXED_LPC_SIZE
    VARDECL(spx_word16_t *freqn);
    VARDECL(spx_word32_t **xp);
    VARDECL(spx_word32_t **xq);
#else
    spx_word16_t freqn[FIXED_LPC_SIZE];
    spx_word32_t *xp[(FIXED_LPC_SIZE/2)+1];
    spx_word32_t *xq[(FIXED_LPC_SIZE/2)+1];
#endif

    int m = lpcrdr>>1;

    /*

       Reconstruct P(z) and Q(z) by cascading second order polynomials
       in form 1 - 2cos(w)z(-1) + z(-2), where w is the LSP frequency.
       In the time domain this is:

       y(n) = x(n) - 2cos(w)x(n-1) + x(n-2)

       This is what the ALLOCS below are trying to do:

         int xp[m+1][lpcrdr+1+2]; // P matrix in QIMP
         int xq[m+1][lpcrdr+1+2]; // Q matrix in QIMP

       These matrices store the output of each stage on each row.  The
       final (m-th) row has the output of the final (m-th) cascaded
       2nd order filter.  The first row is the impulse input to the
       system (not written as it is known).

       The version below takes advantage of the fact that a lot of the
       outputs are zero or known, for example if we put an inpulse
       into the first section the "clock" it 10 times only the first 3
       outputs samples are non-zero (it's an FIR filter).
    */

#ifndef FIXED_LPC_SIZE
    ALLOC(xp, (m+1), spx_word32_t*);
#endif
    ALLOC(xpmem, (m+1)*(lpcrdr+1+2), spx_word32_t);

#ifndef FIXED_LPC_SIZE
    ALLOC(xq, (m+1), spx_word32_t*);
#endif
    ALLOC(xqmem, (m+1)*(lpcrdr+1+2), spx_word32_t);

#ifndef FIXED_LPC_SIZE
    for(i=0; i<=m; i++) {
      xp[i] = xpmem + i*(lpcrdr+1+2);
      xq[i] = xqmem + i*(lpcrdr+1+2);
    }
#else
    for(i=0; i<=m; i++) {
      xp[i] = xpmem + i*(FIXED_LPC_SIZE+1+2);
      xq[i] = xqmem + i*(FIXED_LPC_SIZE+1+2);
    }
#endif
    /* work out 2cos terms in Q14 */

#ifndef FIXED_LPC_SIZE
    ALLOC(freqn, lpcrdr, spx_word16_t);
    for (i=0;i<lpcrdr;i++)
       freqn[i] = ANGLE2X(freq[i]);
#else
    for (i=0;i<FIXED_LPC_SIZE;i++)
       freqn[i] = ANGLE2X(freq[i]);
#endif

    #define QIMP  21   /* scaling for impulse */

    xin = SHL32(EXTEND32(1), (QIMP-1)); /* 0.5 in QIMP format */

    /* first col and last non-zero values of each row are trivial */

    for(i=0;i<=m;i++) {
     xp[i][1] = 0;
     xp[i][2] = xin;
     xp[i][2+2*i] = xin;
     xq[i][1] = 0;
     xq[i][2] = xin;
     xq[i][2+2*i] = xin;
    }

    /* 2nd row (first output row) is trivial */

    xp[1][3] = -MULT16_32_Q14(freqn[0],xp[0][2]);
    xq[1][3] = -MULT16_32_Q14(freqn[1],xq[0][2]);

    xout1 = xout2 = 0;

    /* now generate remaining rows */

    for(i=1;i<m;i++) {

      for(j=1;j<2*(i+1)-1;j++) {
    mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
    xp[i+1][j+2] = ADD32(SUB32(xp[i][j+2], mult), xp[i][j]);
    mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
    xq[i+1][j+2] = ADD32(SUB32(xq[i][j+2], mult), xq[i][j]);
      }

      /* for last col xp[i][j+2] = xq[i][j+2] = 0 */

      mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
      xp[i+1][j+2] = SUB32(xp[i][j], mult);
      mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
      xq[i+1][j+2] = SUB32(xq[i][j], mult);
    }

    /* process last row to extra a{k} */

#ifndef FIXED_LPC_SIZE
    for(j=1;j<=lpcrdr;j++) {
#else
    for(j=1;j<=FIXED_LPC_SIZE;j++) {
#endif
      int shift = QIMP-13;

      /* final filter sections */
      a = PSHR32(xp[m][j+2] + xout1 + xq[m][j+2] - xout2, shift);
      xout1 = xp[m][j+2];
      xout2 = xq[m][j+2];

      /* hard limit ak's to +/- 32767 */

      if (a < -32767) a = -32767;
      if (a > 32767) a = 32767;
      ak[j-1] = (short)a;

    }

}

#else

void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
/*  float *freq     array of LSP frequencies in the x domain    */
/*  float *ak         array of LPC coefficients             */
/*  int lpcrdr      order of LPC coefficients             */


{
    int i,j;
    float xout1,xout2,xin1,xin2;
    VARDECL(float *Wp);
    float *pw,*n1,*n2,*n3,*n4=NULL;
    VARDECL(float *x_freq);
    int m = lpcrdr>>1;

    ALLOC(Wp, 4*m+2, float);
    pw = Wp;

    /* initialise contents of array */

    for(i=0;i<=4*m+1;i++){           /* set contents of buffer to 0 */
    *pw++ = 0.0;
    }

    /* Set pointers up */

    pw = Wp;
    xin1 = 1.0;
    xin2 = 1.0;

    ALLOC(x_freq, lpcrdr, float);
    for (i=0;i<lpcrdr;i++)
       x_freq[i] = ANGLE2X(freq[i]);

    /* reconstruct P(z) and Q(z) by  cascading second order
      polynomials in form 1 - 2xz(-1) +z(-2), where x is the
      LSP coefficient */

    for(j=0;j<=lpcrdr;j++){
       int i2=0;
    for(i=0;i<m;i++,i2+=2){
        n1 = pw+(i*4);
        n2 = n1 + 1;
        n3 = n2 + 1;
        n4 = n3 + 1;
        xout1 = xin1 - 2.f*x_freq[i2] * *n1 + *n2;
        xout2 = xin2 - 2.f*x_freq[i2+1] * *n3 + *n4;
        *n2 = *n1;
        *n4 = *n3;
        *n1 = xin1;
        *n3 = xin2;
        xin1 = xout1;
        xin2 = xout2;
    }
    xout1 = xin1 + *(n4+1);
    xout2 = xin2 - *(n4+2);
    if (j>0)
       ak[j-1] = (xout1 + xout2)*0.5f;
    *(n4+1) = xin1;
    *(n4+2) = xin2;

    xin1 = 0.0;
    xin2 = 0.0;
    }

}
Example #29
0
static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
                             opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
{
    void *silk_dec;
    CELTDecoder *celt_dec;
    int i, silk_ret=0, celt_ret=0;
    ec_dec dec;
    opus_int32 silk_frame_size;
    int pcm_silk_size;
    VARDECL(opus_int16, pcm_silk);
    int pcm_transition_silk_size;
    VARDECL(opus_val16, pcm_transition_silk);
    int pcm_transition_celt_size;
    VARDECL(opus_val16, pcm_transition_celt);
    opus_val16 *pcm_transition=NULL;
    int redundant_audio_size;
    VARDECL(opus_val16, redundant_audio);

    int audiosize;
    int mode;
    int transition=0;
    int start_band;
    int redundancy=0;
    int redundancy_bytes = 0;
    int celt_to_silk=0;
    int c;
    int F2_5, F5, F10, F20;
    const opus_val16 *window;
    opus_uint32 redundant_rng = 0;
    int celt_accum;
    ALLOC_STACK;

    silk_dec = (char*)st+st->silk_dec_offset;
    celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
    F20 = st->Fs/50;
    F10 = F20>>1;
    F5 = F10>>1;
    F2_5 = F5>>1;
    if (frame_size < F2_5)
    {
        RESTORE_STACK;
        return OPUS_BUFFER_TOO_SMALL;
    }
    /* Limit frame_size to avoid excessive stack allocations. */
    frame_size = IMIN(frame_size, st->Fs/25*3);
    /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
    if (len<=1)
    {
        data = NULL;
        /* In that case, don't conceal more than what the ToC says */
        frame_size = IMIN(frame_size, st->frame_size);
    }
    if (data != NULL)
    {
        audiosize = st->frame_size;
        mode = st->mode;
        ec_dec_init(&dec,(unsigned char*)data,len);
    } else {
        audiosize = frame_size;
        mode = st->prev_mode;

        if (mode == 0)
        {
            /* If we haven't got any packet yet, all we can do is return zeros */
            for (i=0; i<audiosize*st->channels; i++)
                pcm[i] = 0;
            RESTORE_STACK;
            return audiosize;
        }

        /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT),
           10, or 20 (e.g. 12.5 or 30 ms). */
        if (audiosize > F20)
        {
            do {
                int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0);
                if (ret<0)
                {
                    RESTORE_STACK;
                    return ret;
                }
                pcm += ret*st->channels;
                audiosize -= ret;
            } while (audiosize > 0);
            RESTORE_STACK;
            return frame_size;
        } else if (audiosize < F20)
        {
            if (audiosize > F10)
                audiosize = F10;
            else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10)
                audiosize = F5;
        }
    }

    /* In fixed-point, we can tell CELT to do the accumulation on top of the
       SILK PCM buffer. This saves some stack space. */
#ifdef FIXED_POINT
    celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10);
#else
    celt_accum = 0;
#endif

    pcm_transition_silk_size = ALLOC_NONE;
    pcm_transition_celt_size = ALLOC_NONE;
    if (data!=NULL && st->prev_mode > 0 && (
                (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
                || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
       )
    {
        transition = 1;
        /* Decide where to allocate the stack memory for pcm_transition */
        if (mode == MODE_CELT_ONLY)
            pcm_transition_celt_size = F5*st->channels;
        else
            pcm_transition_silk_size = F5*st->channels;
    }
    ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16);
    if (transition && mode == MODE_CELT_ONLY)
    {
        pcm_transition = pcm_transition_celt;
        opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
    }
    if (audiosize > frame_size)
    {
        /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/
        RESTORE_STACK;
        return OPUS_BAD_ARG;
    } else {
        frame_size = audiosize;
    }

    /* Don't allocate any memory when in CELT-only mode */
    pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE;
    ALLOC(pcm_silk, pcm_silk_size, opus_int16);

    /* SILK processing */
    if (mode != MODE_CELT_ONLY)
    {
        int lost_flag, decoded_samples;
        opus_int16 *pcm_ptr;
#ifdef FIXED_POINT
        if (celt_accum)
            pcm_ptr = pcm;
        else
#endif
            pcm_ptr = pcm_silk;

        if (st->prev_mode==MODE_CELT_ONLY)
            silk_InitDecoder( silk_dec );

        /* The SILK PLC cannot produce frames of less than 10 ms */
        st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs);

        if (data != NULL)
        {
            st->DecControl.nChannelsInternal = st->stream_channels;
            if( mode == MODE_SILK_ONLY ) {
                if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
                    st->DecControl.internalSampleRate = 8000;
                } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
                    st->DecControl.internalSampleRate = 12000;
                } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
                    st->DecControl.internalSampleRate = 16000;
                } else {
                    st->DecControl.internalSampleRate = 16000;
                    silk_assert( 0 );
                }
            } else {
                /* Hybrid mode */
                st->DecControl.internalSampleRate = 16000;
            }
        }

        lost_flag = data == NULL ? 1 : 2 * decode_fec;
        decoded_samples = 0;
        do {
            /* Call SILK decoder */
            int first_frame = decoded_samples == 0;
            silk_ret = silk_Decode( silk_dec, &st->DecControl,
                                    lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size );
            if( silk_ret ) {
                if (lost_flag) {
                    /* PLC failure should not be fatal */
                    silk_frame_size = frame_size;
                    for (i=0; i<frame_size*st->channels; i++)
                        pcm_ptr[i] = 0;
                } else {
                    RESTORE_STACK;
                    return OPUS_INTERNAL_ERROR;
                }
            }
            pcm_ptr += silk_frame_size * st->channels;
            decoded_samples += silk_frame_size;
        } while( decoded_samples < frame_size );
    }

    start_band = 0;
    if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL
            && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len)
    {
        /* Check if we have a redundant 0-8 kHz band */
        if (mode == MODE_HYBRID)
            redundancy = ec_dec_bit_logp(&dec, 12);
        else
            redundancy = 1;
        if (redundancy)
        {
            celt_to_silk = ec_dec_bit_logp(&dec, 1);
            /* redundancy_bytes will be at least two, in the non-hybrid
               case due to the ec_tell() check above */
            redundancy_bytes = mode==MODE_HYBRID ?
                               (opus_int32)ec_dec_uint(&dec, 256)+2 :
                               len-((ec_tell(&dec)+7)>>3);
            len -= redundancy_bytes;
            /* This is a sanity check. It should never happen for a valid
               packet, so the exact behaviour is not normative. */
            if (len*8 < ec_tell(&dec))
            {
                len = 0;
                redundancy_bytes = 0;
                redundancy = 0;
            }
            /* Shrink decoder because of raw bits */
            dec.storage -= redundancy_bytes;
        }
    }
    if (mode != MODE_CELT_ONLY)
        start_band = 17;

    {
        int endband=21;

        switch(st->bandwidth)
        {
        case OPUS_BANDWIDTH_NARROWBAND:
            endband = 13;
            break;
        case OPUS_BANDWIDTH_MEDIUMBAND:
        case OPUS_BANDWIDTH_WIDEBAND:
            endband = 17;
            break;
        case OPUS_BANDWIDTH_SUPERWIDEBAND:
            endband = 19;
            break;
        case OPUS_BANDWIDTH_FULLBAND:
            endband = 21;
            break;
        }
        celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband));
        celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels));
    }

    if (redundancy)
    {
        transition = 0;
        pcm_transition_silk_size=ALLOC_NONE;
    }

    ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);

    if (transition && mode != MODE_CELT_ONLY)
    {
        pcm_transition = pcm_transition_silk;
        opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
    }

    /* Only allocation memory for redundancy if/when needed */
    redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
    ALLOC(redundant_audio, redundant_audio_size, opus_val16);

    /* 5 ms redundant frame for CELT->SILK*/
    if (redundancy && celt_to_silk)
    {
        celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
        celt_decode_with_ec(celt_dec, data+len, redundancy_bytes,
                            redundant_audio, F5, NULL, 0);
        celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
    }

    /* MUST be after PLC */
    celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band));

    if (mode != MODE_SILK_ONLY)
    {
        int celt_frame_size = IMIN(F20, frame_size);
        /* Make sure to discard any previous CELT state */
        if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
            celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
        /* Decode CELT */
        celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data,
                                       len, pcm, celt_frame_size, &dec, celt_accum);
    } else {
        unsigned char silence[2] = {0xFF, 0xFF};
        if (!celt_accum)
        {
            for (i=0; i<frame_size*st->channels; i++)
                pcm[i] = 0;
        }
        /* For hybrid -> SILK transitions, we let the CELT MDCT
           do a fade-out by decoding a silence frame */
        if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) )
        {
            celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
            celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum);
        }
    }

    if (mode != MODE_CELT_ONLY && !celt_accum)
    {
#ifdef FIXED_POINT
        for (i=0; i<frame_size*st->channels; i++)
            pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i]));
#else
        for (i=0; i<frame_size*st->channels; i++)
            pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]);
#endif
    }

    {
        const CELTMode *celt_mode;
        celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode));
        window = celt_mode->window;
    }

    /* 5 ms redundant frame for SILK->CELT */
    if (redundancy && !celt_to_silk)
    {
        celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
        celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));

        celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0);
        celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
        smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
                    pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
    }
    if (redundancy && celt_to_silk)
    {
        for (c=0; c<st->channels; c++)
        {
            for (i=0; i<F2_5; i++)
                pcm[st->channels*i+c] = redundant_audio[st->channels*i+c];
        }
        smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5,
                    pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs);
    }
    if (transition)
    {
        if (audiosize >= F5)
        {
            for (i=0; i<st->channels*F2_5; i++)
                pcm[i] = pcm_transition[i];
            smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
                        pcm+st->channels*F2_5, F2_5,
                        st->channels, window, st->Fs);
        } else {
            /* Not enough time to do a clean transition, but we do it anyway
               This will not preserve amplitude perfectly and may introduce
               a bit of temporal aliasing, but it shouldn't be too bad and
               that's pretty much the best we can do. In any case, generating this
               transition it pretty silly in the first place */
            smooth_fade(pcm_transition, pcm,
                        pcm, F2_5,
                        st->channels, window, st->Fs);
        }
    }

    if(st->decode_gain)
    {
        opus_val32 gain;
        gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain));
        for (i=0; i<frame_size*st->channels; i++)
        {
            opus_val32 x;
            x = MULT16_32_P16(pcm[i],gain);
            pcm[i] = SATURATE(x, 32767);
        }
    }

    if (len <= 1)
        st->rangeFinal = 0;
    else
        st->rangeFinal = dec.rng ^ redundant_rng;

    st->prev_mode = mode;
    st->prev_redundancy = redundancy && !celt_to_silk;

    if (celt_ret>=0)
    {
        if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels))
            OPUS_PRINT_INT(audiosize);
    }

    RESTORE_STACK;
    return celt_ret < 0 ? celt_ret : audiosize;

}
Example #30
0
void silk_prefilter_FIX(
    silk_encoder_state_FIX          *psEnc,                                 /* I/O  Encoder state                                                               */
    const silk_encoder_control_FIX  *psEncCtrl,                             /* I    Encoder control                                                             */
    opus_int32                      xw_Q3[],                                /* O    Weighted signal                                                             */
    const opus_int16                x[]                                     /* I    Speech signal                                                               */
)
{
    silk_prefilter_state_FIX *P = &psEnc->sPrefilt;
    opus_int   j, k, lag;
    opus_int32 tmp_32;
    const opus_int16 *AR1_shp_Q13;
    const opus_int16 *px;
    opus_int32 *pxw_Q3;
    opus_int   HarmShapeGain_Q12, Tilt_Q14;
    opus_int32 HarmShapeFIRPacked_Q12, LF_shp_Q14;
    VARDECL( opus_int32, x_filt_Q12 );
    VARDECL( opus_int32, st_res_Q2 );
    opus_int16 B_Q10[ 2 ];
    SAVE_STACK;

    /* Set up pointers */
    px  = x;
    pxw_Q3 = xw_Q3;
    lag = P->lagPrev;
    ALLOC( x_filt_Q12, psEnc->sCmn.subfr_length, opus_int32 );
    ALLOC( st_res_Q2, psEnc->sCmn.subfr_length, opus_int32 );
    for( k = 0; k < psEnc->sCmn.nb_subfr; k++ ) {
        /* Update Variables that change per sub frame */
        if( psEnc->sCmn.indices.signalType == TYPE_VOICED ) {
            lag = psEncCtrl->pitchL[ k ];
        }

        /* Noise shape parameters */
        HarmShapeGain_Q12 = silk_SMULWB( (opus_int32)psEncCtrl->HarmShapeGain_Q14[ k ], 16384 - psEncCtrl->HarmBoost_Q14[ k ] );
        silk_assert( HarmShapeGain_Q12 >= 0 );
        HarmShapeFIRPacked_Q12  =                          silk_RSHIFT( HarmShapeGain_Q12, 2 );
        HarmShapeFIRPacked_Q12 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q12, 1 ), 16 );
        Tilt_Q14    = psEncCtrl->Tilt_Q14[   k ];
        LF_shp_Q14  = psEncCtrl->LF_shp_Q14[ k ];
        AR1_shp_Q13 = &psEncCtrl->AR1_Q13[   k * MAX_SHAPE_LPC_ORDER ];

        /* Short term FIR filtering*/
        silk_warped_LPC_analysis_filter_FIX( P->sAR_shp, st_res_Q2, AR1_shp_Q13, px,
            psEnc->sCmn.warping_Q16, psEnc->sCmn.subfr_length, psEnc->sCmn.shapingLPCOrder );

        /* Reduce (mainly) low frequencies during harmonic emphasis */
        B_Q10[ 0 ] = silk_RSHIFT_ROUND( psEncCtrl->GainsPre_Q14[ k ], 4 );
        tmp_32 = silk_SMLABB( SILK_FIX_CONST( INPUT_TILT, 26 ), psEncCtrl->HarmBoost_Q14[ k ], HarmShapeGain_Q12 );   /* Q26 */
        tmp_32 = silk_SMLABB( tmp_32, psEncCtrl->coding_quality_Q14, SILK_FIX_CONST( HIGH_RATE_INPUT_TILT, 12 ) );    /* Q26 */
        tmp_32 = silk_SMULWB( tmp_32, -psEncCtrl->GainsPre_Q14[ k ] );                                                /* Q24 */
        tmp_32 = silk_RSHIFT_ROUND( tmp_32, 14 );                                                                     /* Q10 */
        B_Q10[ 1 ]= silk_SAT16( tmp_32 );
        x_filt_Q12[ 0 ] = silk_MLA( silk_MUL( st_res_Q2[ 0 ], B_Q10[ 0 ] ), P->sHarmHP_Q2, B_Q10[ 1 ] );
        for( j = 1; j < psEnc->sCmn.subfr_length; j++ ) {
            x_filt_Q12[ j ] = silk_MLA( silk_MUL( st_res_Q2[ j ], B_Q10[ 0 ] ), st_res_Q2[ j - 1 ], B_Q10[ 1 ] );
        }
        P->sHarmHP_Q2 = st_res_Q2[ psEnc->sCmn.subfr_length - 1 ];

        silk_prefilt_FIX( P, x_filt_Q12, pxw_Q3, HarmShapeFIRPacked_Q12, Tilt_Q14, LF_shp_Q14, lag, psEnc->sCmn.subfr_length );

        px  += psEnc->sCmn.subfr_length;
        pxw_Q3 += psEnc->sCmn.subfr_length;
    }

    P->lagPrev = psEncCtrl->pitchL[ psEnc->sCmn.nb_subfr - 1 ];
    RESTORE_STACK;
}