/*---------------------------------------------------------------------------* * IT++ * *---------------------------------------------------------------------------* * Copyright (c) 1995-2004 by Tony Ottosson, Thomas Eriksson, Pål Frenger, * * Tobias Ringström, and Jonas Samuelsson. * * * * Permission to use, copy, modify, and distribute this software and its * * documentation under the terms of the GNU General Public License is hereby * * granted. No representations are made about the suitability of this * * software for any purpose. It is provided "as is" without expressed or * * implied warranty. See the GNU General Public License for more details. * *---------------------------------------------------------------------------*/ /*! \file \brief Linear prediction functions, and conversion between common representations of linear predictive parameters. \author Thomas Eriksson 1.8 2004/11/01 09:43:52 */ #include "srccode/lpcfunc.h" #include "base/scalfunc.h" #include "base/stat.h" #include "base/matfunc.h" using std::cout; using std::endl; namespace itpp { // Autocorrelation sequence to reflection coefficients conversion. vec ac2rc(const vec &ac); // Autocorrelation sequence to prediction polynomial conversion. vec ac2poly(const vec &ac); // Inverse sine parameters to reflection coefficients conversion. vec is2rc(const vec &is); // Reflection coefficients to autocorrelation sequence conversion. vec rc2ac(const vec &rc); // Reflection coefficients to inverse sine parameters conversion. vec rc2is(const vec &rc); vec autocorr(const vec &x, int order) { if (order<0) order=x.size(); vec R(order+1); double sum; int i,j; for (i=0;i=1.0) { cout << "levinson : panic! abs(k)>=1, order " << m << ". Aborting..." << endl ; for (j=m;j<=order;j++) { a[j]=0; } break; } for (j=1;j0;m--) { k[m]=aold[m+1] ; if (fabs(k[m])>1) k[m]=1.0/k[m]; for (i=0;i1) k[0]=1.0/k[0]; return k; } vec rc2poly(const vec &k) { int m,i; vec a(k.length()+1),any(k.length()+1); a[0]=1;any[0]=1; a[1]=k[0]; for (m=1;m= 0; --i) { b2 = b1; b1 = b0; b0 = 2.0 * x * b1 - b2 + c[i]; } return (0.5 * (b0 - b2 + c[0])); } double FNevChebP(double x,const double c[],int n) { int i; double b0=0.0, b1=0.0, b2=0.0; for (i = n - 1; i >= 0; --i) { b2 = b1; b1 = b0; b0 = 2.0 * x * b1 - b2 + c[i]; } return (0.5 * (b0 - b2 + c[0])); } vec poly2lsf(const vec &pc) { int np=pc.length()-1; vec lsf(np); vec fa((np+1)/2+1), fb((np+1)/2+1); vec ta((np+1)/2+1), tb((np+1)/2+1); double *t; double xlow, xmid, xhigh; double ylow, ymid, yhigh; double xroot; double dx; int i, j, nf; int odd; int na, nb, n; double ss, aa; double DW=(0.02 * pi); int NBIS=4; odd = (np % 2 != 0); if (odd) { nb = (np + 1) / 2; na = nb + 1; } else { nb = np / 2 + 1; na = nb; } fa[0] = 1.0; for (i = 1, j = np; i < na; ++i, --j) fa[i] = pc[i] + pc[j]; fb[0] = 1.0; for (i = 1, j = np; i < nb; ++i, --j) fb[i] = pc[i] - pc[j]; if (odd) { for (i = 2; i < nb; ++i) fb[i] = fb[i] + fb[i-2]; } else { for (i = 1; i < na; ++i) { fa[i] = fa[i] - fa[i-1]; fb[i] = fb[i] + fb[i-1]; } } ta[0] = fa[na-1]; for (i = 1, j = na - 2; i < na; ++i, --j) ta[i] = 2.0 * fa[j]; tb[0] = fb[nb-1]; for (i = 1, j = nb - 2; i < nb; ++i, --j) tb[i] = 2.0 * fb[j]; nf = 0; t = ta._data(); n = na; xroot = 2.0; xlow = 1.0; ylow = FNevChebP_double(xlow, t, n); ss = sin (DW); aa = 4.0 - 4.0 * cos (DW) - ss; while (xlow > -1.0 && nf < np) { xhigh = xlow; yhigh = ylow; dx = aa * xhigh * xhigh + ss; xlow = xhigh - dx; if (xlow < -1.0) xlow = -1.0; ylow = FNevChebP_double(xlow, t, n); if (ylow * yhigh <= 0.0) { dx = xhigh - xlow; for (i = 1; i <= NBIS; ++i) { dx = 0.5 * dx; xmid = xlow + dx; ymid = FNevChebP_double(xmid, t, n); if (ylow * ymid <= 0.0) { yhigh = ymid; xhigh = xmid; } else { ylow = ymid; xlow = xmid; } } if (yhigh != ylow) xmid = xlow + dx * ylow / (ylow - yhigh); else xmid = xlow + dx; lsf[nf] = acos((double) xmid); ++nf; if (xmid >= xroot) { xmid = xlow - dx; } xroot = xmid; if (t == ta._data()) { t = tb._data(); n = nb; } else { t = ta._data(); n = na; } xlow = xmid; ylow = FNevChebP_double(xlow, t, n); } } if (nf != np) { cout << "poly2lsf: WARNING: failed to find all lsfs" << endl ; } return lsf; } vec lsf2poly(const vec &f) { int m=f.length(); vec pc(m+1); double c1, c2, *a; vec p(m+1), q(m+1); int mq, n, i, nor; it_error_if(m%2!=0,"lsf2poly: THIS ROUTINE WORKS ONLY FOR EVEN m"); pc[0] = 1.0; a = pc._data() + 1; mq=m>>1; for(i=0 ; i <= m ; i++) { q[i]=0.; p[i]=0.; } p[0] = q[0] = 1.; for(n=1; n <= mq; n++) { nor=2*n; c1 = 2*cos(f[nor-1]); c2 = 2*cos(f[nor-2]); for(i=nor; i >= 2; i--) { q[i] += q[i-2] - c1*q[i-1]; p[i] += p[i-2] - c2*p[i-1]; } q[1] -= c1; p[1] -= c2; } a[0] = 0.5 * (p[1] + q[1]); for(i=1, n=2; i < m ; i++, n++) a[i] = 0.5 * (p[i] + p[n] + q[n] - q[i]); return pc; } vec poly2cepstrum(const vec &a) { vec c(a.length()-1); for (int n=1;n<=c.length();n++) { c[n-1]=a[n]; for (int k=1;k