private BasicParameter rotation = new BasicParameter("rotation", 0);
float modelrad = sqrt((model.xMax)*(model.xMax) + (model.yMax)*(model.yMax) + (model.zMax)*(model.zMax));
Pick Sshape;
+ public final PVector P = new PVector();
class Sphery {
float f1xcenter, f1ycenter, f1zcenter, f2xcenter , f2ycenter, f2zcenter; //second three are for an ellipse with two foci
public BasicParameter huespread;
public BasicParameter bouncerate;
public BasicParameter bounceamp;
- public PVector circlecenter;
-
-
public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float vibration_min, float vibration_max, float vperiod)
{
//addModulator(bounceamp); //ybounce.setMagnitude(bouncerate);
addModulator( vibration = new SinLFO(vibration_min , vibration_max, 240000./lx.tempo.bpm())).trigger(); //vibration.modulateDurationBy(vx);
-
+
}
public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float f2xcenter, float f2ycenter, float f2zcenter,
float vibration_min, float vibration_max, float vperiod)
*/
public static class GraphicEQ {
- private final HeronLX lx;
+ private final LX lx;
public final BasicParameter level = new BasicParameter("LVL", 0.5);
public final BasicParameter range = new BasicParameter("RNGE", 0.5);
public final static int DEFAULT_NUM_BANDS = 16;
- public GraphicEQ(HeronLX lx) {
+ public GraphicEQ(LX lx) {
this(lx, DEFAULT_NUM_BANDS);
}
* Note that the number of bands is a suggestion. Due to the FFT implementation
* the actual number may be slightly different.
*/
- public GraphicEQ(HeronLX lx, int num) {
+ public GraphicEQ(LX lx, int num) {
this.lx = lx;
fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
fft.window(FFT.HAMMING);
ObjectMuckerEffect(GLucose glucose) {
super(glucose);
}
- public void doApply(int[] colors){
+ public void apply(int[] colors){
/*for(Strip s: model.strips){
for(int i=0; i<s.points.size(); i++){
int index = s.points.get(i).index;
frames[i] = new int[model.points.size()];
}
}
- public void doApply(int[] colors) {
+ public void apply(int[] colors) {
if(fcount<maxfbuf){
for(int i=0; i<colors.length; i++){
frames[(maxfbuf-1)-fcount][i]=colors[i];
if (abs(p.x - cx) < arm) {
d = min(abs(p.x - cx), abs(p.y - middle));
}
- colors[p.index] = color(
+ colors[p.index] = lx.hsb(
(lx.getBaseHuef() + .2*abs(p.y - model.cy)) % 360,
min(100, sf*dist(abs(p.x - cx), p.y, arm, middle)),
- max(0, 120 - d*falloff));
+ constrain(120 - d*falloff, 0, 100));
}
}
}
}
float posf = position.getValuef();
for (Point p : model.points) {
- colors[p.index] = blendColor(colors[p.index], color(
+ colors[p.index] = blendColor(colors[p.index], lx.hsb(
(lx.getBaseHuef() + .2*abs(p.x - model.cx) + .2*abs(p.y - model.cy)) % 360,
100,
max(0, bright - posf*100 - falloff*abs(p.y - posf*model.yMax))
for (Point p : s.points) {
int wavi = (int) constrain(p.x / model.xMax * wval.length, 0, wval.length-1);
float wavb = max(0, wave.getValuef()*100. - 8.*abs(p.y - wval[wavi]));
- colors[p.index] = color(
+ colors[p.index] = lx.hsb(
(lx.getBaseHuef() + .2*abs(p.x - model.cx) + .2*abs(p.y - model.cy)) % 360,
100,
constrain(wavb + max(0, maxBright - 40.*abs(sparklePos - abs(i - (Cube.POINTS_PER_STRIP-1)/2.))), 0, 100)
float zPos;
BouncyBall(int i) {
- addModulator(xPos).setBasis(random(0, TWO_PI)).start();
+ addModulator(xPos.setBasis(random(0, TWO_PI)).start());
addModulator(yPos = new Accelerator(0, 0, 0));
zPos = lerp(model.zMin, model.zMax, (i+2.) / (NUM_BALLS + 4.));
}
}
class Swarm extends SCPattern {
-
+
SawLFO offset = new SawLFO(0, 1, 1000);
SinLFO rate = new SinLFO(350, 1200, 63000);
SinLFO falloff = new SinLFO(15, 50, 17000);
boom.trigger();
}
- void doApply(int[] colors) {
+ void apply(int[] colors) {
float brightv = 100 * bright.getValuef();
float falloffv = falloffv();
float satv = sat.getValuef() * 100;
onEnable();
}
- public void doApply(int[] colors) {
+ public void apply(int[] colors) {
for (Layer l : layers) {
if (l.boom.isRunning()) {
- l.doApply(colors);
+ l.apply(colors);
}
}
}
addParameter(invert);
}
- public void doApply(int[] colors) {
+ public void apply(int[] colors) {
if (!enabled) {
return;
}
float bMod = level.getValuef();
float sMod = 1 - desat.getValuef();
float hMod = hueShift.getValuef();
- float fSharp = 1/(1.0001-sharp.getValuef());
+ float fSharp = sharp.getValuef();
float fSoft = soft.getValuef();
boolean mon = mono.getValuef() > 0.5;
boolean ivt = invert.getValuef() > 0.5;
hsb[2] = 1 - hsb[2];
}
if (fSharp > 0) {
- hsb[2] = hsb[2] < .5 ? pow(hsb[2],fSharp) : 1-pow(1-hsb[2],fSharp);
+ fSharp = 1/(1-fSharp);
+ if (hsb[2] < .5) {
+ hsb[2] = pow(hsb[2],fSharp);
+ } else {
+ hsb[2] = 1-pow(1-hsb[2],fSharp);
+ }
}
if (fSoft > 0) {
if (hsb[2] > 0.5) {
lastQuant = 0;
}
- public void doApply(int[] colors) {
+ public void apply(int[] colors) {
float fQuant = amount.getValuef();
if (fQuant > 0) {
float tRamp = (lx.tempo.rampf() % (1./pow(2,floor((1-fQuant) * 4))));
class BlurEffect extends SCEffect {
- final LXParameter amount = new BasicParameter("AMT", 0);
+ final BasicParameter amount = new BasicParameter("AMT", 0);
final int[] frame;
final LinearEnvelope env = new LinearEnvelope(0, 1, 100);
env.setRangeFromHereTo(0, 1000).start();
}
- public void doApply(int[] colors) {
+ public void apply(int[] colors) {
float amt = env.getValuef() * amount.getValuef();
if (amt > 0) {
amt = (1 - amt);
* //\\ //\\ //\\ //\\
* ///\\\ ///\\\ ///\\\ ///\\\
* \\\/// \\\/// \\\/// \\\///
- * \\// \\// \\// \\//
+ * \\// \\// \\// \\//H
*
* EXPERTS ONLY!! EXPERTS ONLY!!
*
// Core engine variables
GLucose glucose;
-HeronLX lx;
+LX lx;
LXPattern[] patterns;
Effects effects;
MappingTool mappingTool;
boolean debugMode = false;
DebugUI debugUI;
boolean uiOn = true;
+boolean simulationOn = true;
+boolean diagnosticsOn = false;
LXPattern restoreToPattern = null;
PImage logo;
float[] hsb = new float[3];
* Core render loop and drawing functionality.
*/
void draw() {
+ long drawStart = System.nanoTime();
+
// Draws the simulation and the 2D UI overlay
background(40);
debugUI.maskColors(sendColors);
}
- camera(
+ long simulationStart = System.nanoTime();
+ if (simulationOn) {
+ drawSimulation(simulationColors);
+ }
+ long simulationNanos = System.nanoTime() - simulationStart;
+
+ // 2D Overlay UI
+ long uiStart = System.nanoTime();
+ drawUI();
+ long uiNanos = System.nanoTime() - uiStart;
+
+ long gammaStart = System.nanoTime();
+ // Gamma correction here. Apply a cubic to the brightness
+ // for better representation of dynamic range
+ for (int i = 0; i < sendColors.length; ++i) {
+ lx.RGBtoHSB(sendColors[i], hsb);
+ float b = hsb[2];
+ sendColors[i] = lx.hsb(360.*hsb[0], 100.*hsb[1], 100.*(b*b*b));
+ }
+ long gammaNanos = System.nanoTime() - gammaStart;
+
+ long sendStart = System.nanoTime();
+ for (PandaDriver p : pandaBoards) {
+ p.send(sendColors);
+ }
+ long sendNanos = System.nanoTime() - sendStart;
+
+ long drawNanos = System.nanoTime() - drawStart;
+
+ if (diagnosticsOn) {
+ drawDiagnostics(drawNanos, simulationNanos, uiNanos, gammaNanos, sendNanos);
+ }
+}
+
+void drawDiagnostics(long drawNanos, long simulationNanos, long uiNanos, long gammaNanos, long sendNanos) {
+ float ws = 4 / 1000000.;
+ int thirtyfps = 1000000000 / 30;
+ int sixtyfps = 1000000000 / 60;
+ int x = width - 138;
+ int y = height - 14;
+ int h = 10;
+ noFill();
+ stroke(#999999);
+ rect(x, y, thirtyfps * ws, h);
+ noStroke();
+ int xp = x;
+ float hv = 0;
+ for (long val : new long[] {lx.timer.drawNanos, simulationNanos, uiNanos, gammaNanos, sendNanos }) {
+ fill(lx.hsb(hv % 360, 100, 80));
+ rect(xp, y, val * ws, h-1);
+ hv += 140;
+ xp += val * ws;
+ }
+ noFill();
+ stroke(#333333);
+ line(x+sixtyfps*ws, y+1, x+sixtyfps*ws, y+h-1);
+
+ y = y - 14;
+ xp = x;
+ float tw = thirtyfps * ws;
+ noFill();
+ stroke(#999999);
+ rect(x, y, tw, h);
+ h = 5;
+ noStroke();
+ for (long val : new long[] {
+ lx.engine.timer.deckNanos,
+ lx.engine.timer.copyNanos,
+ lx.engine.timer.fxNanos}) {
+ float amt = val / (float) lx.timer.drawNanos;
+ fill(lx.hsb(hv % 360, 100, 80));
+ rect(xp, y, amt * tw, h-1);
+ hv += 140;
+ xp += amt * tw;
+ }
+
+ xp = x;
+ y += h;
+ hv = 120;
+ for (long val : new long[] {
+ lx.engine.getDeck(0).timer.runNanos,
+ lx.engine.getDeck(1).timer.runNanos,
+ lx.engine.getDeck(1).getFaderTransition().timer.blendNanos}) {
+ float amt = val / (float) lx.timer.drawNanos;
+ fill(lx.hsb(hv % 360, 100, 80));
+ rect(xp, y, amt * tw, h-1);
+ hv += 140;
+ xp += amt * tw;
+ }
+}
+
+void drawSimulation(color[] simulationColors) {
+ camera(
eyeX, eyeY, eyeZ,
midX, midY, midZ,
0, -1, 0
vertex(p.x, p.y, p.z);
}
endShape();
-
- // 2D Overlay UI
- drawUI();
-
- // Gamma correction here. Apply a cubic to the brightness
- // for better representation of dynamic range
- for (int i = 0; i < sendColors.length; ++i) {
- lx.RGBtoHSB(sendColors[i], hsb);
- float b = hsb[2];
- sendColors[i] = lx.hsb(360.*hsb[0], 100.*hsb[1], 100.*(b*b*b));
- }
-
- // TODO(mcslee): move into GLucose engine
- for (PandaDriver p : pandaBoards) {
- p.send(sendColors);
- }
}
void drawBassBox(BassBox b, boolean hasSub) {
p.toggle();
}
break;
+ case 'q':
+ if (!midiEngine.isQwertyEnabled()) {
+ diagnosticsOn = !diagnosticsOn;
+ }
+ break;
+ case 's':
+ if (!midiEngine.isQwertyEnabled()) {
+ simulationOn = !simulationOn;
+ }
+ break;
case 'u':
if (!midiEngine.isQwertyEnabled()) {
uiOn = !uiOn;
getTargetPattern().noteOff(note);
}
}
+
+ protected void setNormalized(LXParameter parameter, float value) {
+ if (parameter != null) {
+ if (parameter instanceof BasicParameter) {
+ ((BasicParameter)parameter).setNormalized(value);
+ } else {
+ parameter.setValue(value);
+ }
+ }
+ }
// Subclasses may implement these to map top-level functionality
protected boolean handleProgramChange(ProgramChange pc) { return false; }
case 7:
switch (channel) {
case 0:
- uiSpeed.speed.setValue(0.5 - value*0.5);
+ uiSpeed.speed.setNormalized(0.5 - value*0.5);
return true;
case 1:
- effects.colorFucker.desat.setValue(value);
+ effects.colorFucker.desat.setNormalized(value);
return true;
case 2:
- effects.colorFucker.sharp.setValue(value);
+ effects.colorFucker.desat.setNormalized(value);
return true;
case 3:
- effects.blur.amount.setValue(value);
+ effects.blur.amount.setNormalized(value);
return true;
case 4:
- effects.quantize.amount.setValue(value);
+ effects.quantize.amount.setNormalized(value);
return true;
}
break;
// Master bright
case 14:
- effects.colorFucker.level.setValue(value);
+ effects.colorFucker.level.setNormalized(value);
return true;
// Crossfader
case 15:
- lx.engine.getDeck(GLucose.RIGHT_DECK).getFader().setValue(value);
+ lx.engine.getDeck(GLucose.RIGHT_DECK).getFader().setNormalized(value);
return true;
// Cue level
cv = cv - 64;
}
val += (cv - 64) / 500.;
- effects.colorFucker.hueShift.setValue((val+1) % 1);
+ effects.colorFucker.hueShift.setNormalized((val+1) % 1);
return true;
}
if (parameterIndex >= 0) {
List<LXParameter> parameters = getTargetPattern().getParameters();
if (parameterIndex < parameters.size()) {
- parameters.get(parameterIndex).setValue(value);
+ setNormalized(parameters.get(parameterIndex), value);
return true;
}
}
int effectIndex = number - 20;
List<LXParameter> parameters = glucose.getSelectedEffect().getParameters();
if (effectIndex < parameters.size()) {
- parameters.get(effectIndex).setValue(value);
+ setNormalized(parameters.get(effectIndex), value);
return true;
}
}
case 49: // SOLO/CUE
switch (nChan) {
case 4:
- effects.colorFucker.mono.setValue(1);
+ effects.colorFucker.mono.setNormalized(1);
return true;
case 5:
- effects.colorFucker.invert.setValue(1);
+ effects.colorFucker.invert.setNormalized(1);
return true;
case 6:
lx.cycleBaseHue(60000);
case 49: // SOLO/CUE
switch (nChan) {
case 4:
- effects.colorFucker.mono.setValue(0);
+ effects.colorFucker.mono.setNormalized(0);
return true;
case 5:
- effects.colorFucker.invert.setValue(0);
+ effects.colorFucker.invert.setNormalized(0);
return true;
case 6:
lx.setBaseHue(lx.getBaseHue());
int parameterIndex = number - 16;
List<LXParameter> parameters = midiEngine.getFocusedPattern().getParameters();
if (parameterIndex < parameters.size()) {
- parameters.get(parameterIndex).setValue(cc.getValue() / 127.);
+ setNormalized(parameters.get(parameterIndex), cc.getValue() / 127.);
return true;
}
}
case 75:
float val = effects.colorFucker.hueShift.getValuef();
val += (cc.getValue() - 64) / 256.;
- effects.colorFucker.hueShift.setValue((val+1) % 1);
+ effects.colorFucker.hueShift.setNormalized((val+1) % 1);
break;
}
if (parameterIndex >= 0) {
LXParameter p = parameters.get(parameterIndex);
float curVal = p.getValuef();
curVal += (cc.getValue() - 64) / 127.;
- p.setValue(constrain(curVal, 0, 1));
+ setNormalized(p, constrain(curVal, 0, 1));
}
}
return false;
redraw();
}
+ protected float getNormalized() {
+ if (parameter != null) {
+ if (parameter instanceof BasicParameter) {
+ return ((BasicParameter)parameter).getNormalizedf();
+ }
+ return parameter.getValuef();
+ }
+ return 0;
+ }
+
+ protected UIParameterControl setNormalized(float value) {
+ if (parameter != null) {
+ if (parameter instanceof BasicParameter) {
+ ((BasicParameter)parameter).setNormalized(value);
+ } else {
+ parameter.setValue(value);
+ }
+ }
+ return this;
+ }
+
public UIParameterControl setParameter(LXParameter parameter) {
if (this.parameter != null) {
if (this.parameter instanceof LXListenableParameter) {
private int knobSize = 28;
private final float knobIndent = .4;
private final int knobLabelHeight = 14;
+ private boolean showValue = false;
public UIParameterKnob(float x, float y) {
this(x, y, 0, 0);
}
protected void onDraw(PGraphics pg) {
- float knobValue = (parameter != null) ? parameter.getValuef() : 0;
+ float knobValue = getNormalized();
pg.ellipseMode(CENTER);
pg.noStroke();
pg.fill(#333333);
pg.ellipse(knobSize/2, knobSize/2, knobSize/2, knobSize/2);
- String knobLabel = (parameter != null) ? parameter.getLabel() : null;
+ String knobLabel;
+ if (showValue) {
+ knobLabel = (parameter != null) ? ("" + parameter.getValue()) : null;
+ } else {
+ knobLabel = (parameter != null) ? parameter.getLabel() : null;
+ }
if (knobLabel == null) {
knobLabel = "-";
} else if (knobLabel.length() > 4) {
} else {
lastMousePress = now;
}
+ showValue = true;
+ redraw();
+ }
+
+ public void onMouseReleased(float mx, float my) {
+ showValue = false;
+ redraw();
}
public void onMouseDragged(float mx, float my, float dx, float dy) {
- if (parameter != null) {
- float value = constrain(parameter.getValuef() - dy / 100., 0, 1);
- parameter.setValue(value);
- }
+ float value = constrain(getNormalized() - dy / 100., 0, 1);
+ setNormalized(value);
}
}
private float doubleClickX = 0;
protected void onMousePressed(float mx, float my) {
long now = millis();
- float handleLeft = 4 + parameter.getValuef() * (w-8-handleWidth);
+ float handleLeft = 4 + getNormalized() * (w-8-handleWidth);
if (mx >= handleLeft && mx < handleLeft + handleWidth) {
editing = true;
} else {
if ((now - lastClick) < DOUBLE_CLICK_THRESHOLD && abs(mx - doubleClickX) < 3) {
- parameter.setValue(doubleClickMode);
+ setNormalized(doubleClickMode);
}
doubleClickX = mx;
if (mx < w*.25) {
protected void onMouseDragged(float mx, float my, float dx, float dy) {
if (editing) {
- parameter.setValue(constrain((mx - handleWidth/2. - 4) / (w-8-handleWidth), 0, 1));
+ setNormalized(constrain((mx - handleWidth/2. - 4) / (w-8-handleWidth), 0, 1));
}
}
}