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 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) {
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);
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);
}
+ 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) {
float b = hsb[2];
sendColors[i] = lx.hsb(360.*hsb[0], 100.*hsb[1], 100.*(b*b*b));
}
+ long gammaNanos = System.nanoTime() - gammaStart;
- // TODO(mcslee): move into GLucose engine
+ 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) {
p.toggle();
}
break;
+ case 'q':
+ if (!midiEngine.isQwertyEnabled()) {
+ diagnosticsOn = !diagnosticsOn;
+ }
+ break;
case 's':
if (!midiEngine.isQwertyEnabled()) {
simulationOn = !simulationOn;
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;