package advanced.gestureSound;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.mt4j.components.MTComponent;
import org.mt4j.input.IMTInputEventListener;
import org.mt4j.input.inputData.AbstractCursorInputEvt;
import org.mt4j.input.inputData.InputCursor;
import org.mt4j.input.inputData.MTInputEvent;
import org.mt4j.sceneManagement.AbstractScene;
import processing.core.PApplet;
import processing.core.PGraphics;
import advanced.gestureSound.gestures.GestureEngine;
import advanced.gestureSound.gestures.GestureEngine.ParamMap;
import advanced.gestureSound.gestures.GestureEngine.Zone;
import advanced.gestureSound.input.InputDelegate;
import de.sciss.jcollider.Buffer;
import de.sciss.jcollider.Synth;
public class GestureSound extends MTComponent {
PApplet applet;
GestureEngine engine;
InputDelegate inDelegate;
SC sc;
List<InputCursor> ins;
float lastRight1 = 0f;
float lastRight2 = 0f;
float lastLeft1 = 0f;
float lastLeft2 = 0f;
public static Buffer b;
public GestureSound(PApplet applet, final AbstractScene scene) {
super(applet);
// TODO Auto-generated constructor stub
this.applet = applet;
this.inDelegate = new InputDelegate(applet, scene);
this.engine = new GestureEngine(applet, inDelegate);
this.ins = new ArrayList<InputCursor>();
inDelegate.addInputListener(new IMTInputEventListener() {
//@Override
public boolean processInputEvent(MTInputEvent inEvt){
if(inEvt instanceof AbstractCursorInputEvt){
AbstractCursorInputEvt posEvt = (AbstractCursorInputEvt)inEvt;
final InputCursor m = posEvt.getCursor();
if (posEvt.getId() == AbstractCursorInputEvt.INPUT_ENDED) {
ins.remove(m);
}
else if (posEvt.getId() == AbstractCursorInputEvt.INPUT_DETECTED) {
ins.add(m);
}
}
else {
System.out.println("Input event! Class:"+inEvt.getClass().toString());
}
return false;
}
});
sc = new SC();
sc.setupSupercollider();
setupGestures();
}
public static class CenterPosMap implements ParamMap {
public float pos = 0f;
public float dur = Float.NaN;
public float sensitivity = 0.05f;
public float map(float in) {
//if (dur == Float.NaN)
dur = (float) b.getDuration();
pos += in*sensitivity;
//pos = Math.min(Math.max(0, pos), dur);
pos = pos % dur;
//System.out.println("Pos:"+pos+" In:"+in+" Dur:"+dur);
return pos;
}}
public static class TrigRateMap implements ParamMap {
public static float sensitivity=1.1f;
public float map(float in) {
float val = (1/DurMap.durVal*(in*1.1f+0.5f));
//System.out.println("durVal:"+DurMap.durVal+"velocity:" + in+" TrigRate:"+val);
if (b.getDuration() != Float.NaN) {
//val = Math.min(Math.max(0f, val), (float)b.getDuration());
}
return val;
//return in*4;
}
}
public static class TrigRateMap2 implements ParamMap {
public static float sensitivity=1.1f;
public DurMap2 durMap = new DurMap2();
public float map(float in) {
float durVal = durMap.map(in);
float val = (1/durVal*(in*1.1f+0.5f));
//System.out.println("durVal:"+DurMap.durVal+"velocity:" + in+" TrigRate:"+val);
if (b.getDuration() != Float.NaN) {
//val = Math.min(Math.max(0f, val), (float)b.getDuration());
}
return val;
//return in*4;
}
}
public static class DurMap2 implements ParamMap {
public static float durVal = 0.2f;
public static float sensitivity=0.2f;
public float map(float in) {
//durVal = (float)((in*sensitivity*b.getDuration()/2f)+2f);
durVal = 0.00f + (float)((1/(in*sensitivity)));
if (b.getDuration() != Float.NaN) {
durVal = Math.min(Math.max(0.01f, durVal), (float)b.getDuration());
}
System.out.println("durVal:"+durVal);
return durVal;
}
}
public static class DurMap implements ParamMap {
public static float durVal = 0.2f;
public static float sensitivity=2.7f;
public static float middle = 0.2f;
public float map(float in) {
float pos = in*sensitivity;
//durVal = ((float)b.getDuration());
durVal = (float) Math.pow(sensitivity, pos)*middle;
//durVal = (float)((in*sensitivity*b.getDuration()/2f)+/2f);
if (b.getDuration() != Float.NaN) {
durVal = Math.min(Math.max(0.01f, durVal), (float)b.getDuration());
}
System.out.println("durVal:"+durVal);
return durVal;
}
}
public static class RateMap implements ParamMap {
public float sensitivity = 0.02f;
public static float rateVal = 1.0f;
public float map(float in) {
//normal mode, not in octaveness yet. (linear, not logrithmic)
rateVal = in*in*in*in*in*sensitivity;
//octaveness
rateVal = (float)Math.exp(in);
rateVal = rateVal + 1; //add in offset.
System.out.println("rate:"+rateVal);
return rateVal; }
}
public static class VelocityMap implements ParamMap {
public float sensitivity = 0.16f;
public float map(float in) {return (float) Math.sqrt(in*sensitivity); }
}
void setupGestures() {
try {
File f = new File("data/sounds/MurrayPerahia1.aif");
System.out.println("Loading sample at: "+f.getAbsolutePath());
b = Buffer.read(sc.server,f.getAbsolutePath());
Synth synth1 = new Synth("grannyyy", new String[] {"trigRate", "buffer", "dur"}, new float[] { 10, b.getBufNum(), 0.1f }, sc.grpAll);
engine.addToMap("curvature", synth1, "centerPos",
new CenterPosMap(),
new Zone() { @Override public boolean in(InputCursor in) {return inQuadrant(in,1)||inQuadrant(in,4);}});
engine.addToMap("velocity", synth1, "amp",
new VelocityMap(),
new Zone() { @Override public boolean in(InputCursor in) {return inQuadrant(in,1)||inQuadrant(in,4);}});
engine.addToMap("velocity", synth1, "trigRate",
new TrigRateMap(),
new Zone() { @Override public boolean in(InputCursor in) {return inQuadrant(in,1)||inQuadrant(in,4);}});
engine.addToMap("curvature", synth1, "rate",
new RateMap(),
new Zone() { @Override public boolean in(InputCursor in) {return inQuadrant(in,2)||inQuadrant(in,3);}});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void drawComponent(PGraphics g) {
g.stroke(100);
g.fill(150);
for (InputCursor in : ins) {
if (in.getFirstEvent().getPosX() < this.applet.width/2) { //its on the left half of the screen
lastLeft1 = engine.getCurrentValue("curvature", in)*30;
lastLeft2 = engine.getCurrentValue("velocity", in)*2;
g.fill(255,255,0);
}
else {
lastRight1 = engine.getCurrentValue("curvature", in)*30;
lastRight2 = engine.getCurrentValue("velocity", in)*2;
g.fill(255,0,255);
}
int sizeofpast = in.getEventCount();
double[] x = new double[sizeofpast];
double[] y = new double[sizeofpast];
int c = 0;
for (AbstractCursorInputEvt evt : in.getEvents()) {
//g.rect(evt.getPosX(), evt.getPosY(), 4, 4);
x[c] = evt.getPosX();
y[c] = evt.getPosY();
c += 1;
}
//try 1: cubic spline library
// if (sizeofpast > 2) {
// g.fill(0,0,0);
// CubicSpline s = new CubicSpline(x,y);
// s.setDerivLimits(3,5);
// Arrays.sort(x);
// for (double xx = x[0]; xx < x[x.length-1]; xx++) {
// g.rect((float)xx, (float)s.interpolate(xx), 1, 1);
// }
// }
//try 2: built-in spline library
// if (sizeofpast > 2) {
// g.fill(0,0,0);
//
// for (int count = sizeofpast-1; count >= 3; count-=3) {
// CubicCurve2D.Double s = new CubicCurve2D.Double(x[count],y[count],x[count-1],y[count-1],x[count-2],y[count-2],x[count-3],y[count-3]);
// //
// PathIterator pit = s.getPathIterator(null,0.1);
// double[] coords = new double[6];
// while(!pit.isDone()) {
// int type = pit.currentSegment(coords);
//
// g.rect((float)coords[0], (float)coords[1], 1, 1);
// pit.next();
//
// }
//
// }
// }
//try 3: code from http://www.faculty.idc.ac.il/arik/Java/ex2/index.html
int n=7;
if (sizeofpast > n) {
g.fill(255,255,255);
for (int count = sizeofpast-1; count > n; count-=n) {
Point2D[] s = new Point2D[n+1];
for (int i=0;i<n+1;i++)
s[i] = new Point2D.Double(x[count-i],y[count-i]);
Point2D p1,p0;
p0 = s[0];
for (int i = 1 ; i <= 50 ; i++) {
double t = (double)i/50.0;
//p1 = Geometry.evalBezierRec(ptArray,t,np);
p1 = Geometry.evalBezier(s,t);
g.line((float)p0.getX(), (float)p0.getY(), (float)p1.getX(), (float)p1.getY());
p0 = p1;
}
}
List<AbstractCursorInputEvt> past = in.getEvents();
n=15;
sizeofpast = in.getEvents().size();
if (sizeofpast > n) {
Point2D[] s = new Point2D[n+1];
for (int i=0;i<n+1;i++) {
AbstractCursorInputEvt p = past.get(sizeofpast-i-1);
s[i] = new Point2D.Double(p.getPosX(),p.getPosY());
}
Point2D p2,p1,p0;
p0 = s[0];
p1 = Geometry.evalBezier(s,0.2);
p2 = Geometry.evalBezier(s,0.4);
//System.out.println("P2: "+p2.getX()+","+p2.getY());
g.fill(0,0,255);
g.rect((float)p1.getX(), (float)p1.getY(), 5, 5);
g.fill(0,255,0);
g.rect((float)p2.getX(), (float)p2.getY(), 10, 10);
g.fill(255,0,0);
g.rect((float)p0.getX(), (float)p0.getY(), 5, 5);
g.fill(255,255,255);
g.rect((float)s[s.length-1].getX(), (float)s[s.length-1].getY(), 5, 5);
}
}
}
g.stroke(100);
g.fill(150);
//top left bars
g.rect(30,50,30,lastLeft1);
g.rect(70,50,30,lastLeft2);
//top right bars
g.rect(this.applet.width-60,50,30,lastRight1);
g.rect(this.applet.width-100,50,30,lastRight2);
//middle line
g.line(this.applet.width/2, 0, this.applet.width/2, this.applet.height);
inDelegate.tick();
}
}