summaryrefslogtreecommitdiffstats
path: root/songdbj/com/jcraft/jorbis/Lpc.java
diff options
context:
space:
mode:
Diffstat (limited to 'songdbj/com/jcraft/jorbis/Lpc.java')
-rw-r--r--songdbj/com/jcraft/jorbis/Lpc.java254
1 files changed, 254 insertions, 0 deletions
diff --git a/songdbj/com/jcraft/jorbis/Lpc.java b/songdbj/com/jcraft/jorbis/Lpc.java
new file mode 100644
index 0000000000..452ed86d91
--- /dev/null
+++ b/songdbj/com/jcraft/jorbis/Lpc.java
@@ -0,0 +1,254 @@
+/* JOrbis
+ * Copyright (C) 2000 ymnk, JCraft,Inc.
+ *
+ * Written by: 2000 ymnk<ymnk@jcraft.com>
+ *
+ * Many thanks to
+ * Monty <monty@xiph.org> and
+ * The XIPHOPHORUS Company http://www.xiph.org/ .
+ * JOrbis has been based on their awesome works, Vorbis codec.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+package com.jcraft.jorbis;
+
+class Lpc{
+ // en/decode lookups
+ Drft fft=new Drft();;
+
+ int ln;
+ int m;
+
+ // 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
+
+ static float lpc_from_data(float[] data, float[] lpc,int n,int m){
+ float[] aut=new float[m+1];
+ float error;
+ int i,j;
+
+ // autocorrelation, p+1 lag coefficients
+
+ j=m+1;
+ while(j--!=0){
+ float d=0;
+ for(i=j;i<n;i++)d+=data[i]*data[i-j];
+ aut[j]=d;
+ }
+
+ // Generate lpc coefficients from autocorr values
+
+ error=aut[0];
+ /*
+ if(error==0){
+ for(int k=0; k<m; k++) lpc[k]=0.0f;
+ return 0;
+ }
+ */
+
+ for(i=0;i<m;i++){
+ float r=-aut[i+1];
+
+ if(error==0){
+ for(int k=0; k<m; k++) lpc[k]=0.0f;
+ return 0;
+ }
+
+ // Sum up this iteration's reflection coefficient; note that in
+ // Vorbis we don't save it. If anyone wants to recycle this code
+ // and needs reflection coefficients, save the results of 'r' from
+ // each iteration.
+
+ for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
+ r/=error;
+
+ // Update LPC coefficients and total error
+
+ lpc[i]=r;
+ for(j=0;j<i/2;j++){
+ float tmp=lpc[j];
+ lpc[j]+=r*lpc[i-1-j];
+ lpc[i-1-j]+=r*tmp;
+ }
+ if(i%2!=0)lpc[j]+=lpc[j]*r;
+
+ error*=1.0-r*r;
+ }
+
+ // we need the error value to know how big an impulse to hit the
+ // filter with later
+
+ return error;
+ }
+
+ // Input : n element envelope spectral curve
+ // Output: m lpc coefficients, excitation energy
+
+ float lpc_from_curve(float[] curve, float[] lpc){
+ int n=ln;
+ float[] work=new float[n+n];
+ float fscale=(float)(.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;i<n;i++){
+ work[i*2]=curve[i]*fscale;
+ work[i*2+1]=0;
+ }
+ work[n*2-1]=curve[n-1]*fscale;
+
+ n*=2;
+ fft.backward(work);
+
+ // The autocorrelation will not be circular. Shift, else we lose
+ // most of the power in the edges.
+
+ for(i=0,j=n/2;i<n/2;){
+ float temp=work[i];
+ work[i++]=work[j];
+ work[j++]=temp;
+ }
+
+ return(lpc_from_data(work,lpc,n,m));
+ }
+
+ void init(int mapped, int m){
+ //memset(l,0,sizeof(lpc_lookup));
+
+ ln=mapped;
+ this.m=m;
+
+ // we cheat decoding the LPC spectrum via FFTs
+ fft.init(mapped*2);
+ }
+
+ void clear(){
+ fft.clear();
+ }
+
+ static float FAST_HYPOT(float a, float b){
+ return (float)Math.sqrt((a)*(a) + (b)*(b));
+ }
+
+ // 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 lpc_to_curve(float[] curve, float[] lpc, float amp){
+
+ //memset(curve,0,sizeof(float)*l->ln*2);
+ for(int i=0; i<ln*2; i++)curve[i]=0.0f;
+
+ if(amp==0)return;
+
+ for(int i=0;i<m;i++){
+ curve[i*2+1]=lpc[i]/(4*amp);
+ curve[i*2+2]=-lpc[i]/(4*amp);
+ }
+
+ fft.backward(curve); // reappropriated ;-)
+
+ {
+ int l2=ln*2;
+ float unit=(float)(1./amp);
+ curve[0]=(float)(1./(curve[0]*2+unit));
+ for(int i=1;i<ln;i++){
+ float real=(curve[i]+curve[l2-i]);
+ float imag=(curve[i]-curve[l2-i]);
+
+ float a = real + unit;
+ curve[i] = (float)(1.0 / FAST_HYPOT(a, imag));
+ }
+ }
+ }
+
+/*
+ // subtract or add an lpc filter to data. Vorbis doesn't actually use this.
+
+ static void lpc_residue(float[] coeff, float[] prime,int m,
+ float[] data, int n){
+
+ // 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
+
+ float[] work=new float[m+n];
+ float y;
+
+ if(prime==null){
+ for(int i=0;i<m;i++){
+ work[i]=0;
+ }
+ }
+ else{
+ for(int i=0;i<m;i++){
+ work[i]=prime[i];
+ }
+ }
+
+ for(int i=0;i<n;i++){
+ y=0;
+ for(int j=0;j<m;j++){
+ y-=work[i+j]*coeff[m-j-1];
+ }
+ work[i+m]=data[i];
+ data[i]-=y;
+ }
+ }
+
+ static void lpc_predict(float[] coeff, float[] prime,int m,
+ float[] data, int n){
+
+ // in: coeff[0...m-1] LPC coefficients
+ // prime[0...m-1] initial values (allocated size of n+m-1)
+ // data[0...n-1] residuals from LPC prediction
+ // out: data[0...n-1] data samples
+
+ int o,p;
+ float y;
+ float[] work=new float[m+n];
+
+ if(prime==null){
+ for(int i=0;i<m;i++){
+ work[i]=0.f;
+ }
+ }
+ else{
+ for(int i=0;i<m;i++){
+ work[i]=prime[i];
+ }
+ }
+
+ for(int i=0;i<n;i++){
+ y=data[i];
+ o=i;
+ p=m;
+ for(int j=0;j<m;j++){
+ y-=work[o++]*coeff[--p];
+ }
+ data[i]=work[o]=y;
+ }
+ }
+*/
+}