Add a MIDI-responding piano key pattern that lights up cubes based on notes
authorMark Slee <mcslee@Mark-Slees-MacBook-Pro.local>
Sun, 26 May 2013 22:23:23 +0000 (15:23 -0700)
committerMark Slee <mcslee@Mark-Slees-MacBook-Pro.local>
Sun, 26 May 2013 22:23:23 +0000 (15:23 -0700)
MarkSlee.pde
SugarCubes.pde
_Internals.pde
code/GLucose.jar

index 07c8ce214728ac48ba66e4efe6ea28c8ef6b0cc0..95e8545698c16a0812dcfab133b6917552079188 100644 (file)
@@ -276,3 +276,71 @@ class BoomEffect extends SCEffect {
   }
 }
 
+public class PianoKeyPattern extends SCPattern {
+  
+  final LinearEnvelope[] cubeBrt;
+  final SinLFO base[];  
+  final BasicParameter attack = new BasicParameter("ATK", 0.1);
+  final BasicParameter release = new BasicParameter("REL", 0.5);
+  final BasicParameter level = new BasicParameter("AMB", 0.6);
+  
+  PianoKeyPattern(GLucose glucose) {
+    super(glucose);
+    
+    for (MidiInputDevice input : RWMidi.getInputDevices()) {
+      input.createInput(this);
+    }
+    
+    addParameter(attack);
+    addParameter(release);
+    addParameter(level);
+    cubeBrt = new LinearEnvelope[Cube.list.size() / 4];
+    for (int i = 0; i < cubeBrt.length; ++i) {
+      addModulator(cubeBrt[i] = new LinearEnvelope(0, 0, 100));
+    }
+    base = new SinLFO[Cube.list.size() / 12];
+    for (int i = 0; i < base.length; ++i) {
+      addModulator(base[i] = new SinLFO(0, 1, 7000 + 1000*i)).trigger();
+    }
+  }
+  
+  private float getAttackTime() {
+    return 15 + attack.getValuef()*attack.getValuef() * 2000;
+  }
+  
+  private float getReleaseTime() {
+    return 15 + release.getValuef() * 3000;
+  }
+  
+  private LinearEnvelope getEnvelope(int index) {
+    return cubeBrt[index % cubeBrt.length];
+  }
+  
+  private SinLFO getBase(int index) {
+    return base[index % base.length];
+  }
+    
+  public void noteOnReceived(Note note) {
+    LinearEnvelope env = getEnvelope(note.getPitch());
+    env.setEndVal(min(1, env.getValuef() + (note.getVelocity() / 127.)), getAttackTime()).start();
+  }
+  
+  public void noteOffReceived(Note note) {
+    getEnvelope(note.getPitch()).setEndVal(0, getReleaseTime()).start();
+  }
+  
+  public void run(int deltaMs) {
+    int i = 0;
+    float huef = lx.getBaseHuef();
+    float levelf = level.getValuef();
+    for (Cube c : Cube.list) {
+      float v = max(getBase(i).getValuef() * levelf/4., getEnvelope(i++).getValuef());
+      setColor(c, color(
+        (huef + 20*v + abs(c.fy-128.)*.3 + c.fz) % 360,
+        min(100, 120*v),
+        100*v
+      ));
+    }
+  }
+}
+
index 3a5354c95d266cc58118ed952ae63de99f56156d..9ec4f079d86feb8b00cf919904004d8265bd3604 100644 (file)
@@ -28,6 +28,7 @@ LXPattern[] patterns(GLucose glucose) {
     new SpaceTime(glucose),
     new Swarm(glucose),
     new CubeEQ(glucose),
+    new PianoKeyPattern(glucose),
     
     // Basic test patterns for reference, not art
 //    new TestHuePattern(glucose),
index 05336ec1016d7114671662b9622f22abef9f5fc4..a45805287f6eb8d042b62f02f3c1302c5c5b4ea4 100644 (file)
@@ -20,6 +20,7 @@ import ddf.minim.*;
 import ddf.minim.analysis.*;
 import processing.opengl.*;
 import java.lang.reflect.*;
+import rwmidi.*;
 
 final int VIEWPORT_WIDTH = 900;
 final int VIEWPORT_HEIGHT = 700;
index cc16b16bb425ef92031daf938c1062be05f2eb26..74084b63edd715547e06d82c6584b0cb25eb3dc1 100644 (file)
Binary files a/code/GLucose.jar and b/code/GLucose.jar differ