]> Joshua Wise's Git repositories - patchfork.git/blame - jorbis/src/com/jcraft/jorbis/Lpc.java
initial import from pitchfork-0.5.5
[patchfork.git] / jorbis / src / com / jcraft / jorbis / Lpc.java
CommitLineData
964dd0bc
JW
1/* JOrbis
2 * Copyright (C) 2000 ymnk, JCraft,Inc.
3 *
4 * Written by: 2000 ymnk<ymnk@jcraft.com>
5 *
6 * Many thanks to
7 * Monty <monty@xiph.org> and
8 * The XIPHOPHORUS Company http://www.xiph.org/ .
9 * JOrbis has been based on their awesome works, Vorbis codec.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public License
13 * as published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26package com.jcraft.jorbis;
27
28class Lpc{
29 // en/decode lookups
30 Drft fft=new Drft();;
31
32 int ln;
33 int m;
34
35 // Autocorrelation LPC coeff generation algorithm invented by
36 // N. Levinson in 1947, modified by J. Durbin in 1959.
37
38 // Input : n elements of time doamin data
39 // Output: m lpc coefficients, excitation energy
40
41 static float lpc_from_data(float[] data, float[] lpc,int n,int m){
42 float[] aut=new float[m+1];
43 float error;
44 int i,j;
45
46 // autocorrelation, p+1 lag coefficients
47
48 j=m+1;
49 while(j--!=0){
50 float d=0;
51 for(i=j;i<n;i++)d+=data[i]*data[i-j];
52 aut[j]=d;
53 }
54
55 // Generate lpc coefficients from autocorr values
56
57 error=aut[0];
58 /*
59 if(error==0){
60 for(int k=0; k<m; k++) lpc[k]=0.0f;
61 return 0;
62 }
63 */
64
65 for(i=0;i<m;i++){
66 float r=-aut[i+1];
67
68 if(error==0){
69 for(int k=0; k<m; k++) lpc[k]=0.0f;
70 return 0;
71 }
72
73 // Sum up this iteration's reflection coefficient; note that in
74 // Vorbis we don't save it. If anyone wants to recycle this code
75 // and needs reflection coefficients, save the results of 'r' from
76 // each iteration.
77
78 for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
79 r/=error;
80
81 // Update LPC coefficients and total error
82
83 lpc[i]=r;
84 for(j=0;j<i/2;j++){
85 float tmp=lpc[j];
86 lpc[j]+=r*lpc[i-1-j];
87 lpc[i-1-j]+=r*tmp;
88 }
89 if(i%2!=0)lpc[j]+=lpc[j]*r;
90
91 error*=1.0-r*r;
92 }
93
94 // we need the error value to know how big an impulse to hit the
95 // filter with later
96
97 return error;
98 }
99
100 // Input : n element envelope spectral curve
101 // Output: m lpc coefficients, excitation energy
102
103 float lpc_from_curve(float[] curve, float[] lpc){
104 int n=ln;
105 float[] work=new float[n+n];
106 float fscale=(float)(.5/n);
107 int i,j;
108
109 // input is a real curve. make it complex-real
110 // This mixes phase, but the LPC generation doesn't care.
111 for(i=0;i<n;i++){
112 work[i*2]=curve[i]*fscale;
113 work[i*2+1]=0;
114 }
115 work[n*2-1]=curve[n-1]*fscale;
116
117 n*=2;
118 fft.backward(work);
119
120 // The autocorrelation will not be circular. Shift, else we lose
121 // most of the power in the edges.
122
123 for(i=0,j=n/2;i<n/2;){
124 float temp=work[i];
125 work[i++]=work[j];
126 work[j++]=temp;
127 }
128
129 return(lpc_from_data(work,lpc,n,m));
130 }
131
132 void init(int mapped, int m){
133 //memset(l,0,sizeof(lpc_lookup));
134
135 ln=mapped;
136 this.m=m;
137
138 // we cheat decoding the LPC spectrum via FFTs
139 fft.init(mapped*2);
140 }
141
142 void clear(){
143 fft.clear();
144 }
145
146 static float FAST_HYPOT(float a, float b){
147 return (float)Math.sqrt((a)*(a) + (b)*(b));
148 }
149
150 // One can do this the long way by generating the transfer function in
151 // the time domain and taking the forward FFT of the result. The
152 // results from direct calculation are cleaner and faster.
153 //
154 // This version does a linear curve generation and then later
155 // interpolates the log curve from the linear curve.
156
157 void lpc_to_curve(float[] curve, float[] lpc, float amp){
158
159 //memset(curve,0,sizeof(float)*l->ln*2);
160 for(int i=0; i<ln*2; i++)curve[i]=0.0f;
161
162 if(amp==0)return;
163
164 for(int i=0;i<m;i++){
165 curve[i*2+1]=lpc[i]/(4*amp);
166 curve[i*2+2]=-lpc[i]/(4*amp);
167 }
168
169 fft.backward(curve); // reappropriated ;-)
170
171 {
172 int l2=ln*2;
173 float unit=(float)(1./amp);
174 curve[0]=(float)(1./(curve[0]*2+unit));
175 for(int i=1;i<ln;i++){
176 float real=(curve[i]+curve[l2-i]);
177 float imag=(curve[i]-curve[l2-i]);
178
179 float a = real + unit;
180 curve[i] = (float)(1.0 / FAST_HYPOT(a, imag));
181 }
182 }
183 }
184
185/*
186 // subtract or add an lpc filter to data. Vorbis doesn't actually use this.
187
188 static void lpc_residue(float[] coeff, float[] prime,int m,
189 float[] data, int n){
190
191 // in: coeff[0...m-1] LPC coefficients
192 // prime[0...m-1] initial values
193 // data[0...n-1] data samples
194 // out: data[0...n-1] residuals from LPC prediction
195
196 float[] work=new float[m+n];
197 float y;
198
199 if(prime==null){
200 for(int i=0;i<m;i++){
201 work[i]=0;
202 }
203 }
204 else{
205 for(int i=0;i<m;i++){
206 work[i]=prime[i];
207 }
208 }
209
210 for(int i=0;i<n;i++){
211 y=0;
212 for(int j=0;j<m;j++){
213 y-=work[i+j]*coeff[m-j-1];
214 }
215 work[i+m]=data[i];
216 data[i]-=y;
217 }
218 }
219
220 static void lpc_predict(float[] coeff, float[] prime,int m,
221 float[] data, int n){
222
223 // in: coeff[0...m-1] LPC coefficients
224 // prime[0...m-1] initial values (allocated size of n+m-1)
225 // data[0...n-1] residuals from LPC prediction
226 // out: data[0...n-1] data samples
227
228 int o,p;
229 float y;
230 float[] work=new float[m+n];
231
232 if(prime==null){
233 for(int i=0;i<m;i++){
234 work[i]=0.f;
235 }
236 }
237 else{
238 for(int i=0;i<m;i++){
239 work[i]=prime[i];
240 }
241 }
242
243 for(int i=0;i<n;i++){
244 y=data[i];
245 o=i;
246 p=m;
247 for(int j=0;j<m;j++){
248 y-=work[o++]*coeff[--p];
249 }
250 data[i]=work[o]=y;
251 }
252 }
253*/
254}
This page took 0.04309 seconds and 4 git commands to generate.