www.pudn.com > CryptoPhone-src-031122.zip > pctolsf.c
/* Copyright 2001,2002,2003 NAH6 * All Rights Reserved * * Parts Copyright DoD, Parts Copyright Starium * */ /************************************************************************** * * NAME * PCtoLSF (formerly pctolsp2) * * FUNCTION * * Compute LSF from predictor polynomial. * * NOTE: Much faster conversion can be performed * if the LSP quantization is incorporated. * * SYNOPSIS * * PCtoLSF(a,freq) * * formal * data I/O * name type type function * ------------------------------------------------------------------- * a float i a-polynomial a(0)=1 * freq float o lsp frequencies * *************************************************************************** * * DESCRIPTION * * Compute line spectrum frequencies by disection method as described in: * * Line Spectrum Pair (LSP) and Speech Data Compression, * F.K. Soong and B-H Juang, * Proc. ICASSP 84, pp. 1.10.1-1.10.4 * * CELP's LPC predictor coefficient convention is: * p+1 -(i-1) * A(z) = SUM a z where a = +1.0 * i=1 i 1 * * Peter uses n=128, eps=1.e-06, nb=15 (this appears to be overkill!) * *************************************************************************** * * CALLED BY * * LPC_Analysis * **************************************************************************/ #define N 128 #define NB 15 #define EPS 1.e-6 #define FALSE 0 #define TRUE 1 #include#include #include "main.h" #include "pctolsf.h" void PCtoLSF( float a[ORDER+1], float freq[ORDER+1]) { static float lastfreq[ORDER]; float p[ORDER], q[ORDER], pi, ang, fm, tempfreq; float fr, pxr, tpxr, tfr, pxm, pxl, fl, qxl, tqxr; float qxm, qxr, tqxl; int mp, mh, nf, mb, jc, i, j, lspflag; pi = atan(1.) * 4.0; mp = ORDER + 1; mh = ORDER / 2; /* *generate p and q polynomials */ for (i = 0; i < mh; i++) { p[i] = a[i+1] + a[ORDER-i]; q[i] = a[i+1] - a[ORDER-i]; } /* *compute p at f=0. */ fl = 0.; for (pxl = 1.0, j = 0; j < mh; j++) pxl += p[j]; /* *search for zeros of p */ nf = 0; for (i = 1; i <= N; pxl = tpxr, fl = tfr, i++) { mb = 0; fr = i * (0.5 / N); pxr = cos(mp * pi * fr); for (j = 0; j < mh; j++) { jc = mp - (j+1)*2; ang = jc * pi * fr; pxr += cos(ang) * p[j]; } tpxr = pxr; tfr = fr; if (pxl * pxr > 0.0) continue; do { mb++; fm = fl + (fr-fl) / (pxl-pxr) * pxl; pxm = cos(mp * pi * fm); for (j = 0; j < mh; j++) { jc = mp - (j+1) * 2; ang = jc * pi * fm; pxm += cos(ang) * p[j]; } (pxm*pxl > 0.0) ? (pxl = pxm, fl = fm) : (pxr = pxm, fr = fm); } while ((fabs(pxm) > EPS) && (mb < 4)); if ((pxl-pxr) * pxl == 0) { for (j = 0; j < ORDER; j++) freq[j] = (j+1) * 0.04545; printf("pctolsf: default lsps used, avoiding /0\n"); return; } freq[nf] = fl + (fr-fl) / (pxl-pxr) * pxl; nf += 2; if (nf > ORDER-2) break; } /* *search for the zeros of q(z) */ freq[ORDER] = 0.5; fl = freq[0]; qxl = sin(mp * pi * fl); for (j = 0; j < mh; j++) { jc = mp - (j+1) * 2; ang = jc * pi * fl; qxl += sin(ang) * q[j]; } for (i = 2; i < mp; qxl = tqxr, fl = tfr, i += 2) { mb = 0; fr = freq[i]; qxr = sin(mp * pi * fr); for (j = 0; j < mh; j++) { jc = mp - (j+1) * 2; ang = jc * pi * fr; qxr += sin(ang) * q[j]; } tqxl = qxl; tfr = fr; tqxr = qxr; do { mb++; fm = (fl+fr) * 0.5; qxm = sin(mp * pi * fm); for (j = 0; j < mh; j++) { jc = mp - (j+1) * 2; ang = jc * pi * fm; qxm += sin(ang) * q[j]; } (qxm*qxl > 0.0) ? (qxl = qxm, fl = fm) : (qxr = qxm, fr = fm); } while ((fabs(qxm) > EPS*tqxl) && (mb < NB)); if ((qxl-qxr) * qxl == 0) { for (j = 0; j < ORDER; j++) freq[j] = lastfreq[j]; printf("pctolsf: last lsps used, avoiding /0\n"); return; } freq[i-1] = fl + (fr-fl) / (qxl-qxr) * qxl; } /* *** ill-conditioned cases */ lspflag = FALSE; if (freq[0] == 0.0 || freq[0] == 0.5) lspflag = TRUE; for (i = 1; i < ORDER; i++) { if (freq[i] == 0.0 || freq[i] == 0.5) lspflag = TRUE; /* *reorder lsps if non-monotonic */ if (freq[i] < freq[i-1]) { lspflag = TRUE; printf("pctolsf: non-monotonic lsps\n"); tempfreq = freq[i]; freq[i] = freq[i-1]; freq[i-1] = tempfreq; } } /* *if non-monotonic after 1st pass, reset to last values */ for (i = 1; i < ORDER; i++) { if (freq[i] < freq[i-1]) { printf("pctolsf: Reset to previous lsp values\n"); for (j = 0; j < ORDER; j++) freq[j] = lastfreq[j]; break; } } for (i = 0; i < ORDER; i++) lastfreq[i] = freq[i]; }