X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Flpc.c;h=798f4cf0766418856ad02c77ebdc9e583a8a01e6;hb=a9eb99a5bd6f2d7da02d6cd13a428baf3a1bf48c;hp=18c435ad5ab88316666123f7239c30fc99ff251f;hpb=685d0681535cf41a80023e30ebb00be4aa76d4be;p=platform%2Fupstream%2Flibvorbis.git diff --git a/lib/lpc.c b/lib/lpc.c index 18c435a..798f4cf 100644 --- a/lib/lpc.c +++ b/lib/lpc.c @@ -1,18 +1,16 @@ /******************************************************************** * * - * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. * - * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * - * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. * - * PLEASE READ THESE TERMS DISTRIBUTING. * + * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * * * - * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 * - * by Monty and The XIPHOPHORUS Company * - * http://www.xiph.org/ * + * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * * * ******************************************************************** function: LPC low level routines - last mod: $Id: lpc.c,v 1.10 1999/12/30 07:26:40 xiphmont Exp $ ********************************************************************/ @@ -45,46 +43,48 @@ Carsten Bormann *********************************************************************/ #include -#include #include #include #include "os.h" #include "smallft.h" #include "lpc.h" -#include "xlogmap.h" +#include "scales.h" +#include "misc.h" -/* This is pared down for Vorbis. Autocorrelation LPC coeff generation - algorithm invented by N. Levinson in 1947, modified by J. Durbin in - 1959. */ +/* Autocorrelation LPC coeff generation algorithm invented by + N. Levinson in 1947, modified by J. Durbin in 1959. */ /* Input : n elements of time doamin data Output: m lpc coefficients, excitation energy */ - -double vorbis_lpc_from_data(double *data,double *lpc,int n,int m){ - double *aut=alloca(sizeof(double)*(m+1)); +float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){ + double *aut=alloca(sizeof(*aut)*(m+1)); + double *lpc=alloca(sizeof(*lpc)*(m)); double error; + double epsilon; int i,j; /* autocorrelation, p+1 lag coefficients */ - j=m+1; while(j--){ - double d=0; - for(i=j;iln; - int m=l->m; - double *work=alloca(sizeof(double)*(n+n)); - double fscale=.5/n; - int i,j; - - /* input is a real curve. make it complex-real */ - /* This mixes phase, but the LPC generation doesn't care. */ - for(i=0;ifft,work); - - /* The autocorrelation will not be circular. Shift, else we lose - most of the power in the edges. */ - - for(i=0,j=n/2;in=n; - l->ln=mapped; - l->m=m; - l->iscale=malloc(n*sizeof(int)); - l->ifrac=malloc(n*sizeof(double)); - l->norm=malloc(n*sizeof(double)); + error*=1.-r*r; - for(i=0;inorm[i]=logB-logA; /* this much */ } - /* the scale is encode/decode specific for algebraic simplicity */ - - if(encode_p){ - /* encode */ - l->escale=malloc(mapped*sizeof(double)); - l->uscale=malloc(n*sizeof(int)); - - /* undersample guard */ - for(i=0;iuscale[i]=rint(LOG_X(i,bias)/oct*mapped); - } + done: - for(i=0;iescale[i]=LINEAR_X(i/scale,bias); - l->uscale[(int)(floor(l->escale[i]))]=-1; - l->uscale[(int)(ceil(l->escale[i]))]=-1; - } - - - } - /* decode; encode may use this too */ - - drft_init(&l->fft,mapped*2); - for(i=0;iiscale[i]=floor(is); - if(l->iscale[i]>=l->ln-1)l->iscale[i]=l->ln-2; - - l->ifrac[i]=is-floor(is); - if(l->ifrac[i]>1.)l->ifrac[i]=1.; - - } -} - -void lpc_clear(lpc_lookup *l){ - if(l){ - if(l->escale)free(l->escale); - drft_clear(&l->fft); - free(l->iscale); - free(l->ifrac); - free(l->norm); - } -} - - -/* less efficient than the decode side (written for clarity). We're - not bottlenecked here anyway */ - -double vorbis_curve_to_lpc(double *curve,double *lpc,lpc_lookup *l){ - /* map the input curve to a log curve for encoding */ - - /* for clarity, mapped and n are both represented although setting - 'em equal is a decent rule of thumb. The below must be reworked - slightly if mapped != n */ - - int mapped=l->ln; - double *work=alloca(sizeof(double)*mapped); - int i; - - /* fairly correct for low frequencies, naieve for high frequencies - (suffers from undersampling) */ - for(i=0;iescale[i]; - int a=floor(lin); - int b=ceil(lin); - double del=lin-floor(lin); - - work[i]=(curve[a]/l->norm[a]*(1.-del)+ - curve[b]/l->norm[b]*del); - - } - - /* for(i=0;in;i++) - if(l->uscale[i]>0) - if(work[l->uscale[i]]uscale[i]]=curve[i];*/ - -#ifdef ANALYSIS + /* slightly damp the filter */ { - int j; - FILE *out; - char buffer[80]; - static int frameno=0; - - sprintf(buffer,"preloglpc%d.m",frameno++); - out=fopen(buffer,"w+"); - for(j=0;jln;j++) - fprintf(out,"%g\n",work[j]); - fclose(out); - } -#endif - - return vorbis_lpc_from_spectrum(work,lpc,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. This could stand - optimization; it could both be more precise as well as not compute - quite a few unused values */ - -void _vlpc_de_helper(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]); - curve[i]=(1./hypot(real+unit,imag)); - } - } -} - - -/* generate the whole freq response curve on an LPC IIR filter */ - -void vorbis_lpc_to_curve(double *curve,double *lpc,double amp,lpc_lookup *l){ - double *lcurve=alloca(sizeof(double)*(l->ln*2)); - int i; - - _vlpc_de_helper(lcurve,lpc,amp,l); - -#ifdef ANALYSIS - { - int j; - FILE *out; - char buffer[80]; - static int frameno=0; - - sprintf(buffer,"loglpc%d.m",frameno++); - out=fopen(buffer,"w+"); - for(j=0;jln;j++) - fprintf(out,"%g\n",lcurve[j]); - fclose(out); - } -#endif - - if(amp==0)return; - - for(i=0;in;i++){ - int ii=l->iscale[i]; - curve[i]=((1.-l->ifrac[i])*lcurve[ii]+ - l->ifrac[i]*lcurve[ii+1])*l->norm[i]; - } - -} - -void vorbis_lpc_apply(double *residue,double *lpc,double amp,lpc_lookup *l){ - double *lcurve=alloca(sizeof(double)*((l->ln+l->n)*2)); - int i; - - if(amp==0){ - memset(residue,0,l->n*sizeof(double)); - }else{ - - _vlpc_de_helper(lcurve,lpc,amp,l); - - for(i=0;in;i++){ - if(residue[i]!=0){ - int ii=l->iscale[i]; - residue[i]*=((1.-l->ifrac[i])*lcurve[ii]+ - l->ifrac[i]*lcurve[ii+1])*l->norm[i]; - } + double g = .99; + double damp = g; + for(j=0;j