1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS DISTRIBUTING. *
8 * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999 *
9 * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: LPC low level routines
15 author: Monty <monty@xiph.org>
16 modifications by: Monty
17 last modification date: Aug 02 1999
19 ********************************************************************/
21 /* Some of these routines (autocorrelator, LPC coefficient estimator)
22 are directly derived from and/or modified from code written by
23 Jutta Degener and Carsten Bormann; thus we include their copyright
24 below. The entirety of this file is freely redistributable on the
25 condition that both of these copyright notices are preserved
26 without modification. */
28 /* Preserved Copyright: *********************************************/
30 /* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
31 Technische Universita"t Berlin
33 Any use of this software is permitted provided that this notice is not
34 removed and that neither the authors nor the Technische Universita"t
35 Berlin are deemed to have made any representations as to the
36 suitability of this software for any purpose nor are held responsible
37 for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
40 As a matter of courtesy, the authors request to be informed about uses
41 this software has found, about bugs in this software, and about any
42 improvements that may be of general interest.
48 *********************************************************************/
56 /* This is pared down for Vorbis where we only use LPC to encode
57 spectral envelope curves. Thus we only are interested in
58 generating the coefficients and recovering the curve from the
59 coefficients. Autocorrelation LPC coeff generation algorithm
60 invented by N. Levinson in 1947, modified by J. Durbin in 1959. */
62 /* Input : n element envelope curve
63 Output: m lpc coefficients, excitation energy */
65 double vorbis_curve_to_lpc(double *curve,int n,double *lpc,int m){
66 double aut[m+1],work[n+n],error;
70 /* input is a real curve. make it complex-real */
78 drft_backward(&dl,work);
81 /* The autocorrelation will not be circular. Shift, else we lose
82 most of the power in the edges. */
84 for(i=0,j=n/2;i<n/2;){
90 /* autocorrelation, p+1 lag coefficients */
95 for(i=j;i<n;i++)d+=work[i]*work[i-j];
99 /* Generate lpc coefficients from autocorr values */
103 memset(lpc,0,m*sizeof(double));
110 /* Sum up this iteration's reflection coefficient; note that in
111 Vorbis we don't save it. If anyone wants to recycle this code
112 and needs reflection coefficients, save the results of 'r' from
115 for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
118 /* Update LPC coefficients and total error */
123 lpc[j]+=r*lpc[i-1-j];
126 if(i%2)lpc[j]+=lpc[j]*r;
131 /* we need the error value to know how big an impulse to hit the
137 /* One can do this the long way by generating the transfer function in
138 the time domain and taking the forward FFT of the result. The
139 results from direct calculation are cleaner and faster, however */
141 static double vorbis_lpc_magnitude(double w,double *lpc, int m){
143 double real=1,imag=0;
145 real+=lpc[k]*cos((k+1)*w);
146 imag+=lpc[k]*sin((k+1)*w);
148 return(1./sqrt(real*real+imag*imag));
151 /* generate the whole freq response curve on an LPC IIR filter */
153 void vorbis_lpc_to_curve(double *curve,int n,double *lpc, double amp,int m){
157 curve[i]=vorbis_lpc_magnitude(i*w,lpc,m)*amp;
160 /* find frequency response of LPC filter only at nonsero residue
161 points and apply the envelope to the residue */
163 void vorbis_lpc_apply(double *residue,int n,double *lpc, double amp,int m){
168 residue[i]*=vorbis_lpc_magnitude(i*w,lpc,m)*amp;