1/* 2 ** Copyright 2003-2010, VisualOn, Inc. 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17/*********************************************************************** 18* File: isp_az.c * 19* * 20* Description:Compute the LPC coefficients from isp (order=M) * 21* * 22************************************************************************/ 23 24#include "typedef.h" 25#include "basic_op.h" 26#include "oper_32b.h" 27#include "cnst.h" 28 29#define NC (M/2) 30#define NC16k (M16k/2) 31 32/* local function */ 33 34static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n); 35static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n); 36 37void Isp_Az( 38 Word16 isp[], /* (i) Q15 : Immittance spectral pairs */ 39 Word16 a[], /* (o) Q12 : predictor coefficients (order = M) */ 40 Word16 m, 41 Word16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */ 42 /* 1 : adaptive scaling enabled */ 43 ) 44{ 45 Word32 i, j; 46 Word16 hi, lo; 47 Word32 f1[NC16k + 1], f2[NC16k]; 48 Word16 nc; 49 Word32 t0; 50 Word16 q, q_sug; 51 Word32 tmax; 52 53 nc = (m >> 1); 54 if(nc > 8) 55 { 56 Get_isp_pol_16kHz(&isp[0], f1, nc); 57 for (i = 0; i <= nc; i++) 58 { 59 f1[i] = f1[i] << 2; 60 } 61 } else 62 Get_isp_pol(&isp[0], f1, nc); 63 64 if (nc > 8) 65 { 66 Get_isp_pol_16kHz(&isp[1], f2, (nc - 1)); 67 for (i = 0; i <= nc - 1; i++) 68 { 69 f2[i] = f2[i] << 2; 70 } 71 } else 72 Get_isp_pol(&isp[1], f2, (nc - 1)); 73 74 /*-----------------------------------------------------* 75 * Multiply F2(z) by (1 - z^-2) * 76 *-----------------------------------------------------*/ 77 78 for (i = (nc - 1); i > 1; i--) 79 { 80 f2[i] = vo_L_sub(f2[i], f2[i - 2]); /* f2[i] -= f2[i-2]; */ 81 } 82 83 /*----------------------------------------------------------* 84 * Scale F1(z) by (1+isp[m-1]) and F2(z) by (1-isp[m-1]) * 85 *----------------------------------------------------------*/ 86 87 for (i = 0; i < nc; i++) 88 { 89 /* f1[i] *= (1.0 + isp[M-1]); */ 90 91 hi = f1[i] >> 16; 92 lo = (f1[i] & 0xffff)>>1; 93 94 t0 = Mpy_32_16(hi, lo, isp[m - 1]); 95 f1[i] = vo_L_add(f1[i], t0); 96 97 /* f2[i] *= (1.0 - isp[M-1]); */ 98 99 hi = f2[i] >> 16; 100 lo = (f2[i] & 0xffff)>>1; 101 t0 = Mpy_32_16(hi, lo, isp[m - 1]); 102 f2[i] = vo_L_sub(f2[i], t0); 103 } 104 105 /*-----------------------------------------------------* 106 * A(z) = (F1(z)+F2(z))/2 * 107 * F1(z) is symmetric and F2(z) is antisymmetric * 108 *-----------------------------------------------------*/ 109 110 /* a[0] = 1.0; */ 111 a[0] = 4096; 112 tmax = 1; 113 for (i = 1, j = m - 1; i < nc; i++, j--) 114 { 115 /* a[i] = 0.5*(f1[i] + f2[i]); */ 116 117 t0 = vo_L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ 118 tmax |= L_abs(t0); 119 a[i] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */ 120 121 /* a[j] = 0.5*(f1[i] - f2[i]); */ 122 123 t0 = vo_L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ 124 tmax |= L_abs(t0); 125 a[j] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */ 126 } 127 128 /* rescale data if overflow has occured and reprocess the loop */ 129 if(adaptive_scaling == 1) 130 q = 4 - norm_l(tmax); /* adaptive scaling enabled */ 131 else 132 q = 0; /* adaptive scaling disabled */ 133 134 if (q > 0) 135 { 136 q_sug = (12 + q); 137 for (i = 1, j = m - 1; i < nc; i++, j--) 138 { 139 /* a[i] = 0.5*(f1[i] + f2[i]); */ 140 t0 = vo_L_add(f1[i], f2[i]); /* f1[i] + f2[i] */ 141 a[i] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ 142 143 /* a[j] = 0.5*(f1[i] - f2[i]); */ 144 t0 = vo_L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */ 145 a[j] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ 146 } 147 a[0] = shr(a[0], q); 148 } 149 else 150 { 151 q_sug = 12; 152 q = 0; 153 } 154 /* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */ 155 hi = f1[nc] >> 16; 156 lo = (f1[nc] & 0xffff)>>1; 157 t0 = Mpy_32_16(hi, lo, isp[m - 1]); 158 t0 = vo_L_add(f1[nc], t0); 159 a[nc] = (Word16)(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */ 160 /* a[m] = isp[m-1]; */ 161 162 a[m] = vo_shr_r(isp[m - 1], (3 + q)); /* from Q15 to Q12 */ 163 return; 164} 165 166/*-----------------------------------------------------------* 167* procedure Get_isp_pol: * 168* ~~~~~~~~~~~ * 169* Find the polynomial F1(z) or F2(z) from the ISPs. * 170* This is performed by expanding the product polynomials: * 171* * 172* F1(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) * 173* i=0,2,4,6,8 * 174* F2(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) * 175* i=1,3,5,7 * 176* * 177* where isp_i are the ISPs in the cosine domain. * 178*-----------------------------------------------------------* 179* * 180* Parameters: * 181* isp[] : isp vector (cosine domaine) in Q15 * 182* f[] : the coefficients of F1 or F2 in Q23 * 183* n : == NC for F1(z); == NC-1 for F2(z) * 184*-----------------------------------------------------------*/ 185 186static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n) 187{ 188 Word16 hi, lo; 189 Word32 i, j, t0; 190 /* All computation in Q23 */ 191 192 f[0] = vo_L_mult(4096, 1024); /* f[0] = 1.0; in Q23 */ 193 f[1] = vo_L_mult(isp[0], -256); /* f[1] = -2.0*isp[0] in Q23 */ 194 195 f += 2; /* Advance f pointer */ 196 isp += 2; /* Advance isp pointer */ 197 for (i = 2; i <= n; i++) 198 { 199 *f = f[-2]; 200 for (j = 1; j < i; j++, f--) 201 { 202 hi = f[-1]>>16; 203 lo = (f[-1] & 0xffff)>>1; 204 205 t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */ 206 t0 = t0 << 1; 207 *f = vo_L_sub(*f, t0); /* *f -= t0 */ 208 *f = vo_L_add(*f, f[-2]); /* *f += f[-2] */ 209 } 210 *f -= (*isp << 9); /* *f -= isp<<8 */ 211 f += i; /* Advance f pointer */ 212 isp += 2; /* Advance isp pointer */ 213 } 214 return; 215} 216 217static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n) 218{ 219 Word16 hi, lo; 220 Word32 i, j, t0; 221 222 /* All computation in Q23 */ 223 f[0] = L_mult(4096, 256); /* f[0] = 1.0; in Q23 */ 224 f[1] = L_mult(isp[0], -64); /* f[1] = -2.0*isp[0] in Q23 */ 225 226 f += 2; /* Advance f pointer */ 227 isp += 2; /* Advance isp pointer */ 228 229 for (i = 2; i <= n; i++) 230 { 231 *f = f[-2]; 232 for (j = 1; j < i; j++, f--) 233 { 234 VO_L_Extract(f[-1], &hi, &lo); 235 t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */ 236 t0 = L_shl2(t0, 1); 237 *f = L_sub(*f, t0); /* *f -= t0 */ 238 *f = L_add(*f, f[-2]); /* *f += f[-2] */ 239 } 240 *f = L_msu(*f, *isp, 64); /* *f -= isp<<8 */ 241 f += i; /* Advance f pointer */ 242 isp += 2; /* Advance isp pointer */ 243 } 244 return; 245} 246 247 248