@@ -0,0 +1,1392 @@
+package jeranvier.math.dsp;%0A%0Aimport jeranvier.math.linearAlgebra.Vector;%0Aimport jeranvier.math.util.Complex;%0A%0Apublic class ButterworthFilter %7B%0A%09%0A%09private final double frequencyCut;%0A%09private final double sampleRate;%0A%09private final int filterOrder;%0A%09private final double DCGain;%0A%0A%09public ButterworthFilter(double sampleRate, double frequencyCut, int filterOrder, double DCGain)%7B%0A%09%09this.frequencyCut = frequencyCut;%0A%09%09this.sampleRate = sampleRate;%0A%09%09this.filterOrder = filterOrder;%0A%09%09this.DCGain = DCGain;%09%0A%09%7D%0A%09%0A%09public ButterworthFilter(double sampleRate, double frequencyCut, int filterOrder)%7B%0A%09%09%09this(frequencyCut, sampleRate, filterOrder, 1.0);%0A%09%7D%0A%09%0A%09%0A%09%0A%09public Vector filter(Vector signal)%7B%0A%09%09Vector fft = Fourier.dft(signal);%0A%09%09int n = signal.size();%0A%09%09int numBins = n / 2;  // Half the length of the FFT by symmetry%0A%09%09double binWidth = this.sampleRate / n; // Hz%0A%09%09Vector.Builder filteredBuilder = new Vector.Builder(n);%0A%09%09filteredBuilder.set(1, fft.get(1));%0A%09%09filteredBuilder.set(n, fft.get(n));%0A%09%09%0A%09%09for(int i = 2; i %3C n/2+1; i++)%7B%0A%09%09%09double binFreq = binWidth * i;%0A%09%09%09double gain = Math.abs(DCGain)/(Math.sqrt( ( 1 + Math.pow( binFreq / frequencyCut, 2.0 * filterOrder))));%0A%09%09%09filteredBuilder.set(i, fft.get(i).multiplyBy(gain));%0A%09%09%09filteredBuilder.set(n-i+1, fft.get(n-i+1).multiplyBy(gain));%0A%09%09%7D%0A%09%09%0A%09%09Vector filtered = filteredBuilder.build();%0A%0A%09%09return Fourier.ift(filtered);%0A%09%7D%0A%7D%0A%0A

Add butterworth low path filter. Todo: create hight path and band path filters as well.