| /* |
| ** Copyright 2003-2010, VisualOn, Inc. |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| /*********************************************************************** |
| * File: isp_az.c * |
| * * |
| * Description:Compute the LPC coefficients from isp (order=M) * |
| * * |
| ************************************************************************/ |
| |
| #include "typedef.h" |
| #include "basic_op.h" |
| #include "oper_32b.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 */ |
| ) |
| { |
| Word32 i, j; |
| Word16 hi, lo; |
| Word32 f1[NC16k + 1], f2[NC16k]; |
| Word16 nc; |
| Word32 t0; |
| Word16 q, q_sug; |
| Word32 tmax; |
| |
| nc = (m >> 1); |
| if(nc > 8) |
| { |
| Get_isp_pol_16kHz(&isp[0], f1, nc); |
| for (i = 0; i <= nc; i++) |
| { |
| f1[i] = f1[i] << 2; |
| } |
| } else |
| Get_isp_pol(&isp[0], f1, nc); |
| |
| if (nc > 8) |
| { |
| Get_isp_pol_16kHz(&isp[1], f2, (nc - 1)); |
| for (i = 0; i <= nc - 1; i++) |
| { |
| f2[i] = f2[i] << 2; |
| } |
| } else |
| Get_isp_pol(&isp[1], f2, (nc - 1)); |
| |
| /*-----------------------------------------------------* |
| * Multiply F2(z) by (1 - z^-2) * |
| *-----------------------------------------------------*/ |
| |
| for (i = (nc - 1); i > 1; i--) |
| { |
| f2[i] = vo_L_sub(f2[i], f2[i - 2]); /* 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]); */ |
| |
| hi = f1[i] >> 16; |
| lo = (f1[i] & 0xffff)>>1; |
| |
| t0 = Mpy_32_16(hi, lo, isp[m - 1]); |
| f1[i] = vo_L_add(f1[i], t0); |
| |
| /* f2[i] *= (1.0 - isp[M-1]); */ |
| |
| hi = f2[i] >> 16; |
| lo = (f2[i] & 0xffff)>>1; |
| t0 = Mpy_32_16(hi, lo, isp[m - 1]); |
| f2[i] = vo_L_sub(f2[i], t0); |
| } |
| |
| /*-----------------------------------------------------* |
| * A(z) = (F1(z)+F2(z))/2 * |
| * F1(z) is symmetric and F2(z) is antisymmetric * |
| *-----------------------------------------------------*/ |
| |
| /* a[0] = 1.0; */ |
| a[0] = 4096; |
| tmax = 1; |
| for (i = 1, j = m - 1; i < nc; i++, j--) |
| { |
| /* a[i] = 0.5*(f1[i] + f2[i]); */ |
| |
| t0 = vo_L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ |
| tmax |= L_abs(t0); |
| a[i] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */ |
| |
| /* a[j] = 0.5*(f1[i] - f2[i]); */ |
| |
| t0 = vo_L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ |
| tmax |= L_abs(t0); |
| a[j] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */ |
| } |
| |
| /* rescale data if overflow has occured and reprocess the loop */ |
| if(adaptive_scaling == 1) |
| q = 4 - norm_l(tmax); /* adaptive scaling enabled */ |
| else |
| q = 0; /* adaptive scaling disabled */ |
| |
| if (q > 0) |
| { |
| q_sug = (12 + q); |
| for (i = 1, j = m - 1; i < nc; i++, j--) |
| { |
| /* a[i] = 0.5*(f1[i] + f2[i]); */ |
| t0 = vo_L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ |
| a[i] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ |
| |
| /* a[j] = 0.5*(f1[i] - f2[i]); */ |
| t0 = vo_L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ |
| a[j] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ |
| } |
| a[0] = shr(a[0], q); |
| } |
| else |
| { |
| q_sug = 12; |
| q = 0; |
| } |
| /* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */ |
| hi = f1[nc] >> 16; |
| lo = (f1[nc] & 0xffff)>>1; |
| t0 = Mpy_32_16(hi, lo, isp[m - 1]); |
| t0 = vo_L_add(f1[nc], t0); |
| a[nc] = (Word16)(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ |
| /* a[m] = isp[m-1]; */ |
| |
| a[m] = vo_shr_r(isp[m - 1], (3 + q)); /* from Q15 to Q12 */ |
| 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 hi, lo; |
| Word32 i, j, t0; |
| /* All computation in Q23 */ |
| |
| f[0] = vo_L_mult(4096, 1024); /* f[0] = 1.0; in Q23 */ |
| f[1] = vo_L_mult(isp[0], -256); /* f[1] = -2.0*isp[0] in Q23 */ |
| |
| f += 2; /* Advance f pointer */ |
| isp += 2; /* Advance isp pointer */ |
| for (i = 2; i <= n; i++) |
| { |
| *f = f[-2]; |
| for (j = 1; j < i; j++, f--) |
| { |
| hi = f[-1]>>16; |
| lo = (f[-1] & 0xffff)>>1; |
| |
| t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */ |
| t0 = t0 << 1; |
| *f = vo_L_sub(*f, t0); /* *f -= t0 */ |
| *f = vo_L_add(*f, f[-2]); /* *f += f[-2] */ |
| } |
| *f -= (*isp << 9); /* *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 hi, lo; |
| Word32 i, j, t0; |
| |
| /* All computation in Q23 */ |
| f[0] = L_mult(4096, 256); /* f[0] = 1.0; in Q23 */ |
| f[1] = L_mult(isp[0], -64); /* f[1] = -2.0*isp[0] in Q23 */ |
| |
| f += 2; /* Advance f pointer */ |
| isp += 2; /* Advance isp pointer */ |
| |
| for (i = 2; i <= n; i++) |
| { |
| *f = f[-2]; |
| for (j = 1; j < i; j++, f--) |
| { |
| VO_L_Extract(f[-1], &hi, &lo); |
| t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */ |
| t0 = L_shl2(t0, 1); |
| *f = L_sub(*f, t0); /* *f -= t0 */ |
| *f = L_add(*f, f[-2]); /* *f += f[-2] */ |
| } |
| *f = L_msu(*f, *isp, 64); /* *f -= isp<<8 */ |
| f += i; /* Advance f pointer */ |
| isp += 2; /* Advance isp pointer */ |
| } |
| return; |
| } |
| |
| |