package jass.generators; /** Kelly-Lochbaum filter. Follow notation of MATLAB sample code from www.cs.tut.fi/sgn/arg/8003051 and associated writeup therein @author Kees van den Doel (kvdoel@cs.ubc.ca) */ public class KellyLochbaumFilterOld implements Filter { /** Sampling rate in Hertz. */ protected float srate; private static final double DEFAULT_glottalReflectionCoeff = 0; private static final double DEFAULT_dampingCoeff = 1; /** State of filter. */ protected double[] F0,F1,B0,B1; /** How much is reflected back at glottis*/ protected double glottalReflectionCoeff=DEFAULT_glottalReflectionCoeff; /** How much damping in system (1 == no damping)*/ protected double dampingCoeff=DEFAULT_dampingCoeff; /** Scratch variables */ protected double[] F0old,F1old,B0old,B1old; /** This many cylinder segments */ protected int nTubeSections; /** This many junctions (above -1) */ protected int nJunctions; /** Radii of the segments */ protected double[] cylRadius; /** Filter coefficients derived form cylinder radii */ protected double[] kCoeff; /** Create and initialize. @param srate sampling rate in Hertz. @param nTubeSection number of sections */ public KellyLochbaumFilterOld(float srate, int nTubeSections) { this.srate = srate; this.nTubeSections = nTubeSections; this.nJunctions = nTubeSections-1; allocate(); resetFilter(); System.out.println("ns="+nTubeSections); } public KellyLochbaumFilterOld() {} private void allocate() { F0 = new double[nJunctions]; F0old = new double[nJunctions]; F1 = new double[nJunctions]; // F1 needs 1 less really F1old = new double[nJunctions]; B0 = new double[nJunctions]; B0old = new double[nJunctions]; B1 = new double[nJunctions]; B1old = new double[nJunctions]; cylRadius = new double[nTubeSections]; kCoeff = new double[nJunctions]; for(int i=0;i<nJunctions;i++) { cylRadius[i] = 1; } cylRadius[nJunctions] = 1; computeKCoeff(); } /** Compute low level filter values from geometry */ protected void computeKCoeff() { for(int i=0;i<nJunctions;i++) { kCoeff[i] = (cylRadius[i]*cylRadius[i]-cylRadius[i+1]*cylRadius[i+1])/(cylRadius[i]*cylRadius[i]+cylRadius[i+1]*cylRadius[i+1]); } } /** Set an individual segment radius @param k index of segment (0,...) @param r radius to set */ public void setCylinderRadius(int k,double r) { cylRadius[k]=r; computeKCoeff(); } /** Set all radii @param array of r radii */ public void setAllCylinderRadii(double[] r) { for(int k=0;k<nTubeSections;k++) { cylRadius[k]=r[k]; } computeKCoeff(); } /** Clear filter of past history */ public void resetFilter() { for(int i=0;i<nJunctions;i++) { F0[i] = F0old[i] = F1[i] = F1old[i] = 0; B0[i] = B0old[i] = B1[i] = B1old[i] = 0; //System.out.println("B0[0]="+B0[0]); } } /** Set the glottal reflection coeff. @param val glottal reflection coefficient */ public void setGlottalReflectionCoeff(double val) { glottalReflectionCoeff = val; } /** Set damping coeff. (1 == no damping) @param val damping coefficient */ public void setDampingCoeff(double val) { dampingCoeff = val; } /** Proces input (may be same as output). Implements Filter interface @param output user provided buffer for returned result. @param input user provided input buffer. @param nsamples number of samples written to output buffer. @param inputOffset where to start in circular buffer input. */ public void filter(float [] output, float[] input, int nsamples, int inputOffset) { int inputLen = input.length; int ii = inputOffset; for(int i=0;i<nJunctions-1;i++) { double kkk = kCoeff[i]; if(Math.abs(kkk)>=1) { System.out.println("kCoef="+kCoeff[i]); } } //System.out.println("B0[0]="+B0[0]); for(int k=0;k<nsamples;k++) { for(int i=0;i<nJunctions;i++) { F0old[i] = F0[i]; F1old[i] = F1[i]; B0old[i] = B0[i]; B1old[i] = B1[i]; } B0[0] = B1old[0]; F0[0] = B0[0]*glottalReflectionCoeff + input[ii]; F1[0] = F0old[0]; B1[0] = (B1[1]*(1+kCoeff[0]) + F1[0]*kCoeff[0])*dampingCoeff; for(int i=1;i<nJunctions-1;i++) { B0[i] = B1old[i]; F0[i] = (F1[i-1]*(1-kCoeff[i-1]) - B0[i]*kCoeff[i-1])*dampingCoeff; F1[i] = F0old[i-1]; B1[i] = (B1[i+1]*(1+kCoeff[i]) + F1[i]*kCoeff[i])*dampingCoeff; } B0[nJunctions-1] = 0; F0[nJunctions-1] = F1[nJunctions-2]*(1-kCoeff[nJunctions-1])*dampingCoeff; output[k]=(float)F0[nJunctions-1]; if(ii == inputLen - 1) { ii = 0; } else { ii++; } } } }