int lpc_to_lsp (float *a,int lpcrdr,float *freq,int nb,float delta, char *stack) /* float *a lpc coefficients */ /* int lpcrdr order of LPC coefficients (10) */ /* float *freq LSP frequencies in the x domain */ /* 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/*,temp_qsumr*/; int i,j,m,flag,k; float *Q; /* ptrs for memory allocation */ float *P; 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; /* DR 8/2/94: number of roots found */ flag = 1; /* program is searching for a root when, 1 else has found one */ m = lpcrdr/2; /* order of P'(z) & Q'(z) polynomials */ /* Allocate memory space for polynomials */ Q = PUSH(stack, (m+1), float); P = PUSH(stack, (m+1), float); /* 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; /* initialise 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,stack); /* evals poly. at xl */ flag = 1; while(flag && (xr >= -1.0)){ float dd; /* Modified by JMV to provide smaller steps around x=+-1 */ dd=(delta*(1-.9*xl*xl)); if (fabs(psuml)<.2) dd *= .5; xr = xl - dd; /* interval spacing */ psumr = cheb_poly_eva(pt,xr,lpcrdr,stack);/* 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,stack); 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; } } } return(roots); }
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) || (psumr == 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); }
int lpc_to_lsp (spx_coef_t *a,int lpcrdr,spx_lsp_t *freq,int nb,spx_word16_t delta, char *stack) /* float *a lpc coefficients */ /* int lpcrdr order of LPC coefficients (10) */ /* float *freq LSP frequencies in the x domain */ /* int nb number of sub-intervals (4) */ /* float delta grid spacing interval (0.02) */ { spx_word16_t temp_xr,xl,xr,xm=0; spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/; int i,j,m,flag,k; spx_word32_t *Q; /* ptrs for memory allocation */ spx_word32_t *P; spx_word32_t *px; /* ptrs of respective P'(z) & Q'(z) */ spx_word32_t *qx; spx_word32_t *p; spx_word32_t *q; spx_word32_t *pt; /* ptr used for cheb_poly_eval() whether P' or Q' */ int roots=0; /* DR 8/2/94: number of roots found */ flag = 1; /* program is searching for a root when, 1 else has found one */ m = lpcrdr/2; /* order of P'(z) & Q'(z) polynomials */ /* Allocate memory space for polynomials */ Q = PUSH(stack, (m+1), spx_word32_t); P = PUSH(stack, (m+1), spx_word32_t); /* 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; /* initialise ptrs */ qx = Q; p = px; q = qx; #ifdef FIXED_POINT *px++ = LPC_SCALING; *qx++ = LPC_SCALING; 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++) { /*if (fabs(*px)>=32768) speex_warning_int("px", *px); if (fabs(*qx)>=32768) speex_warning_int("qx", *qx);*/ *px = (2+*px)>>2; *qx = (2+*qx)>>2; px++; qx++; } P[m] = PSHR(P[m],3); Q[m] = PSHR(Q[m],3); #else *px++ = LPC_SCALING; *qx++ = LPC_SCALING; 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++; } #endif 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 = FREQ_SCALE; /* start at point xl = 1 */ for(j=0;j<lpcrdr;j++){ if(j&1) /* determines whether P' or Q' is eval. */ pt = qx; else pt = px; psuml = cheb_poly_eva(pt,xl,lpcrdr,stack); /* evals poly. at xl */ flag = 1; while(flag && (xr >= -FREQ_SCALE)){ spx_word16_t dd; /* Modified by JMV to provide smaller steps around x=+-1 */ #ifdef FIXED_POINT dd = MULT16_16_Q15(delta,(FREQ_SCALE - MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000))); if (psuml<512 && psuml>-512) dd = PSHR(dd,1); #else dd=delta*(1-.9*xl*xl); if (fabs(psuml)<.2) dd *= .5; #endif xr = xl - dd; /* interval spacing */ psumr = cheb_poly_eva(pt,xr,lpcrdr,stack);/* 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(SIGN_CHANGE(psumr,psuml)) { roots++; psumm=psuml; for(k=0;k<=nb;k++){ #ifdef FIXED_POINT xm = ADD16(PSHR(xl,1),PSHR(xr,1)); /* bisect the interval */ #else xm = .5*(xl+xr); /* bisect the interval */ #endif psumm=cheb_poly_eva(pt,xm,lpcrdr,stack); /*if(psumm*psuml>0.)*/ if(!SIGN_CHANGE(psumm,psuml)) { psuml=psumm; xl=xm; } else { psumr=psumm; xr=xm; } } /* once zero is found, reset initial interval to xr */ freq[j] = X2ANGLE(xm); xl = xm; flag = 0; /* reset flag for next search */ } else{ psuml=temp_psumr; xl=temp_xr; } } } return(roots); }