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: az_isp.c
19*
20*  Description:
21*-----------------------------------------------------------------------*
22* Compute the ISPs from  the LPC coefficients  (order=M)                *
23*-----------------------------------------------------------------------*
24*                                                                       *
25* The ISPs are the roots of the two polynomials F1(z) and F2(z)         *
26* defined as                                                            *
27*               F1(z) = A(z) + z^-m A(z^-1)                             *
28*  and          F2(z) = A(z) - z^-m A(z^-1)                             *
29*                                                                       *
30* For a even order m=2n, F1(z) has M/2 conjugate roots on the unit      *
31* circle and F2(z) has M/2-1 conjugate roots on the unit circle in      *
32* addition to two roots at 0 and pi.                                    *
33*                                                                       *
34* For a 16th order LP analysis, F1(z) and F2(z) can be written as       *
35*                                                                       *
36*   F1(z) = (1 + a[M])   PRODUCT  (1 - 2 cos(w_i) z^-1 + z^-2 )         *
37*                        i=0,2,4,6,8,10,12,14                           *
38*                                                                       *
39*   F2(z) = (1 - a[M]) (1 - z^-2) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) *
40*                                 i=1,3,5,7,9,11,13                     *
41*                                                                       *
42* The ISPs are the M-1 frequencies w_i, i=0...M-2 plus the last         *
43* predictor coefficient a[M].                                           *
44*-----------------------------------------------------------------------*
45
46************************************************************************/
47
48#include "typedef.h"
49#include "basic_op.h"
50#include "oper_32b.h"
51#include "stdio.h"
52#include "grid100.tab"
53
54#define M   16
55#define NC  (M/2)
56
57/* local function */
58static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n);
59
60void Az_isp(
61		Word16 a[],                           /* (i) Q12 : predictor coefficients                 */
62		Word16 isp[],                         /* (o) Q15 : Immittance spectral pairs              */
63		Word16 old_isp[]                      /* (i)     : old isp[] (in case not found M roots)  */
64	   )
65{
66	Word32 i, j, nf, ip, order;
67	Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
68	Word16 x, y, sign, exp;
69	Word16 *coef;
70	Word16 f1[NC + 1], f2[NC];
71	Word32 t0;
72	/*-------------------------------------------------------------*
73	 * find the sum and diff polynomials F1(z) and F2(z)           *
74	 *      F1(z) = [A(z) + z^M A(z^-1)]                           *
75	 *      F2(z) = [A(z) - z^M A(z^-1)]/(1-z^-2)                  *
76	 *                                                             *
77	 * for (i=0; i<NC; i++)                                        *
78	 * {                                                           *
79	 *   f1[i] = a[i] + a[M-i];                                    *
80	 *   f2[i] = a[i] - a[M-i];                                    *
81	 * }                                                           *
82	 * f1[NC] = 2.0*a[NC];                                         *
83	 *                                                             *
84	 * for (i=2; i<NC; i++)            Divide by (1-z^-2)          *
85	 *   f2[i] += f2[i-2];                                         *
86	 *-------------------------------------------------------------*/
87	for (i = 0; i < NC; i++)
88	{
89		t0 = a[i] << 15;
90		f1[i] = vo_round(t0 + (a[M - i] << 15));        /* =(a[i]+a[M-i])/2 */
91		f2[i] = vo_round(t0 - (a[M - i] << 15));        /* =(a[i]-a[M-i])/2 */
92	}
93	f1[NC] = a[NC];
94	for (i = 2; i < NC; i++)               /* Divide by (1-z^-2) */
95		f2[i] = add1(f2[i], f2[i - 2]);
96
97	/*---------------------------------------------------------------------*
98	 * Find the ISPs (roots of F1(z) and F2(z) ) using the                 *
99	 * Chebyshev polynomial evaluation.                                    *
100	 * The roots of F1(z) and F2(z) are alternatively searched.            *
101	 * We start by finding the first root of F1(z) then we switch          *
102	 * to F2(z) then back to F1(z) and so on until all roots are found.    *
103	 *                                                                     *
104	 *  - Evaluate Chebyshev pol. at grid points and check for sign change.*
105	 *  - If sign change track the root by subdividing the interval        *
106	 *    2 times and ckecking sign change.                                *
107	 *---------------------------------------------------------------------*/
108	nf = 0;                                  /* number of found frequencies */
109	ip = 0;                                  /* indicator for f1 or f2      */
110	coef = f1;
111	order = NC;
112	xlow = vogrid[0];
113	ylow = Chebps2(xlow, coef, order);
114	j = 0;
115	while ((nf < M - 1) && (j < GRID_POINTS))
116	{
117		j ++;
118		xhigh = xlow;
119		yhigh = ylow;
120		xlow = vogrid[j];
121		ylow = Chebps2(xlow, coef, order);
122		if ((ylow * yhigh) <= (Word32) 0)
123		{
124			/* divide 2 times the interval */
125			for (i = 0; i < 2; i++)
126			{
127				xmid = (xlow >> 1) + (xhigh >> 1);        /* xmid = (xlow + xhigh)/2 */
128				ymid = Chebps2(xmid, coef, order);
129				if ((ylow * ymid) <= (Word32) 0)
130				{
131					yhigh = ymid;
132					xhigh = xmid;
133				} else
134				{
135					ylow = ymid;
136					xlow = xmid;
137				}
138			}
139			/*-------------------------------------------------------------*
140			 * Linear interpolation                                        *
141			 *    xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow);            *
142			 *-------------------------------------------------------------*/
143			x = xhigh - xlow;
144			y = yhigh - ylow;
145			if (y == 0)
146			{
147				xint = xlow;
148			} else
149			{
150				sign = y;
151				y = abs_s(y);
152				exp = norm_s(y);
153				y = y << exp;
154				y = div_s((Word16) 16383, y);
155				t0 = x * y;
156				t0 = (t0 >> (19 - exp));
157				y = vo_extract_l(t0);         /* y= (xhigh-xlow)/(yhigh-ylow) in Q11 */
158				if (sign < 0)
159					y = -y;
160				t0 = ylow * y;      /* result in Q26 */
161				t0 = (t0 >> 10);        /* result in Q15 */
162				xint = vo_sub(xlow, vo_extract_l(t0));        /* xint = xlow - ylow*y */
163			}
164			isp[nf] = xint;
165			xlow = xint;
166			nf++;
167			if (ip == 0)
168			{
169				ip = 1;
170				coef = f2;
171				order = NC - 1;
172			} else
173			{
174				ip = 0;
175				coef = f1;
176				order = NC;
177			}
178			ylow = Chebps2(xlow, coef, order);
179		}
180	}
181	/* Check if M-1 roots found */
182	if(nf < M - 1)
183	{
184		for (i = 0; i < M; i++)
185		{
186			isp[i] = old_isp[i];
187		}
188	} else
189	{
190		isp[M - 1] = a[M] << 3;                      /* From Q12 to Q15 with saturation */
191	}
192	return;
193}
194
195/*--------------------------------------------------------------*
196* function  Chebps2:                                           *
197*           ~~~~~~~                                            *
198*    Evaluates the Chebishev polynomial series                 *
199*--------------------------------------------------------------*
200*                                                              *
201*  The polynomial order is                                     *
202*     n = M/2   (M is the prediction order)                    *
203*  The polynomial is given by                                  *
204*    C(x) = f(0)T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2 *
205* Arguments:                                                   *
206*  x:     input value of evaluation; x = cos(frequency) in Q15 *
207*  f[]:   coefficients of the pol.                      in Q11 *
208*  n:     order of the pol.                                    *
209*                                                              *
210* The value of C(x) is returned. (Satured to +-1.99 in Q14)    *
211*                                                              *
212*--------------------------------------------------------------*/
213
214static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n)
215{
216	Word32 i, cheb;
217	Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l;
218	Word32 t0;
219
220	/* Note: All computation are done in Q24. */
221
222	t0 = f[0] << 13;
223	b2_h = t0 >> 16;
224	b2_l = (t0 & 0xffff)>>1;
225
226	t0 = ((b2_h * x)<<1) + (((b2_l * x)>>15)<<1);
227	t0 <<= 1;
228	t0 += (f[1] << 13);						/* + f[1] in Q24        */
229
230	b1_h = t0 >> 16;
231	b1_l = (t0 & 0xffff) >> 1;
232
233	for (i = 2; i < n; i++)
234	{
235		t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1);
236
237		t0 += (b2_h * (-16384))<<1;
238		t0 += (f[i] << 12);
239		t0 <<= 1;
240		t0 -= (b2_l << 1);					/* t0 = 2.0*x*b1 - b2 + f[i]; */
241
242		b0_h = t0 >> 16;
243		b0_l = (t0 & 0xffff) >> 1;
244
245		b2_l = b1_l;                         /* b2 = b1; */
246		b2_h = b1_h;
247		b1_l = b0_l;                         /* b1 = b0; */
248		b1_h = b0_h;
249	}
250
251	t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1);
252	t0 += (b2_h * (-32768))<<1;				/* t0 = x*b1 - b2          */
253	t0 -= (b2_l << 1);
254	t0 += (f[n] << 12);						/* t0 = x*b1 - b2 + f[i]/2 */
255
256	t0 = L_shl2(t0, 6);                     /* Q24 to Q30 with saturation */
257
258	cheb = extract_h(t0);                  /* Result in Q14              */
259
260	if (cheb == -32768)
261	{
262		cheb = -32767;                     /* to avoid saturation in Az_isp */
263	}
264	return (cheb);
265}
266
267
268
269