blob: d7074f07e7a825f59af031b8f446eb430a9d333f [file] [log] [blame]
/*
** 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: az_isp.c
*
* Description:
*-----------------------------------------------------------------------*
* Compute the ISPs from the LPC coefficients (order=M) *
*-----------------------------------------------------------------------*
* *
* The ISPs are the roots of the two polynomials F1(z) and F2(z) *
* defined as *
* F1(z) = A(z) + z^-m A(z^-1) *
* and F2(z) = A(z) - z^-m A(z^-1) *
* *
* For a even order m=2n, F1(z) has M/2 conjugate roots on the unit *
* circle and F2(z) has M/2-1 conjugate roots on the unit circle in *
* addition to two roots at 0 and pi. *
* *
* For a 16th order LP analysis, F1(z) and F2(z) can be written as *
* *
* F1(z) = (1 + a[M]) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) *
* i=0,2,4,6,8,10,12,14 *
* *
* F2(z) = (1 - a[M]) (1 - z^-2) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) *
* i=1,3,5,7,9,11,13 *
* *
* The ISPs are the M-1 frequencies w_i, i=0...M-2 plus the last *
* predictor coefficient a[M]. *
*-----------------------------------------------------------------------*
************************************************************************/
#include "typedef.h"
#include "basic_op.h"
#include "oper_32b.h"
#include "stdio.h"
#include "grid100.tab"
#define M 16
#define NC (M/2)
/* local function */
static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n);
void Az_isp(
Word16 a[], /* (i) Q12 : predictor coefficients */
Word16 isp[], /* (o) Q15 : Immittance spectral pairs */
Word16 old_isp[] /* (i) : old isp[] (in case not found M roots) */
)
{
Word32 i, j, nf, ip, order;
Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
Word16 x, y, sign, exp;
Word16 *coef;
Word16 f1[NC + 1], f2[NC];
Word32 t0;
/*-------------------------------------------------------------*
* find the sum and diff polynomials F1(z) and F2(z) *
* F1(z) = [A(z) + z^M A(z^-1)] *
* F2(z) = [A(z) - z^M A(z^-1)]/(1-z^-2) *
* *
* for (i=0; i<NC; i++) *
* { *
* f1[i] = a[i] + a[M-i]; *
* f2[i] = a[i] - a[M-i]; *
* } *
* f1[NC] = 2.0*a[NC]; *
* *
* for (i=2; i<NC; i++) Divide by (1-z^-2) *
* f2[i] += f2[i-2]; *
*-------------------------------------------------------------*/
for (i = 0; i < NC; i++)
{
t0 = a[i] << 15;
f1[i] = vo_round(t0 + (a[M - i] << 15)); /* =(a[i]+a[M-i])/2 */
f2[i] = vo_round(t0 - (a[M - i] << 15)); /* =(a[i]-a[M-i])/2 */
}
f1[NC] = a[NC];
for (i = 2; i < NC; i++) /* Divide by (1-z^-2) */
f2[i] = add1(f2[i], f2[i - 2]);
/*---------------------------------------------------------------------*
* Find the ISPs (roots of F1(z) and F2(z) ) using the *
* Chebyshev polynomial evaluation. *
* The roots of F1(z) and F2(z) are alternatively searched. *
* We start by finding the first root of F1(z) then we switch *
* to F2(z) then back to F1(z) and so on until all roots are found. *
* *
* - Evaluate Chebyshev pol. at grid points and check for sign change.*
* - If sign change track the root by subdividing the interval *
* 2 times and ckecking sign change. *
*---------------------------------------------------------------------*/
nf = 0; /* number of found frequencies */
ip = 0; /* indicator for f1 or f2 */
coef = f1;
order = NC;
xlow = vogrid[0];
ylow = Chebps2(xlow, coef, order);
j = 0;
while ((nf < M - 1) && (j < GRID_POINTS))
{
j ++;
xhigh = xlow;
yhigh = ylow;
xlow = vogrid[j];
ylow = Chebps2(xlow, coef, order);
if ((ylow * yhigh) <= (Word32) 0)
{
/* divide 2 times the interval */
for (i = 0; i < 2; i++)
{
xmid = (xlow >> 1) + (xhigh >> 1); /* xmid = (xlow + xhigh)/2 */
ymid = Chebps2(xmid, coef, order);
if ((ylow * ymid) <= (Word32) 0)
{
yhigh = ymid;
xhigh = xmid;
} else
{
ylow = ymid;
xlow = xmid;
}
}
/*-------------------------------------------------------------*
* Linear interpolation *
* xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow); *
*-------------------------------------------------------------*/
x = xhigh - xlow;
y = yhigh - ylow;
if (y == 0)
{
xint = xlow;
} else
{
sign = y;
y = abs_s(y);
exp = norm_s(y);
y = y << exp;
y = div_s((Word16) 16383, y);
t0 = x * y;
t0 = (t0 >> (19 - exp));
y = vo_extract_l(t0); /* y= (xhigh-xlow)/(yhigh-ylow) in Q11 */
if (sign < 0)
y = -y;
t0 = ylow * y; /* result in Q26 */
t0 = (t0 >> 10); /* result in Q15 */
xint = vo_sub(xlow, vo_extract_l(t0)); /* xint = xlow - ylow*y */
}
isp[nf] = xint;
xlow = xint;
nf++;
if (ip == 0)
{
ip = 1;
coef = f2;
order = NC - 1;
} else
{
ip = 0;
coef = f1;
order = NC;
}
ylow = Chebps2(xlow, coef, order);
}
}
/* Check if M-1 roots found */
if(nf < M - 1)
{
for (i = 0; i < M; i++)
{
isp[i] = old_isp[i];
}
} else
{
isp[M - 1] = a[M] << 3; /* From Q12 to Q15 with saturation */
}
return;
}
/*--------------------------------------------------------------*
* function Chebps2: *
* ~~~~~~~ *
* Evaluates the Chebishev polynomial series *
*--------------------------------------------------------------*
* *
* The polynomial order is *
* n = M/2 (M is the prediction order) *
* The polynomial is given by *
* C(x) = f(0)T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2 *
* Arguments: *
* x: input value of evaluation; x = cos(frequency) in Q15 *
* f[]: coefficients of the pol. in Q11 *
* n: order of the pol. *
* *
* The value of C(x) is returned. (Satured to +-1.99 in Q14) *
* *
*--------------------------------------------------------------*/
static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n)
{
Word32 i, cheb;
Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l;
Word32 t0;
/* Note: All computation are done in Q24. */
t0 = f[0] << 13;
b2_h = t0 >> 16;
b2_l = (t0 & 0xffff)>>1;
t0 = ((b2_h * x)<<1) + (((b2_l * x)>>15)<<1);
t0 <<= 1;
t0 += (f[1] << 13); /* + f[1] in Q24 */
b1_h = t0 >> 16;
b1_l = (t0 & 0xffff) >> 1;
for (i = 2; i < n; i++)
{
t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1);
t0 += (b2_h * (-16384))<<1;
t0 += (f[i] << 12);
t0 <<= 1;
t0 -= (b2_l << 1); /* t0 = 2.0*x*b1 - b2 + f[i]; */
b0_h = t0 >> 16;
b0_l = (t0 & 0xffff) >> 1;
b2_l = b1_l; /* b2 = b1; */
b2_h = b1_h;
b1_l = b0_l; /* b1 = b0; */
b1_h = b0_h;
}
t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1);
t0 += (b2_h * (-32768))<<1; /* t0 = x*b1 - b2 */
t0 -= (b2_l << 1);
t0 += (f[n] << 12); /* t0 = x*b1 - b2 + f[i]/2 */
t0 = L_shl2(t0, 6); /* Q24 to Q30 with saturation */
cheb = extract_h(t0); /* Result in Q14 */
if (cheb == -32768)
{
cheb = -32767; /* to avoid saturation in Az_isp */
}
return (cheb);
}