ref: b03e0534d7d2ab306b584296bf0af011db85bf55
dir: /amr-wb/isp_az.c/
/*-----------------------------------------------------------------------* * ISP_AZ.C * *-----------------------------------------------------------------------* * Compute the LPC coefficients from isp (order=M) * *-----------------------------------------------------------------------*/ #include "typedef.h" #include "basic_op.h" #include "oper_32b.h" #include "count.h" #include "cnst.h" #define NC (M/2) #define NC16k (M16k/2) /* local function */ static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n); static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n); void Isp_Az( Word16 isp[], /* (i) Q15 : Immittance spectral pairs */ Word16 a[], /* (o) Q12 : predictor coefficients (order = M) */ Word16 m, Word16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */ /* 1 : adaptive scaling enabled */ ) { Word16 i, j, hi, lo; Word32 f1[NC16k + 1], f2[NC16k]; Word16 nc; Word32 t0; Word16 q, q_sug; Word32 tmax; nc = shr(m, 1); test(); if (sub(nc, 8) > 0) { Get_isp_pol_16kHz(&isp[0], f1, nc); for (i = 0; i <= nc; i++) { f1[i] = L_shl(f1[i], 2); move32(); } } else Get_isp_pol(&isp[0], f1, nc); test(); if (sub(nc, 8) > 0) { Get_isp_pol_16kHz(&isp[1], f2, sub(nc, 1)); for (i = 0; i <= nc - 1; i++) { f2[i] = L_shl(f2[i], 2); move32(); } } else Get_isp_pol(&isp[1], f2, sub(nc, 1)); /*-----------------------------------------------------* * Multiply F2(z) by (1 - z^-2) * *-----------------------------------------------------*/ for (i = sub(nc, 1); i > 1; i--) { f2[i] = L_sub(f2[i], f2[i - 2]); move32(); /* f2[i] -= f2[i-2]; */ } /*----------------------------------------------------------* * Scale F1(z) by (1+isp[m-1]) and F2(z) by (1-isp[m-1]) * *----------------------------------------------------------*/ for (i = 0; i < nc; i++) { /* f1[i] *= (1.0 + isp[M-1]); */ L_Extract(f1[i], &hi, &lo); t0 = Mpy_32_16(hi, lo, isp[m - 1]); f1[i] = L_add(f1[i], t0); move32(); /* f2[i] *= (1.0 - isp[M-1]); */ L_Extract(f2[i], &hi, &lo); t0 = Mpy_32_16(hi, lo, isp[m - 1]); f2[i] = L_sub(f2[i], t0); move32(); } /*-----------------------------------------------------* * A(z) = (F1(z)+F2(z))/2 * * F1(z) is symmetric and F2(z) is antisymmetric * *-----------------------------------------------------*/ /* a[0] = 1.0; */ a[0] = 4096; move16(); tmax = 1; move32(); for (i = 1, j = sub(m, 1); i < nc; i++, j--) { /* a[i] = 0.5*(f1[i] + f2[i]); */ t0 = L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ tmax |= L_abs(t0); logic32(); a[i] = extract_l(L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */ move16(); /* a[j] = 0.5*(f1[i] - f2[i]); */ t0 = L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ tmax |= L_abs(t0); logic32(); a[j] = extract_l(L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */ move16(); } /* rescale data if overflow has occured and reprocess the loop */ test(); if ( sub(adaptive_scaling, 1) == 0 ) q = sub(4, norm_l(tmax)); /* adaptive scaling enabled */ else q = 0; move16(); /* adaptive scaling disabled */ test(); if (q > 0) { q_sug = add(12, q); for (i = 1, j = sub(m, 1); i < nc; i++, j--) { /* a[i] = 0.5*(f1[i] + f2[i]); */ t0 = L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ a[i] = extract_l(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ move16(); /* a[j] = 0.5*(f1[i] - f2[i]); */ t0 = L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ a[j] = extract_l(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ move16(); } a[0] = shr(a[0], q); move16(); } else { q_sug = 12; move16(); q = 0; move16(); } /* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */ L_Extract(f1[nc], &hi, &lo); t0 = Mpy_32_16(hi, lo, isp[m - 1]); t0 = L_add(f1[nc], t0); a[nc] = extract_l(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ move16(); /* a[m] = isp[m-1]; */ a[m] = shr_r(isp[m - 1], add(3,q)); /* from Q15 to Q12 */ move16(); return; } /*-----------------------------------------------------------* * procedure Get_isp_pol: * * ~~~~~~~~~~~ * * Find the polynomial F1(z) or F2(z) from the ISPs. * * This is performed by expanding the product polynomials: * * * * F1(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) * * i=0,2,4,6,8 * * F2(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) * * i=1,3,5,7 * * * * where isp_i are the ISPs in the cosine domain. * *-----------------------------------------------------------* * * * Parameters: * * isp[] : isp vector (cosine domaine) in Q15 * * f[] : the coefficients of F1 or F2 in Q23 * * n : == NC for F1(z); == NC-1 for F2(z) * *-----------------------------------------------------------*/ static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n) { Word16 i, j, hi, lo; Word32 t0; /* All computation in Q23 */ f[0] = L_mult(4096, 1024); move32(); /* f[0] = 1.0; in Q23 */ f[1] = L_mult(isp[0], -256); move32(); /* f[1] = -2.0*isp[0] in Q23 */ f += 2; move32(); /* Advance f pointer */ isp += 2; move16(); /* Advance isp pointer */ for (i = 2; i <= n; i++) { *f = f[-2]; move32(); for (j = 1; j < i; j++, f--) { L_Extract(f[-1], &hi, &lo); t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */ t0 = L_shl(t0, 1); *f = L_sub(*f, t0); move32(); /* *f -= t0 */ *f = L_add(*f, f[-2]); move32(); /* *f += f[-2] */ } *f = L_msu(*f, *isp, 256); move32(); /* *f -= isp<<8 */ f += i; /* Advance f pointer */ isp += 2; /* Advance isp pointer */ } return; } static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n) { Word16 i, j, hi, lo; Word32 t0; /* All computation in Q23 */ f[0] = L_mult(4096, 256); move32(); /* f[0] = 1.0; in Q23 */ f[1] = L_mult(isp[0], -64); move32(); /* f[1] = -2.0*isp[0] in Q23 */ f += 2; move32(); /* Advance f pointer */ isp += 2; move16(); /* Advance isp pointer */ for (i = 2; i <= n; i++) { *f = f[-2]; move32(); for (j = 1; j < i; j++, f--) { L_Extract(f[-1], &hi, &lo); t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */ t0 = L_shl(t0, 1); *f = L_sub(*f, t0); move32(); /* *f -= t0 */ *f = L_add(*f, f[-2]); move32(); /* *f += f[-2] */ } *f = L_msu(*f, *isp, 64); move32(); /* *f -= isp<<8 */ f += i; /* Advance f pointer */ isp += 2; /* Advance isp pointer */ } return; }