diff options
Diffstat (limited to 'gr-vocoder/lib/codec2/lsp.c')
-rw-r--r-- | gr-vocoder/lib/codec2/lsp.c | 325 |
1 files changed, 0 insertions, 325 deletions
diff --git a/gr-vocoder/lib/codec2/lsp.c b/gr-vocoder/lib/codec2/lsp.c deleted file mode 100644 index b57507bb4..000000000 --- a/gr-vocoder/lib/codec2/lsp.c +++ /dev/null @@ -1,325 +0,0 @@ -/*---------------------------------------------------------------------------*\ - - FILE........: lsp.c - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 - - - This file contains functions for LPC to LSP conversion and LSP to - LPC conversion. Note that the LSP coefficients are not in radians - format but in the x domain of the unit circle. - -\*---------------------------------------------------------------------------*/ - -/* - Copyright (C) 2009 David Rowe - - All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License version 2.1, as - published by the Free Software Foundation. This program is - distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. -*/ - -#include "defines.h" -#include "lsp.h" -#include <math.h> -#include <stdio.h> -#include <stdlib.h> - -/* Only 10 gets used, so far. */ -#define LSP_MAX_ORDER 20 - -/*---------------------------------------------------------------------------*\ - - Introduction to Line Spectrum Pairs (LSPs) - ------------------------------------------ - - LSPs are used to encode the LPC filter coefficients {ak} for - transmission over the channel. LSPs have several properties (like - less sensitivity to quantisation noise) that make them superior to - direct quantisation of {ak}. - - A(z) is a polynomial of order lpcrdr with {ak} as the coefficients. - - A(z) is transformed to P(z) and Q(z) (using a substitution and some - algebra), to obtain something like: - - A(z) = 0.5[P(z)(z+z^-1) + Q(z)(z-z^-1)] (1) - - As you can imagine A(z) has complex zeros all over the z-plane. P(z) - and Q(z) have the very neat property of only having zeros _on_ the - unit circle. So to find them we take a test point z=exp(jw) and - evaluate P (exp(jw)) and Q(exp(jw)) using a grid of points between 0 - and pi. - - The zeros (roots) of P(z) also happen to alternate, which is why we - swap coefficients as we find roots. So the process of finding the - LSP frequencies is basically finding the roots of 5th order - polynomials. - - The root so P(z) and Q(z) occur in symmetrical pairs at +/-w, hence - the name Line Spectrum Pairs (LSPs). - - To convert back to ak we just evaluate (1), "clocking" an impulse - thru it lpcrdr times gives us the impulse response of A(z) which is - {ak}. - -\*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*\ - - FUNCTION....: cheb_poly_eva() - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 - - This function evalutes a series of chebyshev polynomials - - FIXME: performing memory allocation at run time is very inefficient, - replace with stack variables of MAX_P size. - -\*---------------------------------------------------------------------------*/ - - -static float -cheb_poly_eva(float *coef,float x,int m) -/* float coef[] coefficients of the polynomial to be evaluated */ -/* float x the point where polynomial is to be evaluated */ -/* int m order of the polynomial */ -{ - int i; - float *t,*u,*v,sum; - float T[(LSP_MAX_ORDER / 2) + 1]; - - /* Initialise pointers */ - - t = T; /* T[i-2] */ - *t++ = 1.0; - u = t--; /* T[i-1] */ - *u++ = x; - v = u--; /* T[i] */ - - /* Evaluate chebyshev series formulation using iterative approach */ - - for(i=2;i<=m/2;i++) - *v++ = (2*x)*(*u++) - *t++; /* T[i] = 2*x*T[i-1] - T[i-2] */ - - sum=0.0; /* initialise sum to zero */ - t = T; /* reset pointer */ - - /* Evaluate polynomial and return value also free memory space */ - - for(i=0;i<=m/2;i++) - sum+=coef[(m/2)-i]**t++; - - return sum; -} - - -/*---------------------------------------------------------------------------*\ - - FUNCTION....: lpc_to_lsp() - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 - - This function converts LPC coefficients to LSP coefficients. - -\*---------------------------------------------------------------------------*/ - -int lpc_to_lsp (float *a, int lpcrdr, float *freq, int nb, float delta) -/* float *a lpc coefficients */ -/* int lpcrdr order of LPC coefficients (10) */ -/* float *freq LSP frequencies in radians */ -/* int nb number of sub-intervals (4) */ -/* float delta grid spacing interval (0.02) */ -{ - float psuml,psumr,psumm,temp_xr,xl,xr,xm = 0; - float temp_psumr; - int i,j,m,flag,k; - float *px; /* ptrs of respective P'(z) & Q'(z) */ - float *qx; - float *p; - float *q; - float *pt; /* ptr used for cheb_poly_eval() - whether P' or Q' */ - int roots=0; /* number of roots found */ - float Q[LSP_MAX_ORDER + 1]; - float P[LSP_MAX_ORDER + 1]; - - flag = 1; - m = lpcrdr/2; /* order of P'(z) & Q'(z) polynimials */ - - /* Allocate memory space for polynomials */ - - /* determine P'(z)'s and Q'(z)'s coefficients where - P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */ - - px = P; /* initilaise ptrs */ - qx = Q; - p = px; - q = qx; - *px++ = 1.0; - *qx++ = 1.0; - for(i=1;i<=m;i++){ - *px++ = a[i]+a[lpcrdr+1-i]-*p++; - *qx++ = a[i]-a[lpcrdr+1-i]+*q++; - } - px = P; - qx = Q; - for(i=0;i<m;i++){ - *px = 2**px; - *qx = 2**qx; - px++; - qx++; - } - px = P; /* re-initialise ptrs */ - qx = Q; - - /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z). - Keep alternating between the two polynomials as each zero is found */ - - xr = 0; /* initialise xr to zero */ - xl = 1.0; /* start at point xl = 1 */ - - - for(j=0;j<lpcrdr;j++){ - if(j%2) /* determines whether P' or Q' is eval. */ - pt = qx; - else - pt = px; - - psuml = cheb_poly_eva(pt,xl,lpcrdr); /* evals poly. at xl */ - flag = 1; - while(flag && (xr >= -1.0)){ - xr = xl - delta ; /* interval spacing */ - psumr = cheb_poly_eva(pt,xr,lpcrdr);/* poly(xl-delta_x) */ - temp_psumr = psumr; - temp_xr = xr; - - /* if no sign change increment xr and re-evaluate - poly(xr). Repeat til sign change. if a sign change has - occurred the interval is bisected and then checked again - for a sign change which determines in which interval the - zero lies in. If there is no sign change between poly(xm) - and poly(xl) set interval between xm and xr else set - interval between xl and xr and repeat till root is located - within the specified limits */ - - if((psumr*psuml)<0.0){ - roots++; - - psumm=psuml; - for(k=0;k<=nb;k++){ - xm = (xl+xr)/2; /* bisect the interval */ - psumm=cheb_poly_eva(pt,xm,lpcrdr); - if(psumm*psuml>0.){ - psuml=psumm; - xl=xm; - } - else{ - psumr=psumm; - xr=xm; - } - } - - /* once zero is found, reset initial interval to xr */ - freq[j] = (xm); - xl = xm; - flag = 0; /* reset flag for next search */ - } - else{ - psuml=temp_psumr; - xl=temp_xr; - } - } - } - - /* convert from x domain to radians */ - - for(i=0; i<lpcrdr; i++) { - freq[i] = acos(freq[i]); - } - - return(roots); -} - -/*---------------------------------------------------------------------------*\ - - FUNCTION....: lsp_to_lpc() - AUTHOR......: David Rowe - DATE CREATED: 24/2/93 - - This function converts LSP coefficients to LPC coefficients. In the - Speex code we worked out a way to simplify this significantly. - -\*---------------------------------------------------------------------------*/ - -void lsp_to_lpc(float *lsp, float *ak, int lpcrdr) -/* float *freq array of LSP frequencies in radians */ -/* float *ak array of LPC coefficients */ -/* int lpcrdr order of LPC coefficients */ - - -{ - int i,j; - float xout1,xout2,xin1,xin2; - float *pw,*n1,*n2,*n3,*n4 = 0; - int m = lpcrdr/2; - float freq[LSP_MAX_ORDER]; - float Wp[(LSP_MAX_ORDER * 4) + 2]; - - /* convert from radians to the x=cos(w) domain */ - - for(i=0; i<lpcrdr; i++) - freq[i] = cos(lsp[i]); - - pw = Wp; - - /* initialise contents of array */ - - for(i=0;i<=4*m+1;i++){ /* set contents of buffer to 0 */ - *pw++ = 0.0; - } - - /* Set pointers up */ - - pw = Wp; - xin1 = 1.0; - xin2 = 1.0; - - /* reconstruct P(z) and Q(z) by cascading second order polynomials - in form 1 - 2xz(-1) +z(-2), where x is the LSP coefficient */ - - for(j=0;j<=lpcrdr;j++){ - for(i=0;i<m;i++){ - n1 = pw+(i*4); - n2 = n1 + 1; - n3 = n2 + 1; - n4 = n3 + 1; - xout1 = xin1 - 2*(freq[2*i]) * *n1 + *n2; - xout2 = xin2 - 2*(freq[2*i+1]) * *n3 + *n4; - *n2 = *n1; - *n4 = *n3; - *n1 = xin1; - *n3 = xin2; - xin1 = xout1; - xin2 = xout2; - } - xout1 = xin1 + *(n4+1); - xout2 = xin2 - *(n4+2); - ak[j] = (xout1 + xout2)*0.5; - *(n4+1) = xin1; - *(n4+2) = xin2; - - xin1 = 0.0; - xin2 = 0.0; - } -} - |