package de.tu.darmstadt.seemoo.ansian.model;
import java.util.Arrays;
import de.tu.darmstadt.seemoo.ansian.control.StateHandler;
import de.tu.darmstadt.seemoo.ansian.control.threads.SourceControlThread;
import de.tu.darmstadt.seemoo.ansian.model.preferences.Preferences;
public class GuiFFTDataAdapter {
@SuppressWarnings("unused")
private static final String LOGTAG = "GuiFFTDataAdapter";
private float[] tempMagnitudes;
private int tempBandwith;
private int targetValues;
private long guiCenterFrequency;
private long guiBandwidth;
private FFTDrawData fftDrawData;
private FFTSample sample;
private float ratio;
private long lowerSampleFrequency;
private long upperGuiFrequency;
private long lowerGuiFrequency;
private long upperSampleFrequency;
public GuiFFTDataAdapter(FFTSample sample, int pixel) {
this.sample = sample;
ratio = 0;
init(pixel);
}
public void init(int values) {
targetValues = values;
guiBandwidth = Preferences.GUI_PREFERENCE.getBandwidth();
guiCenterFrequency = Preferences.GUI_PREFERENCE.getFrequency();
tempBandwith = getFFTBandwidth();
tempMagnitudes = sample.getMagnitudes(tempBandwith);
lowerGuiFrequency = guiCenterFrequency - guiBandwidth / 2;
upperGuiFrequency = guiCenterFrequency + guiBandwidth / 2;
lowerSampleFrequency = sample.getCenterFrequency() - tempBandwith / 2;
upperSampleFrequency = sample.getCenterFrequency() + tempBandwith / 2;
}
private void scaleValues() {
if (tempMagnitudes != null) {
long pixels = targetValues;
// if (StateHandler.isScanning()) {
pixels = (long) (pixels * ((float) tempBandwith / guiBandwidth) * (1 - ratio));
// }
float[] result = new float[(int) pixels];
// Log.d(LOGTAG, "1 scaleResult" + Arrays.toString(result));
float scale = (float) tempMagnitudes.length / pixels;
if (scale != 1) {
float max = 0;
for (int i = 0; i < pixels; i++) {
result[i] = calcAverage(tempMagnitudes, Math.round(max), Math.round(max += scale));
}
tempMagnitudes = result;
}
}
}
private float calcAverage(float[] values, int from, int till) {
float avg = 0;
if (from >= values.length || till >= values.length) {
return Float.NaN;
}
if (from == till) {
return values[from];
}
for (int pos = from; pos < till; pos++) {
avg += values[pos];
}
return avg / (till - from);
}
private void cutValues() {
float lowerRatio = 0;
float upperRatio = 0;
if (lowerSampleFrequency < lowerGuiFrequency) {
lowerRatio = (lowerGuiFrequency - lowerSampleFrequency) / (float) tempBandwith;
}
if (upperSampleFrequency > upperGuiFrequency) {
upperRatio = (upperSampleFrequency - upperGuiFrequency) / (float) tempBandwith;
}
if (lowerRatio != 0 || upperRatio != 0) {
ratio = lowerRatio + upperRatio;
if (ratio < 1 && tempMagnitudes != null) {
int length = tempMagnitudes.length;
tempMagnitudes = Arrays.copyOfRange(tempMagnitudes, (int) (lowerRatio * length),
(int) ((1 - upperRatio) * length));
} else {
tempMagnitudes = null;
}
}
}
public FFTDrawData getFftDrawData(int pixel) {
if (fftDrawData != null && pixel == targetValues && guiBandwidth == Preferences.GUI_PREFERENCE.getBandwidth()
&& guiCenterFrequency == Preferences.GUI_PREFERENCE.getFrequency()) {
return fftDrawData;
} else {
init(pixel);
// Log.d(LOGTAG, "1 precut" + Arrays.toString(tempMagnitudes));
cutValues();
// Log.d(LOGTAG, "2 postcut" + Arrays.toString(tempMagnitudes));
// Scaling
scaleValues();
// Log.d(LOGTAG, "3 postScale" + Arrays.toString(tempMagnitudes));
fftDrawData = new FFTDrawData(tempMagnitudes, calcStartIndex());
return fftDrawData;
}
}
private int getFFTBandwidth() {
if (StateHandler.isScanning()) {
return (int) (sample.getBandwidth() * SourceControlThread.getScanDataFactor());
} else
return sample.getBandwidth();
};
private int calcStartIndex() {
float firstTemp = (float) lowerSampleFrequency - lowerGuiFrequency;
float temp = (firstTemp / guiBandwidth);
if (temp != 0) {
// temp=(int) (temp+(float)tempBandwith/guiBandwidth);
temp = Math.max(0, temp * targetValues);
}
return Math.round(temp);
}
}