void split_cb_shape_sign_unquant( spx_sig_t *exc, const void *par, /* non-overlapping codebook */ int nsf, /* number of samples in subframe */ SpeexBits *bits, char *stack, spx_int32_t *seed ) { int i,j; VARDECL(int *ind); VARDECL(int *signs); const signed char *shape_cb; //int shape_cb_size; int subvect_size, nb_subvect; const split_cb_params *params; 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(ind, nb_subvect, int); ALLOC(signs, nb_subvect, int); /* Decode codewords and gains */ for (i=0;i<nb_subvect;i++) { if (have_sign) signs[i] = speex_bits_unpack_unsigned(bits, 1); else signs[i] = 0; ind[i] = speex_bits_unpack_unsigned(bits, params->shape_bits); } /* Compute decoded excitation */ for (i=0;i<nb_subvect;i++) { spx_word16_t s=1; if (signs[i]) s=-1; #ifdef FIXED_POINT if (s==1) { for (j=0;j<subvect_size;j++) exc[subvect_size*i+j]=SHL32(EXTEND32(shape_cb[ind[i]*subvect_size+j]),SIG_SHIFT-5); } else { for (j=0;j<subvect_size;j++) exc[subvect_size*i+j]=NEG32(SHL32(EXTEND32(shape_cb[ind[i]*subvect_size+j]),SIG_SHIFT-5)); } #else for (j=0;j<subvect_size;j++) exc[subvect_size*i+j]+=s*0.03125*shape_cb[ind[i]*subvect_size+j]; #endif } }
EXPORT int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr) { switch(request) { case SPEEX_ECHO_GET_FRAME_SIZE: (*(int*)ptr) = st->frame_size; break; case SPEEX_ECHO_SET_SAMPLING_RATE: st->sampling_rate = (*(int*)ptr); st->spec_average = DIV32_16(SHL32(EXTEND32(st->frame_size), 15), st->sampling_rate); #ifdef FIXED_POINT st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate); st->beta_max = DIV32_16(SHL32(EXTEND32(st->frame_size), 14), st->sampling_rate); #else st->beta0 = (2.0f*st->frame_size)/st->sampling_rate; st->beta_max = (.5f*st->frame_size)/st->sampling_rate; #endif if (st->sampling_rate<12000) st->notch_radius = QCONST16(.9, 15); else if (st->sampling_rate<24000) st->notch_radius = QCONST16(.982, 15); else st->notch_radius = QCONST16(.992, 15); break; case SPEEX_ECHO_GET_SAMPLING_RATE: (*(int*)ptr) = st->sampling_rate; break; case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE: /*FIXME: Implement this for multiple channels */ *((spx_int32_t *)ptr) = st->M * st->frame_size; break; case SPEEX_ECHO_GET_IMPULSE_RESPONSE: { int M = st->M, N = st->window_size, n = st->frame_size, i, j; spx_int32_t *filt = (spx_int32_t *) ptr; for(j=0;j<M;j++) { /*FIXME: Implement this for multiple channels */ #ifdef FIXED_POINT for (i=0;i<N;i++) st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN)); spx_ifft(st->fft_table, st->wtmp2, st->wtmp); #else spx_ifft(st->fft_table, &st->W[j*N], st->wtmp); #endif for(i=0;i<n;i++) filt[j*n+i] = PSHR32(MULT16_16(32767,st->wtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN); } } break; default: speex_warning_int("Unknown speex_echo_ctl request: ", request); return -1; } return 0; }
static void kf_bfly2( kiss_fft_cpx * Fout, const size_t fstride, const kiss_fft_cfg st, int m, int N, int mm ) { kiss_fft_cpx * Fout2; kiss_fft_cpx * tw1; kiss_fft_cpx t; if (!st->inverse) { int i,j; kiss_fft_cpx * Fout_beg = Fout; for (i=0;i<N;i++) { Fout = Fout_beg + i*mm; Fout2 = Fout + m; tw1 = st->twiddles; for(j=0;j<m;j++) { /* Almost the same as the code path below, except that we divide the input by two (while keeping the best accuracy possible) */ ms_word32_t tr, ti; tr = SHR32(SUB32(MULT16_16(Fout2->r , tw1->r),MULT16_16(Fout2->i , tw1->i)), 1); ti = SHR32(ADD32(MULT16_16(Fout2->i , tw1->r),MULT16_16(Fout2->r , tw1->i)), 1); tw1 += fstride; Fout2->r = PSHR32(SUB32(SHL32(EXTEND32(Fout->r), 14), tr), 15); Fout2->i = PSHR32(SUB32(SHL32(EXTEND32(Fout->i), 14), ti), 15); Fout->r = PSHR32(ADD32(SHL32(EXTEND32(Fout->r), 14), tr), 15); Fout->i = PSHR32(ADD32(SHL32(EXTEND32(Fout->i), 14), ti), 15); ++Fout2; ++Fout; } } } else { int i,j; kiss_fft_cpx * Fout_beg = Fout; for (i=0;i<N;i++) { Fout = Fout_beg + i*mm; Fout2 = Fout + m; tw1 = st->twiddles; for(j=0;j<m;j++) { C_MUL (t, *Fout2 , *tw1); tw1 += fstride; C_SUB( *Fout2 , *Fout , t ); C_ADDTO( *Fout , t ); ++Fout2; ++Fout; } } } }
static void bmw_small_f2(uint32_t* h, uint32_t* q, const void* m){ uint32_t xl=0, xh; uint8_t i; for(i=16;i<24;++i){ xl ^= q[i]; } xh = xl; for(i=24;i<32;++i){ xh ^= q[i]; } #if DEBUG cli_putstr("\r\n XL = "); cli_hexdump_rev(&xl, 4); cli_putstr("\r\n XH = "); cli_hexdump_rev(&xh, 4); #endif memcpy(h, m, 16*4); h[0] ^= SHL32(xh, 5) ^ SHR32(q[16], 5); h[1] ^= SHR32(xh, 7) ^ SHL32(q[17], 8); h[2] ^= SHR32(xh, 5) ^ SHL32(q[18], 5); h[3] ^= SHR32(xh, 1) ^ SHL32(q[19], 5); h[4] ^= SHR32(xh, 3) ^ q[20]; h[5] ^= SHL32(xh, 6) ^ SHR32(q[21], 6); h[6] ^= SHR32(xh, 4) ^ SHL32(q[22], 6); h[7] ^= SHR32(xh,11) ^ SHL32(q[23], 2); for(i=0; i<8; ++i){ h[i] += xl ^ q[24+i] ^ q[i]; } for(i=0; i<8; ++i){ h[8+i] ^= xh ^ q[24+i]; h[8+i] += ROTL32(h[(4+i)%8],i+9); } /* h[ 8] += SHL32(xl, 8) ^ q[23] ^ q[ 8]; h[ 9] += SHR32(xl, 6) ^ q[16] ^ q[ 9]; h[10] += SHL32(xl, 6) ^ q[17] ^ q[10]; h[11] += SHL32(xl, 4) ^ q[18] ^ q[11]; h[12] += SHR32(xl, 3) ^ q[19] ^ q[12]; h[13] += SHR32(xl, 4) ^ q[20] ^ q[13]; h[14] += SHR32(xl, 7) ^ q[21] ^ q[14]; h[15] += SHR32(xl, 2) ^ q[22] ^ q[15]; */ memxor(q+9, q+16, 7*4); q[8] ^= q[23]; h[ 8] += SHL32(xl, 8) ^ q[ 8]; h[ 9] += SHR32(xl, 6) ^ q[ 9]; h[10] += SHL32(xl, 6) ^ q[10]; h[11] += SHL32(xl, 4) ^ q[11]; h[12] += SHR32(xl, 3) ^ q[12]; h[13] += SHR32(xl, 4) ^ q[13]; h[14] += SHR32(xl, 7) ^ q[14]; h[15] += SHR32(xl, 2) ^ q[15]; }
void clt_mdct_init(mdct_lookup *l,int N) { int i; int N2; l->n = N; N2 = N>>1; l->kfft = cpx32_fft_alloc(N>>2); #ifndef ENABLE_TI_DSPLIB55 if (l->kfft==NULL) return; #endif l->trig = (kiss_twiddle_scalar*)celt_alloc(N2*sizeof(kiss_twiddle_scalar)); if (l->trig==NULL) return; /* We have enough points that sine isn't necessary */ #if defined(FIXED_POINT) #if defined(DOUBLE_PRECISION) & !defined(MIXED_PRECISION) for (i=0;i<N2;i++) l->trig[i] = SAMP_MAX*cos(2*M_PI*(i+1./8.)/N); #else for (i=0;i<N2;i++) l->trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),16386),N)); #endif #else for (i=0;i<N2;i++) l->trig[i] = cos(2*M_PI*(i+1./8.)/N); #endif }
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); }
void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes) { #ifndef FIXED_LPC_SIZE int i; #endif spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes); spx_word16_t tmp2 = 16384-tmp; #ifndef FIXED_LPC_SIZE for (i=0;i<len;i++) { interp_lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]); } #else interp_lsp[0] = MULT16_16_P14(tmp2,old_lsp[0]) + MULT16_16_P14(tmp,new_lsp[0]); interp_lsp[1] = MULT16_16_P14(tmp2,old_lsp[1]) + MULT16_16_P14(tmp,new_lsp[1]); interp_lsp[2] = MULT16_16_P14(tmp2,old_lsp[2]) + MULT16_16_P14(tmp,new_lsp[2]); interp_lsp[3] = MULT16_16_P14(tmp2,old_lsp[3]) + MULT16_16_P14(tmp,new_lsp[3]); interp_lsp[4] = MULT16_16_P14(tmp2,old_lsp[4]) + MULT16_16_P14(tmp,new_lsp[4]); interp_lsp[5] = MULT16_16_P14(tmp2,old_lsp[5]) + MULT16_16_P14(tmp,new_lsp[5]); interp_lsp[6] = MULT16_16_P14(tmp2,old_lsp[6]) + MULT16_16_P14(tmp,new_lsp[6]); interp_lsp[7] = MULT16_16_P14(tmp2,old_lsp[7]) + MULT16_16_P14(tmp,new_lsp[7]); interp_lsp[8] = MULT16_16_P14(tmp2,old_lsp[8]) + MULT16_16_P14(tmp,new_lsp[8]); interp_lsp[9] = MULT16_16_P14(tmp2,old_lsp[9]) + MULT16_16_P14(tmp,new_lsp[9]); #endif }
static void celt_fir5(opus_val16 *x, const opus_val16 *num, int N) { int i; opus_val16 num0, num1, num2, num3, num4; opus_val32 mem0, mem1, mem2, mem3, mem4; num0=num[0]; num1=num[1]; num2=num[2]; num3=num[3]; num4=num[4]; mem0=0; mem1=0; mem2=0; mem3=0; mem4=0; for (i=0;i<N;i++) { opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT); sum = MAC16_16(sum,num0,mem0); sum = MAC16_16(sum,num1,mem1); sum = MAC16_16(sum,num2,mem2); sum = MAC16_16(sum,num3,mem3); sum = MAC16_16(sum,num4,mem4); mem4 = mem3; mem3 = mem2; mem2 = mem1; mem1 = mem0; mem0 = x[i]; x[i] = ROUND16(sum, SIG_SHIFT); } }
static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len) { const int N = st->filt_len; int out_sample = 0; int last_sample = st->last_sample[channel_index]; spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; const int out_stride = st->out_stride; const int int_advance = st->int_advance; const int frac_advance = st->frac_advance; const spx_uint32_t den_rate = st->den_rate; spx_word32_t sum; while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len)) { const spx_word16_t *iptr = & in[last_sample]; const int offset = samp_frac_num*st->oversample/st->den_rate; #ifdef FIXED_POINT const spx_word16_t frac = PDIV32(SHL32((samp_frac_num*st->oversample) % st->den_rate,15),st->den_rate); #else const spx_word16_t frac = ((float)((samp_frac_num*st->oversample) % st->den_rate))/st->den_rate; #endif spx_word16_t interp[4]; #ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE int j; spx_word32_t accum[4] = {0,0,0,0}; for(j=0;j<N;j++) { const spx_word16_t curr_in=iptr[j]; accum[0] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-2]); accum[1] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset-1]); accum[2] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset]); accum[3] += MULT16_16(curr_in,st->sinc_table[4+(j+1)*st->oversample-offset+1]); } cubic_coef(frac, interp); sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1)); sum = SATURATE32PSHR(sum, 15, 32767); #else cubic_coef(frac, interp); sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp); #endif out[out_stride * out_sample++] = sum; last_sample += int_advance; samp_frac_num += frac_advance; if (samp_frac_num >= den_rate) { samp_frac_num -= den_rate; last_sample++; } } st->last_sample[channel_index] = last_sample; st->samp_frac_num[channel_index] = samp_frac_num; return out_sample; }
void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes) { int i; spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes); spx_word16_t tmp2 = 16384-tmp; for (i=0;i<len;i++) { interp_lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]); } }
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; }
void mlp_process(const MLP * m, const opus_val16 * in, opus_val16 * out) { int j; opus_val16 hidden[MAX_NEURONS]; const opus_val16 *W = m->weights; /* Copy to tmp_in */ for (j = 0; j < m->topo[1]; j++) { int k; opus_val32 sum = SHL32(EXTEND32(*W++), 8); for (k = 0; k < m->topo[0]; k++) sum = MAC16_16(sum, in[k], *W++); hidden[j] = tansig_approx(sum); } for (j = 0; j < m->topo[2]; j++) { int k; opus_val32 sum = SHL32(EXTEND32(*W++), 14); for (k = 0; k < m->topo[1]; k++) sum = MAC16_16(sum, hidden[k], *W++); out[j] = tansig_approx(EXTRACT16(PSHR32(sum, 17))); } }
void _celt_lpc( opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */ const opus_val32 *ac, /* in: [0...p] autocorrelation values */ int p ) { int i, j; opus_val32 r; opus_val32 error = ac[0]; #ifdef OPUS_FIXED_POINT opus_val32 lpc[LPC_ORDER]; #else float *lpc = _lpc; #endif for (i = 0; i < p; i++) lpc[i] = 0; if (ac[0] != 0) { for (i = 0; i < p; i++) { /* Sum up this iteration's reflection coefficient */ opus_val32 rr = 0; for (j = 0; j < i; j++) rr += MULT32_32_Q31(lpc[j],ac[i - j]); rr += SHR32(ac[i + 1],3); r = -frac_div32(SHL32(rr,3), error); /* Update LPC coefficients and total error */ lpc[i] = SHR32(r,3); for (j = 0; j < (i+1)>>1; j++) { opus_val32 tmp1, tmp2; tmp1 = lpc[j]; tmp2 = lpc[i-1-j]; lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2); lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1); } error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error); /* Bail out once we get 30 dB gain */ #ifdef OPUS_FIXED_POINT if (error<SHR32(ac[0],10)) break; #else if (error<.001f*ac[0]) break; #endif } } #ifdef OPUS_FIXED_POINT for (i=0;i<p;i++) _lpc[i] = ROUND16(lpc[i],16); #endif }
void noise_codebook_unquant( spx_sig_t *exc, const void *par, /* non-overlapping codebook */ int nsf, /* number of samples in subframe */ SpeexBits *bits, char *stack, spx_int32_t *seed ) { int i; /* FIXME: This is bad, but I don't think the function ever gets called anyway */ for (i=0;i<nsf;i++) exc[i]=SHL32(EXTEND32(speex_rand(1, seed)),SIG_SHIFT); }
static inline void filter_dc_notch16(const spx_int16_t *in, spx_word16_t radius, spx_word16_t *out, int len, spx_mem_t *mem, int stride) { int i; spx_word16_t den2; #ifdef FIXED_POINT den2 = MULT16_16_Q15(radius,radius) + MULT16_16_Q15(QCONST16(.7,15),MULT16_16_Q15(32767-radius,32767-radius)); #else den2 = radius*radius + .7*(1-radius)*(1-radius); #endif /*printf ("%d %d %d %d %d %d\n", num[0], num[1], num[2], den[0], den[1], den[2]);*/ for (i=0;i<len;i++) { spx_word16_t vin = in[i*stride]; spx_word32_t vout = mem[0] + SHL32(EXTEND32(vin),15); #ifdef FIXED_POINT mem[0] = mem[1] + SHL32(SHL32(-EXTEND32(vin),15) + MULT16_32_Q15(radius,vout),1); #else mem[0] = mem[1] + 2*(-vin + radius*vout); #endif mem[1] = SHL32(EXTEND32(vin),15) - MULT16_32_Q15(den2,vout); out[i] = SATURATE32(PSHR32(MULT16_32_Q15(radius,vout),15),32767); } }
static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft) { int i; #ifdef FIXED_POINT for (i=0;i<nfft;++i) { opus_val32 phase = -i; kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft)); } #else for (i=0;i<nfft;++i) { const double pi=3.14159265358979323846264338327; double phase = ( -2*pi /nfft ) * i; kf_cexp(twiddles+i, phase ); } #endif }
/* returns minimum mean square error */ spx_word32_t _spx_lpc( spx_coef_t *lpc, /* out: [0...p-1] LPC coefficients */ const spx_word16_t *ac, /* in: [0...p] autocorrelation values */ int p ) { int i, j; spx_word16_t r; spx_word16_t error = ac[0]; if (ac[0] == 0) { for (i = 0; i < p; i++) lpc[i] = 0; return 0; } for (i = 0; i < p; i++) { /* Sum up this iteration's reflection coefficient */ spx_word32_t rr = NEG32(SHL32(EXTEND32(ac[i + 1]),13)); for (j = 0; j < i; j++) rr = SUB32(rr,MULT16_16(lpc[j],ac[i - j])); #ifdef FIXED_POINT r = DIV32_16(rr+PSHR32(error,1),ADD16(error,8)); #else r = rr/(error+.003*ac[0]); #endif /* Update LPC coefficients and total error */ lpc[i] = r; for (j = 0; j < i>>1; j++) { spx_word16_t tmp = lpc[j]; lpc[j] = MAC16_16_P13(lpc[j],r,lpc[i-1-j]); lpc[i-1-j] = MAC16_16_P13(lpc[i-1-j],r,tmp); } if (i & 1) lpc[j] = MAC16_16_P13(lpc[j],lpc[j],r); error = SUB16(error,MULT16_16_Q13(r,MULT16_16_Q13(error,r))); } return error; }
void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *lsp, int len, int subframe, int nb_subframes, spx_word16_t margin) { int i; spx_word16_t m = margin; spx_word16_t m2 = 25736-margin; spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes); spx_word16_t tmp2 = 16384-tmp; for (i=0;i<len;i++) lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]); /* Enforce margin to sure the LSPs are stable*/ if (lsp[0]<m) lsp[0]=m; if (lsp[len-1]>m2) lsp[len-1]=m2; for (i=1;i<len-1;i++) { if (lsp[i]<lsp[i-1]+m) lsp[i]=lsp[i-1]+m; if (lsp[i]>lsp[i+1]-m) lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1); } }
/* * * User-callable function to allocate all necessary storage space for the fft. * * The return value is a contiguous block of memory, allocated with malloc. As such, * It can be freed with free(), rather than a kiss_fft-specific function. * */ kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem ) { kiss_fft_cfg st=NULL; size_t memneeded = sizeof(struct kiss_fft_state) + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/ if ( lenmem==NULL ) { st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); }else{ if (mem != NULL && *lenmem >= memneeded) st = (kiss_fft_cfg)mem; *lenmem = memneeded; } if (st) { int i; st->nfft=nfft; st->inverse = inverse_fft; #ifdef MS_FIXED_POINT for (i=0;i<nfft;++i) { ms_word32_t phase = i; if (!st->inverse) phase = -phase; kf_cexp2(st->twiddles+i, DIV32(SHL32(phase,17),nfft)); } #else for (i=0;i<nfft;++i) { const double pi=3.14159265358979323846264338327; double phase = ( -2*pi /nfft ) * i; if (st->inverse) phase *= -1; kf_cexp(st->twiddles+i, phase ); } #endif kf_factor(nfft,st->factors); } return st; }
void celt_fir(const opus_val16 *x, const opus_val16 *num, opus_val16 *y, int N, int ord, opus_val16 *mem) { int i,j; for (i=0;i<N;i++) { opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT); for (j=0;j<ord;j++) { sum += MULT16_16(num[j],mem[j]); } for (j=ord-1;j>=1;j--) { mem[j]=mem[j-1]; } mem[0] = x[i]; y[i] = ROUND16(sum, SIG_SHIFT); } }
void pitch_unquant_3tap( spx_word16_t exc[], /* Input excitation */ spx_word32_t exc_out[], /* Output excitation */ int start, /* Smallest pitch value allowed */ int end, /* Largest pitch value allowed */ spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ const void* par, int nsf, /* Number of samples in subframe */ int* pitch_val, spx_word16_t* gain_val, SpeexBits* bits, char* stack, int count_lost, int subframe_offset, spx_word16_t last_pitch_gain, int cdbk_offset ) { int i; int pitch; int gain_index; spx_word16_t gain[3]; const signed char* gain_cdbk; int gain_cdbk_size; const ltp_params* params; params = (const ltp_params*) par; gain_cdbk_size = 1 << params->gain_bits; gain_cdbk = params->gain_cdbk + 4 * gain_cdbk_size * cdbk_offset; pitch = speex_bits_unpack_unsigned(bits, params->pitch_bits); pitch += start; gain_index = speex_bits_unpack_unsigned(bits, params->gain_bits); /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/ #ifdef FIXED_POINT gain[0] = ADD16(32, (spx_word16_t)gain_cdbk[gain_index * 4]); gain[1] = ADD16(32, (spx_word16_t)gain_cdbk[gain_index * 4 + 1]); gain[2] = ADD16(32, (spx_word16_t)gain_cdbk[gain_index * 4 + 2]); #else gain[0] = 0.015625 * gain_cdbk[gain_index * 4] + .5; gain[1] = 0.015625 * gain_cdbk[gain_index * 4 + 1] + .5; gain[2] = 0.015625 * gain_cdbk[gain_index * 4 + 2] + .5; #endif if (count_lost && pitch > subframe_offset) { spx_word16_t gain_sum; if (1) { #ifdef FIXED_POINT spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : SHR16(last_pitch_gain, 1); if (tmp > 62) tmp = 62; #else spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : 0.5 * last_pitch_gain; if (tmp > .95) tmp = .95; #endif gain_sum = gain_3tap_to_1tap(gain); if (gain_sum > tmp) { spx_word16_t fact = DIV32_16(SHL32(EXTEND32(tmp), 14), gain_sum); for (i = 0; i < 3; i++) gain[i] = MULT16_16_Q14(fact, gain[i]); } } } *pitch_val = pitch; gain_val[0] = gain[0]; gain_val[1] = gain[1]; gain_val[2] = gain[2]; gain[0] = SHL16(gain[0], 7); gain[1] = SHL16(gain[1], 7); gain[2] = SHL16(gain[2], 7); SPEEX_MEMSET(exc_out, 0, nsf); for (i = 0; i < 3; i++) { int j; int tmp1, tmp3; int pp = pitch + 1 - i; tmp1 = nsf; if (tmp1 > pp) tmp1 = pp; for (j = 0; j < tmp1; j++) exc_out[j] = MAC16_16(exc_out[j], gain[2 - i], exc[j - pp]); tmp3 = nsf; if (tmp3 > pp + pitch) tmp3 = pp + pitch; for (j = tmp1; j < tmp3; j++) exc_out[j] = MAC16_16(exc_out[j], gain[2 - i], exc[j - pp - pitch]); } /*for (i=0;i<nsf;i++) exc[i]=PSHR32(exc32[i],13);*/ }
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; }
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,m,q; const signed char *shape_cb; int shape_cb_size = 32, subvect_size = 10; int best_index; spx_word32_t best_dist; spx_word16_t resp[320]; spx_word16_t *resp2 = resp; spx_word32_t E[32]; spx_word16_t t[40]; spx_sig_t e[40]; shape_cb=exc_10_32_table; /* FIXME: Do we still need to copy the target? */ SPEEX_COPY(t, target, nsf); //compute_weighted_codebook { int i, k; spx_word16_t shape[10]; 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 */ { spx_word32_t resj; spx_word16_t res16; // 0 resj = MULT16_16(shape[0],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[0] = res16; //++++++++++++++++++++++++++ // 1 resj = MULT16_16(shape[0],r[1]); resj = MAC16_16(resj,shape[1],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[1] = res16; //++++++++++++++++++++++++++ // 2 resj = MULT16_16(shape[0],r[2]); resj = MAC16_16(resj,shape[1],r[1]); resj = MAC16_16(resj,shape[2],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[2] = res16; //++++++++++++++++++++++++++ // 3 resj = MULT16_16(shape[0],r[3]); resj = MAC16_16(resj,shape[1],r[2]); resj = MAC16_16(resj,shape[2],r[1]); resj = MAC16_16(resj,shape[3],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[3] = res16; //++++++++++++++++++++++++++ // 4 resj = MULT16_16(shape[0],r[4]); resj = MAC16_16(resj,shape[1],r[3]); resj = MAC16_16(resj,shape[2],r[2]); resj = MAC16_16(resj,shape[3],r[1]); resj = MAC16_16(resj,shape[4],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[4] = res16; //++++++++++++++++++++++++++ // 5 resj = MULT16_16(shape[0],r[5]); resj = MAC16_16(resj,shape[1],r[4]); resj = MAC16_16(resj,shape[2],r[3]); resj = MAC16_16(resj,shape[3],r[2]); resj = MAC16_16(resj,shape[4],r[1]); resj = MAC16_16(resj,shape[5],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[5] = res16; //++++++++++++++++++++++++++ // 6 resj = MULT16_16(shape[0],r[6]); resj = MAC16_16(resj,shape[1],r[5]); resj = MAC16_16(resj,shape[2],r[4]); resj = MAC16_16(resj,shape[3],r[3]); resj = MAC16_16(resj,shape[4],r[2]); resj = MAC16_16(resj,shape[5],r[1]); resj = MAC16_16(resj,shape[6],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[6] = res16; //++++++++++++++++++++++++++ // 7 resj = MULT16_16(shape[0],r[7]); resj = MAC16_16(resj,shape[1],r[6]); resj = MAC16_16(resj,shape[2],r[5]); resj = MAC16_16(resj,shape[3],r[4]); resj = MAC16_16(resj,shape[4],r[3]); resj = MAC16_16(resj,shape[5],r[2]); resj = MAC16_16(resj,shape[6],r[1]); resj = MAC16_16(resj,shape[7],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[7] = res16; //++++++++++++++++++++++++++ // 8 resj = MULT16_16(shape[0],r[8]); resj = MAC16_16(resj,shape[1],r[7]); resj = MAC16_16(resj,shape[2],r[6]); resj = MAC16_16(resj,shape[3],r[5]); resj = MAC16_16(resj,shape[4],r[4]); resj = MAC16_16(resj,shape[5],r[3]); resj = MAC16_16(resj,shape[6],r[2]); resj = MAC16_16(resj,shape[7],r[1]); resj = MAC16_16(resj,shape[8],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[8] = res16; //++++++++++++++++++++++++++ // 9 resj = MULT16_16(shape[0],r[9]); resj = MAC16_16(resj,shape[1],r[8]); resj = MAC16_16(resj,shape[2],r[7]); resj = MAC16_16(resj,shape[3],r[6]); resj = MAC16_16(resj,shape[4],r[5]); resj = MAC16_16(resj,shape[5],r[4]); resj = MAC16_16(resj,shape[6],r[3]); resj = MAC16_16(resj,shape[7],r[2]); resj = MAC16_16(resj,shape[8],r[1]); resj = MAC16_16(resj,shape[9],r[0]); res16 = EXTRACT16(SHR32(resj, 13)); // Compute codeword energy E[i]=MAC16_16(E[i],res16,res16); res[9] = res16; //++++++++++++++++++++++++++ } } } for (i=0;i<4;i++) { spx_word16_t *x=t+subvect_size*i; /*Find new n-best based on previous n-best j*/ vq_nbest(x, resp2, subvect_size, shape_cb_size, E, 1, &best_index, &best_dist, stack); speex_bits_pack(bits,best_index,5); { 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]); 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)); } } 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; g=sign*shape_cb[rind*subvect_size+m]; 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]); }
/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ static spx_word32_t pitch_gain_search_3tap( const spx_word16_t target[], /* Target vector */ const spx_coef_t ak[], /* LPCs for this subframe */ const spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ const spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ spx_sig_t exc[], /* Excitation */ const signed char* gain_cdbk, int gain_cdbk_size, int pitch, /* Pitch value */ int p, /* Number of LPC coeffs */ int nsf, /* Number of samples in subframe */ SpeexBits* bits, char* stack, const spx_word16_t* exc2, const spx_word16_t* r, spx_word16_t* new_target, int* cdbk_index, int plc_tuning, spx_word32_t cumul_gain, int scaledown ) { int i, j; VARDECL(spx_word16_t * tmp1); VARDECL(spx_word16_t * e); spx_word16_t* x[3]; spx_word32_t corr[3]; spx_word32_t A[3][3]; spx_word16_t gain[3]; spx_word32_t err; spx_word16_t max_gain = 128; int best_cdbk = 0; ALLOC(tmp1, 3 * nsf, spx_word16_t); ALLOC(e, nsf, spx_word16_t); if (cumul_gain > 262144) max_gain = 31; x[0] = tmp1; x[1] = tmp1 + nsf; x[2] = tmp1 + 2 * nsf; for (j = 0; j < nsf; j++) new_target[j] = target[j]; { VARDECL(spx_mem_t * mm); int pp = pitch - 1; ALLOC(mm, p, spx_mem_t); for (j = 0; j < nsf; j++) { if (j - pp < 0) e[j] = exc2[j - pp]; else if (j - pp - pitch < 0) e[j] = exc2[j - pp - pitch]; else e[j] = 0; } #ifdef FIXED_POINT /* Scale target and excitation down if needed (avoiding overflow) */ if (scaledown) { for (j = 0; j < nsf; j++) e[j] = SHR16(e[j], 1); for (j = 0; j < nsf; j++) new_target[j] = SHR16(new_target[j], 1); } #endif for (j = 0; j < p; j++) mm[j] = 0; iir_mem16(e, ak, e, nsf, p, mm, stack); for (j = 0; j < p; j++) mm[j] = 0; filter_mem16(e, awk1, awk2, e, nsf, p, mm, stack); for (j = 0; j < nsf; j++) x[2][j] = e[j]; } for (i = 1; i >= 0; i--) { spx_word16_t e0 = exc2[-pitch - 1 + i]; #ifdef FIXED_POINT /* Scale excitation down if needed (avoiding overflow) */ if (scaledown) e0 = SHR16(e0, 1); #endif x[i][0] = MULT16_16_Q14(r[0], e0); for (j = 0; j < nsf - 1; j++) x[i][j + 1] = ADD32(x[i + 1][j], MULT16_16_P14(r[j + 1], e0)); } for (i = 0; i < 3; i++) corr[i] = inner_prod(x[i], new_target, nsf); for (i = 0; i < 3; i++) for (j = 0; j <= i; j++) A[i][j] = A[j][i] = inner_prod(x[i], x[j], nsf); { spx_word32_t C[9]; #ifdef FIXED_POINT spx_word16_t C16[9]; #else spx_word16_t* C16 = C; #endif C[0] = corr[2]; C[1] = corr[1]; C[2] = corr[0]; C[3] = A[1][2]; C[4] = A[0][1]; C[5] = A[0][2]; C[6] = A[2][2]; C[7] = A[1][1]; C[8] = A[0][0]; /*plc_tuning *= 2;*/ if (plc_tuning < 2) plc_tuning = 2; if (plc_tuning > 30) plc_tuning = 30; #ifdef FIXED_POINT C[0] = SHL32(C[0], 1); C[1] = SHL32(C[1], 1); C[2] = SHL32(C[2], 1); C[3] = SHL32(C[3], 1); C[4] = SHL32(C[4], 1); C[5] = SHL32(C[5], 1); C[6] = MAC16_32_Q15(C[6], MULT16_16_16(plc_tuning, 655), C[6]); C[7] = MAC16_32_Q15(C[7], MULT16_16_16(plc_tuning, 655), C[7]); C[8] = MAC16_32_Q15(C[8], MULT16_16_16(plc_tuning, 655), C[8]); normalize16(C, C16, 32767, 9); #else C[6] *= .5 * (1 + .02 * plc_tuning); C[7] *= .5 * (1 + .02 * plc_tuning); C[8] *= .5 * (1 + .02 * plc_tuning); #endif best_cdbk = pitch_gain_search_3tap_vq(gain_cdbk, gain_cdbk_size, C16, max_gain); #ifdef FIXED_POINT gain[0] = ADD16(32, (spx_word16_t)gain_cdbk[best_cdbk * 4]); gain[1] = ADD16(32, (spx_word16_t)gain_cdbk[best_cdbk * 4 + 1]); gain[2] = ADD16(32, (spx_word16_t)gain_cdbk[best_cdbk * 4 + 2]); /*printf ("%d %d %d %d\n",gain[0],gain[1],gain[2], best_cdbk);*/ #else gain[0] = 0.015625 * gain_cdbk[best_cdbk * 4] + .5; gain[1] = 0.015625 * gain_cdbk[best_cdbk * 4 + 1] + .5; gain[2] = 0.015625 * gain_cdbk[best_cdbk * 4 + 2] + .5; #endif *cdbk_index = best_cdbk; } SPEEX_MEMSET(exc, 0, nsf); for (i = 0; i < 3; i++) { int j; int tmp1, tmp3; int pp = pitch + 1 - i; tmp1 = nsf; if (tmp1 > pp) tmp1 = pp; for (j = 0; j < tmp1; j++) exc[j] = MAC16_16(exc[j], SHL16(gain[2 - i], 7), exc2[j - pp]); tmp3 = nsf; if (tmp3 > pp + pitch) tmp3 = pp + pitch; for (j = tmp1; j < tmp3; j++) exc[j] = MAC16_16(exc[j], SHL16(gain[2 - i], 7), exc2[j - pp - pitch]); } for (i = 0; i < nsf; i++) { spx_word32_t tmp = ADD32(ADD32(MULT16_16(gain[0], x[2][i]), MULT16_16(gain[1], x[1][i])), MULT16_16(gain[2], x[0][i])); new_target[i] = SUB16(new_target[i], EXTRACT16(PSHR32(tmp, 6))); } err = inner_prod(new_target, new_target, nsf); return err; }
void open_loop_nbest_pitch(spx_word16_t* sw, int start, int end, int len, int* pitch, spx_word16_t* gain, int N, char* stack) { int i, j, k; VARDECL(spx_word32_t * best_score); VARDECL(spx_word32_t * best_ener); spx_word32_t e0; VARDECL(spx_word32_t * corr); #ifdef FIXED_POINT /* In fixed-point, we need only one (temporary) array of 32-bit values and two (corr16, ener16) arrays for (normalized) 16-bit values */ VARDECL(spx_word16_t * corr16); VARDECL(spx_word16_t * ener16); spx_word32_t* energy; int cshift = 0, eshift = 0; int scaledown = 0; ALLOC(corr16, end - start + 1, spx_word16_t); ALLOC(ener16, end - start + 1, spx_word16_t); ALLOC(corr, end - start + 1, spx_word32_t); energy = corr; #else /* In floating-point, we need to float arrays and no normalized copies */ VARDECL(spx_word32_t * energy); spx_word16_t* corr16; spx_word16_t* ener16; ALLOC(energy, end - start + 2, spx_word32_t); ALLOC(corr, end - start + 1, spx_word32_t); corr16 = corr; ener16 = energy; #endif ALLOC(best_score, N, spx_word32_t); ALLOC(best_ener, N, spx_word32_t); for (i = 0; i < N; i++) { best_score[i] = -1; best_ener[i] = 0; pitch[i] = start; } #ifdef FIXED_POINT for (i = -end; i < len; i++) { if (ABS16(sw[i]) > 16383) { scaledown = 1; break; } } /* If the weighted input is close to saturation, then we scale it down */ if (scaledown) { for (i = -end; i < len; i++) { sw[i] = SHR16(sw[i], 1); } } #endif energy[0] = inner_prod(sw - start, sw - start, len); e0 = inner_prod(sw, sw, len); for (i = start; i < end; i++) { /* Update energy for next pitch*/ energy[i - start + 1] = SUB32(ADD32(energy[i - start], SHR32(MULT16_16(sw[-i - 1], sw[-i - 1]), 6)), SHR32(MULT16_16(sw[-i + len - 1], sw[-i + len - 1]), 6)); if (energy[i - start + 1] < 0) energy[i - start + 1] = 0; } #ifdef FIXED_POINT eshift = normalize16(energy, ener16, 32766, end - start + 1); #endif /* In fixed-point, this actually overrites the energy array (aliased to corr) */ pitch_xcorr(sw, sw - end, corr, len, end - start + 1, stack); #ifdef FIXED_POINT /* Normalize to 180 so we can square it and it still fits in 16 bits */ cshift = normalize16(corr, corr16, 180, end - start + 1); /* If we scaled weighted input down, we need to scale it up again (OK, so we've just lost the LSB, who cares?) */ if (scaledown) { for (i = -end; i < len; i++) { sw[i] = SHL16(sw[i], 1); } } #endif /* Search for the best pitch prediction gain */ for (i = start; i <= end; i++) { spx_word16_t tmp = MULT16_16_16(corr16[i - start], corr16[i - start]); /* Instead of dividing the tmp by the energy, we multiply on the other side */ if (MULT16_16(tmp, best_ener[N - 1]) > MULT16_16(best_score[N - 1], ADD16(1, ener16[i - start]))) { /* We can safely put it last and then check */ best_score[N - 1] = tmp; best_ener[N - 1] = ener16[i - start] + 1; pitch[N - 1] = i; /* Check if it comes in front of others */ for (j = 0; j < N - 1; j++) { if (MULT16_16(tmp, best_ener[j]) > MULT16_16(best_score[j], ADD16(1, ener16[i - start]))) { for (k = N - 1; k > j; k--) { best_score[k] = best_score[k - 1]; best_ener[k] = best_ener[k - 1]; pitch[k] = pitch[k - 1]; } best_score[j] = tmp; best_ener[j] = ener16[i - start] + 1; pitch[j] = i; break; } } } } /* Compute open-loop gain if necessary */ if (gain) { for (j = 0; j < N; j++) { spx_word16_t g; i = pitch[j]; g = DIV32(SHL32(EXTEND32(corr16[i - start]), cshift), 10 + SHR32(MULT16_16(spx_sqrt(e0), spx_sqrt(SHL32(EXTEND32(ener16[i - start]), eshift))), 6)); /* FIXME: g = max(g,corr/energy) */ if (g < 0) g = 0; gain[j] = g; } } }
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; } }
FilterBank *filterbank_new(int banks, spx_word32_t sampling, int len, int type) { FilterBank *bank; spx_word32_t df; spx_word32_t max_mel, mel_interval; int i; int id1; int id2; df = DIV32(SHL32(sampling,15),MULT16_16(2,len)); max_mel = toBARK(EXTRACT16(sampling/2)); mel_interval = PDIV32(max_mel,banks-1); bank = (FilterBank*)speex_alloc(sizeof(FilterBank)); bank->nb_banks = banks; bank->len = len; bank->bank_left = (int*)speex_alloc(len*sizeof(int)); bank->bank_right = (int*)speex_alloc(len*sizeof(int)); bank->filter_left = (spx_word16_t*)speex_alloc(len*sizeof(spx_word16_t)); bank->filter_right = (spx_word16_t*)speex_alloc(len*sizeof(spx_word16_t)); /* Think I can safely disable normalisation that for fixed-point (and probably float as well) */ #ifndef FIXED_POINT bank->scaling = (float*)speex_alloc(banks*sizeof(float)); #endif for (i=0;i<len;i++) { spx_word16_t curr_freq; spx_word32_t mel; spx_word16_t val; curr_freq = EXTRACT16(MULT16_32_P15(i,df)); mel = toBARK(curr_freq); if (mel > max_mel) break; #ifdef FIXED_POINT id1 = DIV32(mel,mel_interval); #else id1 = (int)(floor(mel/mel_interval)); #endif if (id1>banks-2) { id1 = banks-2; val = Q15_ONE; } else { val = DIV32_16(mel - id1*mel_interval,EXTRACT16(PSHR32(mel_interval,15))); } id2 = id1+1; bank->bank_left[i] = id1; bank->filter_left[i] = SUB16(Q15_ONE,val); bank->bank_right[i] = id2; bank->filter_right[i] = val; } /* Think I can safely disable normalisation for fixed-point (and probably float as well) */ #ifndef FIXED_POINT for (i=0;i<bank->nb_banks;i++) bank->scaling[i] = 0; for (i=0;i<bank->len;i++) { int id = bank->bank_left[i]; bank->scaling[id] += bank->filter_left[i]; id = bank->bank_right[i]; bank->scaling[id] += bank->filter_right[i]; } for (i=0;i<bank->nb_banks;i++) bank->scaling[i] = Q15_ONE/(bank->scaling[i]); #endif return bank; }
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)); } }
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; } }