static inline spx_word32_t cheb_poly_eva( spx_word16_t *coef, /* P or Q coefs in Q13 format */ spx_word16_t x, /* cos of freq (-1.0 to 1.0) in Q14 format */ int m, /* LPC order/2 */ char *stack ) { int i; spx_word16_t b0, b1; spx_word32_t sum; /*Prevents overflows*/ if (x>16383) x = 16383; if (x<-16383) x = -16383; /* Initialise values */ b1=16384; b0=x; /* Evaluate Chebyshev series formulation usin g iterative approach */ sum = ADD32(EXTEND32(coef[m]), EXTEND32(MULT16_16_P14(coef[m-1],x))); for(i=2;i<=m;i++) { spx_word16_t tmp=b0; b0 = SUB16(MULT16_16_Q13(x,b0), b1); b1 = tmp; sum = ADD32(sum, EXTEND32(MULT16_16_P14(coef[m-i],b0))); } return sum; }
void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *_stereo) { int i; spx_word32_t balance; spx_word16_t e_left, e_right, e_ratio; RealSpeexStereoState *stereo = (RealSpeexStereoState*)_stereo; /* COMPATIBILITY_HACK(stereo); */ balance=stereo->balance; e_ratio=stereo->e_ratio; /* These two are Q14, with max value just below 2. */ e_right = DIV32(QCONST32(1., 22), spx_sqrt(MULT16_32_Q15(e_ratio, ADD32(QCONST32(1., 16), balance)))); e_left = SHR32(MULT16_16(spx_sqrt(balance), e_right), 8); for (i=frame_size-1;i>=0;i--) { spx_int16_t tmp=data[i]; stereo->smooth_left = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_left, QCONST16(0.98, 15)), e_left, QCONST16(0.02, 15)), 15)); stereo->smooth_right = EXTRACT16(PSHR32(MAC16_16(MULT16_16(stereo->smooth_right, QCONST16(0.98, 15)), e_right, QCONST16(0.02, 15)), 15)); data[2*i] = (spx_int16_t)MULT16_16_P14(stereo->smooth_left, tmp); data[2*i+1] = (spx_int16_t)MULT16_16_P14(stereo->smooth_right, tmp); } }
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(SHL(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]); } }
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; spx_word16_t *T; spx_word32_t sum; int m2=m>>1; spx_word16_t *coefn; /*Prevents overflows*/ if (x>16383) x = 16383; if (x<-16383) x = -16383; /* Allocate memory for Chebyshev series formulation */ T=PUSH(stack, m2+1, spx_word16_t); coefn=PUSH(stack, 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] = 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; }
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); } }
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 }
/** 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; }