From: Monty Date: Sat, 19 Aug 2000 11:46:28 +0000 (+0000) Subject: All new LSP->freq envelope curve computation code. X-Git-Tag: v1.3.3~1153 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e74b2b02da2d3712eca332c2bf3e4f734b1223a0;p=platform%2Fupstream%2Flibvorbis.git All new LSP->freq envelope curve computation code. It turns out that LSP->LPC using the impulse response algorithm is *very* sensitive to noise, and doubles really are necessary. Unfortunate, that. Reimplmented the code with a direct LSP->curve computation, skipping the LPC intermediary step. This also eliminates any need for the LPC or iFFT code in decode/synthesis. Monty svn path=/trunk/vorbis/; revision=597 --- diff --git a/lib/floor0.c b/lib/floor0.c index 13642e6..ce30444 100644 --- a/lib/floor0.c +++ b/lib/floor0.c @@ -12,7 +12,7 @@ ******************************************************************** function: floor backend 0 implementation - last mod: $Id: floor0.c,v 1.20 2000/08/15 09:09:42 xiphmont Exp $ + last mod: $Id: floor0.c,v 1.21 2000/08/19 11:46:28 xiphmont Exp $ ********************************************************************/ @@ -41,6 +41,7 @@ typedef struct { vorbis_info_floor0 *vi; lpc_lookup lpclook; + double *lsp_look; } vorbis_look_floor0; @@ -82,6 +83,7 @@ static void free_look(vorbis_look_floor *i){ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; if(i){ if(look->linearmap)free(look->linearmap); + if(look->lsp_look)free(look->lsp_look); lpc_clear(&look->lpclook); memset(look,0,sizeof(vorbis_look_floor0)); free(look); @@ -145,7 +147,9 @@ static vorbis_look_floor *look (vorbis_dsp_state *vd,vorbis_info_mode *mi, look->n=vi->blocksizes[mi->blockflag]/2; look->ln=info->barkmap; look->vi=info; - lpc_init(&look->lpclook,look->ln,look->m); + + if(vd->analysisp) + lpc_init(&look->lpclook,look->ln,look->m); /* we choose a scaling constant so that: floor(bark(rate/2-1)*C)=mapped-1 @@ -166,6 +170,10 @@ static vorbis_look_floor *look (vorbis_dsp_state *vd,vorbis_info_mode *mi, look->linearmap[j]=val; } + look->lsp_look=malloc(look->ln*sizeof(double)); + for(j=0;jln;j++) + look->lsp_look[j]=2*cos(M_PI/look->ln*j); + return look; } @@ -235,31 +243,17 @@ double _curve_to_lpc(double *curve,double *lpc, /* generate the whole freq response curve of an LPC IIR filter */ -void _lpc_to_curve(double *curve,double *lpc,double amp, +void _lsp_to_curve(double *curve,double *lsp,double amp, vorbis_look_floor0 *l,char *name,long frameno){ /* l->m+1 must be less than l->ln, but guard in case we get a bad stream */ - double *lcurve=alloca(sizeof(double)*max(l->ln*2,l->m*2+2)); + double *lcurve=alloca(sizeof(double)*l->ln); int i; if(amp==0){ memset(curve,0,sizeof(double)*l->n); return; } - vorbis_lpc_to_curve(lcurve,lpc,amp,&(l->lpclook)); - -#if 0 - { /******************/ - FILE *of; - char buffer[80]; - int i; - - sprintf(buffer,"%s_%d.m",name,frameno); - of=fopen(buffer,"w"); - for(i=0;iln;i++) - fprintf(of,"%g\n",lcurve[i]); - fclose(of); - } -#endif + vorbis_lsp_to_curve(lcurve,l->ln,lsp,l->m,amp,l->lsp_look); for(i=0;in;i++)curve[i]=lcurve[l->linearmap[i]]; @@ -335,7 +329,7 @@ static int forward(vorbis_block *vb,vorbis_look_floor *i, #ifdef ANALYSIS if(vb->W==0){fprintf(stderr,"%d ",seq);} vorbis_lsp_to_lpc(out,work,look->m); - _lpc_to_curve(work,work,amp,look,"Ffloor",seq); + _lsp_to_curve(work,work,amp,look,"Ffloor",seq); for(j=0;jn;j++)work[j]-=info->ampdB; _analysis_output("rawfloor",seq,work,look->n,0,0); { @@ -394,8 +388,7 @@ static int forward(vorbis_block *vb,vorbis_look_floor *i, #endif /* take the coefficients back to a spectral envelope curve */ - vorbis_lsp_to_lpc(work,out,look->m); - _lpc_to_curve(out,out,amp,look,"Ffloor",seq++); + _lsp_to_curve(out,work,amp,look,"Ffloor",seq++); for(j=0;jn;j++)out[j]= fromdB(out[j]-info->ampdB); return(1); } @@ -430,8 +423,7 @@ static int inverse(vorbis_block *vb,vorbis_look_floor *i,double *out){ } /* take the coefficients back to a spectral envelope curve */ - vorbis_lsp_to_lpc(out,out,look->m); - _lpc_to_curve(out,out,amp,look,"",0); + _lsp_to_curve(out,out,amp,look,"",0); for(j=0;jn;j++)out[j]=fromdB(out[j]-info->ampdB); return(1); diff --git a/lib/lpc.c b/lib/lpc.c index c94b9ee..3987f7a 100644 --- a/lib/lpc.c +++ b/lib/lpc.c @@ -12,7 +12,7 @@ ******************************************************************** function: LPC low level routines - last mod: $Id: lpc.c,v 1.23 2000/08/15 09:09:43 xiphmont Exp $ + last mod: $Id: lpc.c,v 1.24 2000/08/19 11:46:28 xiphmont Exp $ ********************************************************************/ @@ -165,127 +165,3 @@ void lpc_clear(lpc_lookup *l){ } } -/* One can do this the long way by generating the transfer function in - the time domain and taking the forward FFT of the result. The - results from direct calculation are cleaner and faster. - - This version does a linear curve generation and then later - interpolates the log curve from the linear curve. */ - -void vorbis_lpc_to_curve(double *curve,double *lpc,double amp, - lpc_lookup *l){ - int i; - memset(curve,0,sizeof(double)*l->ln*2); - if(amp==0)return; - - for(i=0;im;i++){ - curve[i*2+1]=lpc[i]/(4*amp); - curve[i*2+2]=-lpc[i]/(4*amp); - } - - drft_backward(&l->fft,curve); /* reappropriated ;-) */ - - { - int l2=l->ln*2; - double unit=1./amp; - curve[0]=(1./(curve[0]*2+unit)); - for(i=1;iln;i++){ - double real=(curve[i]+curve[l2-i]); - double imag=(curve[i]-curve[l2-i]); - - double a = real + unit; - curve[i] = 1.0 / FAST_HYPOT(a, imag); - } - } -} - -/* subtract or add an lpc filter to data. */ - -void vorbis_lpc_filter(double *coeff,double *prime,int m, - double *data,long n,double amp){ - - /* in: coeff[0...m-1] LPC coefficients - prime[0...m-1] initial values - data[0...n-1] data samples - out: data[0...n-1] residuals from LPC prediction */ - - long i,j; - double *work=alloca(sizeof(double)*(m+n)); - double y; - - if(!prime) - for(i=0;i