From 9e5b2114b6c3ac438251a21fe1fe4cbdc8f7bc1b Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 22 Aug 1999 07:30:15 +0000 Subject: [PATCH] Added baised log frequency scaling and energy normalization to curve encoding. See the comments for details. Monty 19990822 svn path=/trunk/vorbis/; revision=73 --- lib/lpc.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ lib/lpc.h | 15 +++-- 2 files changed, 186 insertions(+), 23 deletions(-) diff --git a/lib/lpc.c b/lib/lpc.c index 4e00321..e8c6cc1 100644 --- a/lib/lpc.c +++ b/lib/lpc.c @@ -14,16 +14,15 @@ function: LPC low level routines author: Monty modifications by: Monty - last modification date: Aug 02 1999 + last modification date: Aug 22 1999 ********************************************************************/ /* Some of these routines (autocorrelator, LPC coefficient estimator) - are directly derived from and/or modified from code written by - Jutta Degener and Carsten Bormann; thus we include their copyright - below. The entirety of this file is freely redistributable on the - condition that both of these copyright notices are preserved - without modification. */ + are derived from code written by Jutta Degener and Carsten Bormann; + thus we include their copyright below. The entirety of this file + is freely redistributable on the condition that both of these + copyright notices are preserved without modification. */ /* Preserved Copyright: *********************************************/ @@ -48,10 +47,12 @@ Carsten Bormann *********************************************************************/ #include +#include #include #include #include "smallft.h" #include "lpc.h" +#include "xlogmap.h" /* This is pared down for Vorbis where we only use LPC to encode spectral envelope curves. Thus we only are interested in @@ -62,7 +63,53 @@ Carsten Bormann /* Input : n element envelope curve Output: m lpc coefficients, excitation energy */ -double vorbis_curve_to_lpc(double *curve,int n,double *lpc,int m){ +double memcof(double *data, int n, int m, double *d){ + int k,j,i; + double p=0.,wk1[n],wk2[n],wkm[m],xms; + + memset(wk1,0,sizeof(wk1)); + memset(wk2,0,sizeof(wk2)); + memset(wkm,0,sizeof(wkm)); + + for (j=0;jn=n; + l->m=m; + l->escale=malloc(n*sizeof(double)); + l->dscale=malloc(n*sizeof(double)); + l->norm=malloc(n*sizeof(double)); + + for(i=0;inorm[i]=logB-logA; /* this much */ + } + + /* the scale is encode/decode specific for algebraic simplicity */ + + if(encode_p){ + /* encode */ + + for(i=0;iescale[i]=LINEAR_X(i/scale,bias); + + } + /* decode; encode may use this too */ + + { + double w=1./oct*M_PI; + for(i=0;idscale[i]=LOG_X(i,bias)*w; + } +} + +void lpc_clear(lpc_lookup *l){ + if(l){ + if(l->escale)free(l->escale); + free(l->dscale); + 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. */ + + int n=l->n; + int m=l->m; + int mapped=n; + double work[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); + + } + + memcpy(curve,work,sizeof(work)); + + return vorbis_gen_lpc(work,mapped,lpc,l->m); +} + /* generate the whole freq response curve on an LPC IIR filter */ -void vorbis_lpc_to_curve(double *curve,int n,double *lpc, double amp,int m){ +void vorbis_lpc_to_curve(double *curve,double *lpc,double amp,lpc_lookup *l){ int i; - double w=1./n*M_PI; - for(i=0;in;i++) + curve[i]=vorbis_lpc_magnitude(l->dscale[i],lpc,l->m)*amp*l->norm[i]; } /* find frequency response of LPC filter only at nonsero residue points and apply the envelope to the residue */ -void vorbis_lpc_apply(double *residue,int n,double *lpc, double amp,int m){ +void vorbis_lpc_apply(double *residue,double *lpc,double amp,lpc_lookup *l){ int i; - double w=1./n*M_PI; - for(i=0;in;i++) if(residue[i]) - residue[i]*=vorbis_lpc_magnitude(i*w,lpc,m)*amp; + residue[i]*=vorbis_lpc_magnitude(l->dscale[i],lpc,l->m)*amp*l->norm[i]; } diff --git a/lib/lpc.h b/lib/lpc.h index 431d7ab..e21f73b 100644 --- a/lib/lpc.h +++ b/lib/lpc.h @@ -18,10 +18,15 @@ #ifndef _V_LPC_H_ #define _V_LPC_H_ -extern double vorbis_curve_to_lpc(double *curve,int n,double *lpc,int m); -extern void vorbis_lpc_to_curve(double *curve,int n,double *lpc, - double amp,int m); -extern void vorbis_lpc_apply(double *residue,int n,double *lpc, - double amp,int m); +#include "codec.h" + +extern double lpc_init(lpc_lookup *l,int n, int m, int oct, int encode_p); +extern void lpc_clear(lpc_lookup *l); + +extern double vorbis_curve_to_lpc(double *curve,double *lpc,lpc_lookup *l); +extern void vorbis_lpc_to_curve(double *curve,double *lpc, double amp, + lpc_lookup *l); +extern void vorbis_lpc_apply(double *residue,double *lpc, double amp, + lpc_lookup *l); #endif -- 2.7.4