package de.tu.darmstadt.seemoo.ansian.control.threads;
import java.util.concurrent.ArrayBlockingQueue;
import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;
import de.tu.darmstadt.seemoo.ansian.control.events.DataEvent;
import de.tu.darmstadt.seemoo.ansian.control.events.FFTDataEvent;
import de.tu.darmstadt.seemoo.ansian.model.FFT;
import de.tu.darmstadt.seemoo.ansian.model.FFTSample;
import de.tu.darmstadt.seemoo.ansian.model.SamplePacket;
import de.tu.darmstadt.seemoo.ansian.model.preferences.Preferences;
/**
* FFTCalcThread provides the FFT calculator with new samples
*
*
*/
public class FFTCalcThread extends Thread {
@SuppressWarnings("unused")
private static final String LOGTAG = "FftCalcThread";
private FFT fftBlock;
private int oldFFTSize;
private int fftDivider = 1;
private int FFT_QUEUE_SIZE = 5;
private int counter = fftDivider;
boolean stopRequested = false;
private ArrayBlockingQueue<SamplePacket> inputQueue;
private ArrayBlockingQueue<FFTSample> outputQueue;
public FFTCalcThread() {
fftBlock = new FFT(oldFFTSize = Preferences.MISC_PREFERENCE.getFFTSize());
inputQueue = new ArrayBlockingQueue<SamplePacket>(FFT_QUEUE_SIZE);
outputQueue = new ArrayBlockingQueue<FFTSample>(FFT_QUEUE_SIZE);
}
@Override
public void run() {
EventBus.getDefault().register(this);
while (!stopRequested) {
int fFTSize = Preferences.MISC_PREFERENCE.getFFTSize();
if (oldFFTSize != fFTSize) {
fftBlock = new FFT(oldFFTSize = fFTSize);
}
SamplePacket samples = null;
while (inputQueue.isEmpty()) {
try {
sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
float[] mag = new float[fFTSize];
float[] re, im;
samples = inputQueue.poll();
re = samples.getRe().clone();
im = samples.getIm().clone();
// Multiply the samples with a Window function:
fftBlock.applyWindow(re, im);
// Calculate the fft:
fftBlock.fft(re, im);
// Calculate the logarithmic magnitude:
float realPower;
float imagPower;
int size = samples.size();
for (int j = 0; j < size; j++) {
// We have to flip both sides of the fft to draw it centered on
// the
// screen:
int targetIndex = (j + size / 2) % size;
// Calc the magnitude = log( re^2 + im^2 )
// note that we still have to divide re and im by the fft size
realPower = re[j] / fFTSize;
realPower = realPower * realPower;
imagPower = im[j] / fFTSize;
imagPower = imagPower * imagPower;
mag[targetIndex] = (float) (10 * Math.log10(Math.sqrt(realPower + imagPower)));
}
outputQueue.offer(new FFTSample(samples, mag));
EventBus.getDefault().post(new FFTDataEvent(outputQueue.poll()));
}
EventBus.getDefault().unregister(this);
}
@Subscribe
public void onEvent(DataEvent event) {
if (counter % fftDivider == 0)
inputQueue.offer(event.getSample());
counter++;
}
public void stopFFTCalcThread() {
stopRequested = true;
}
}