package org.signalml.domain.signal.filter.fft;
import org.apache.commons.math.complex.Complex;
import org.signalml.domain.montage.filter.FFTSampleFilter;
import org.signalml.domain.montage.filter.SampleFilterDefinition;
import org.signalml.domain.signal.filter.SinglechannelSampleFilterEngine;
import org.signalml.domain.signal.samplesource.SampleSource;
import org.signalml.math.fft.FourierTransform;
/**
* This engine can be used to filter very long signals in order to export them to a file.
* It uses the overlap-add to filter the data.
*
* @author Piotr Szachewicz
*/
public class FFTFilterEngineForExport extends SinglechannelSampleFilterEngine {
/**
* The sample filter used to filter the data.
*/
private FFTSampleFilter fftSampleFilter;
/**
* Buffer to store the overlapping part of the previously filtered sequence.
* See {@link http://en.wikipedia.org/wiki/Overlap%E2%80%93add_method#The_algorithm}
* for reference.
*/
private double[] overlapBuffer;
public FFTFilterEngineForExport(SampleSource source, FFTSampleFilter filter) {
super(source);
this.fftSampleFilter = filter;
}
@Override
public void getSamples(double[] target, int signalOffset, int count, int arrayOffset) {
double[] samples = new double[count];
source.getSamples(samples, signalOffset, count, 0);
FourierTransform fourierTransform = new FourierTransform(fftSampleFilter.getWindowType(), fftSampleFilter.getWindowParameter());
Complex[] samplesFFT = fourierTransform.forwardFFT(samples);
FFTSinglechannelSampleFilter.multiplyFFTByFFTSampleFilter(samplesFFT, fftSampleFilter, source.getSamplingFrequency());
double[] filteredSignal = fourierTransform.inverseFFT(samplesFFT);
if (overlapBuffer != null) {
for (int i = 0; i < overlapBuffer.length; i++) {
filteredSignal[i] += overlapBuffer[i];
}
}
System.arraycopy(filteredSignal, 0, target, 0, count);
overlapBuffer = new double[filteredSignal.length - count];
System.arraycopy(filteredSignal, count, overlapBuffer, 0, overlapBuffer.length);
}
@Override
public SampleFilterDefinition getFilterDefinition() {
return fftSampleFilter;
}
}