package com.elmz.drift.openbci;
public class StreamReader {
private final int WINDOW_SIZE = 100;
private final int DIF_SIZE = 10;
private final double THRESHOLD = 6.0;
private final int DUPE_SIZE = 10;
private final double SAMPLE_RATE = 250.0;
private double[] windowD = new double[WINDOW_SIZE+DIF_SIZE]; //differential
private double[] windowR = new double[WINDOW_SIZE+DIF_SIZE]; //real
private double[] dupes = new double[DUPE_SIZE];
private int index = 0;
private int indexTotal = 0;
private int dupeIndex = 0;
private int mode = 0;
private int leadingEdge = 0;
private int fallingEdge = 0;
private int lastDown = -1;
private int frameCount = 0;
private boolean waitOne = true;
private BrainStateCallback mCallback;
public StreamReader(BrainStateCallback bsc) {
mCallback = bsc;
}
public void addFrame(double frame) {
windowR[index] = frame;
if (indexTotal >= 10) {
windowD[index] = (frame-windowR[mod(index-DIF_SIZE, WINDOW_SIZE+DIF_SIZE)])/DIF_SIZE;
} else {
windowD[index] = 0;
}
index++;
index = index%(WINDOW_SIZE+DIF_SIZE);
indexTotal++;
if (frameCount++ > 50 && !waitOne) {
scan();
frameCount = 0;
}
if (waitOne) {
waitOne = false;
}
}
public void scan() {
for (int i = 0; i < WINDOW_SIZE-1; i++) {
double actual = windowD[(index+DIF_SIZE+i)%(WINDOW_SIZE+DIF_SIZE)];
double prevus = windowD[(index+DIF_SIZE+i-1)%(WINDOW_SIZE+DIF_SIZE)];
int absolt = indexTotal-WINDOW_SIZE+i;
if (mode == 0) {
if (prevus < THRESHOLD && actual >= THRESHOLD) {
mode = 1;
leadingEdge = absolt;
} else if (prevus > -THRESHOLD && actual <= -THRESHOLD) {
mode = -1;
fallingEdge = absolt;
}
} else if (mode == 1) {
if (actual <= THRESHOLD) {
double val = ((absolt-leadingEdge)/2.0+leadingEdge);
if (!dupeContains(val)) {
//System.out.println("BLINK ENDED AT FRAME: "+val+" WITH BOUNDRIES "+leadingEdge+" & "+absolt);
dupes[dupeIndex%DUPE_SIZE] = val;
dupeIndex++;
if (lastDown > 0) {
mCallback.blinkEnd(Math.abs((absolt-lastDown)/SAMPLE_RATE));
System.out.println("BLINK OCCURRED FOR "+(absolt-lastDown)/SAMPLE_RATE+" SECONDS");
lastDown = -1;
}
mode = 0;
leadingEdge = 0;
fallingEdge = 0;
}
}
} else if (mode == -1) {
if (actual >= -THRESHOLD) {
double val = ((absolt-fallingEdge)/2.0+fallingEdge);
if (!dupeContains(val)) {
//System.out.println("BLINK BEGAN AT FRAME: "+val+" WITH BOUNDRIES "+fallingEdge+" & "+absolt);
dupes[dupeIndex%DUPE_SIZE] = val;
dupeIndex++;
if (lastDown < 0) {
lastDown = absolt;
mCallback.blinkStart();
}
mode = 0;
leadingEdge = 0;
fallingEdge = 0;
}
}
}
}
}
public double getFrame(int in) {
if (in < 0 || in >= WINDOW_SIZE) {
return -1.0;
} else {
return windowD[mod((index+in-1),(WINDOW_SIZE+DIF_SIZE))];
}
}
private boolean dupeContains(double val) {
for (int i = 0; i < DUPE_SIZE; i++) {
if (((int)dupes[i]) == ((int)val)) {
return true;
}
}
return false;
}
private int mod(int a, int b) {
if (a >= 0) {
return a%b;
} else {
return a%b+b;
}
}
}