Add push control framework wrapped in environment
authorEugene Petkevich <nasedil.genio.code@gmail.com>
Fri, 6 May 2022 14:30:21 +0000 (17:30 +0300)
committerEugene Petkevich <nasedil.genio.code@gmail.com>
Fri, 6 May 2022 14:30:21 +0000 (17:30 +0300)
push-control.scd [new file with mode: 0644]

diff --git a/push-control.scd b/push-control.scd
new file mode 100644 (file)
index 0000000..ec4df39
--- /dev/null
@@ -0,0 +1,191 @@
+// Ableton push handler
+// by Eugene Zuelum
+//
+// see https://github.com/Ableton/push-interface for info about ABI:
+// https://github.com/Ableton/push-interface/blob/master/doc/AbletonPush2MIDIDisplayInterface.asc
+
+(
+~pushFactory = {
+  var push = Environment[
+    \version -> "33.7.2.5",
+    // preprocess relative controls
+    \ppcr -> { |zi ...args|
+      if (args[0] > 64, {
+        args[0] = args[0] - 128;
+      });
+      args;
+    },
+
+    // preprocess absolute controls and notes
+    \ppca -> { |zi ...args|
+      args[0] = args[0].linlin(0, 127, 0, 1);
+      args;
+    },
+
+    // preprocess bend
+    \ppcb -> { |zi ...args|
+      if (args[0] >= 8192, {
+        args[0] = args[0].linlin(8192, 16383, 0, 1);
+      }, {
+        args[0] = args[0].linlin(0, 8192, -1, 0);
+      });
+      args;
+    },
+
+    // preprocess push color
+    \pppc -> {|zi, c=0,l=3,w=false|
+      var color;
+      if (c == 0, {
+        color = l;
+      },{
+        if (l == 0, {
+          color = 0;
+        }, {
+          if (w, {
+            color = c*4;
+          }, {
+            color = c*4 + 4 - l;
+          });
+        });
+      });
+      color;
+    },
+
+    \hcPushTurnN -> Array.newClear(9),
+    \hcPushTouchN -> Array.newClear(9)
+  ];
+
+  push.know = true;
+
+  push.controllerFuncs = [
+    // Rotators
+    MIDIFunc.cc({ |...args|
+      push.hcPushTurnS.valueArray(push.ppcr.valueArray(args));
+
+    }, 14, 0),
+    MIDIFunc.cc({ |...args|
+      push.hcPushTurnL.valueArray(push.ppcr.valueArray(args));
+
+    }, 15, 0),
+    MIDIFunc.cc({ |...args|
+      var col = args[1] - 71;
+      push.hcPushTurnN[col].valueArray(push.ppcr.valueArray(args));
+    },
+    (71..79), 0),
+    MIDIFunc.noteOn({ |...args|
+      push.hcPushTouchS.valueArray(true, args);
+
+    }, 10, 0),
+    MIDIFunc.noteOn({ |...args|
+      push.hcPushTouchL.valueArray(true, args);
+
+    }, 9, 0),
+    MIDIFunc.noteOn({ |...args|
+      //args[1] = args[1] - 71;
+      push.hcPushTouchN[args[1]].valueArray(true, args);
+    },
+    (0..8), 0),
+    MIDIFunc.noteOff({ |...args|
+      push.hcPushTouchS.valueArray(false, args);
+
+    }, 10, 0),
+    MIDIFunc.noteOff({ |...args|
+      push.hcPushTouchL.valueArray(false, args);
+
+    }, 9, 0),
+    MIDIFunc.noteOff({ |...args|
+      args[1] = args[1] - 71;
+      push.hcPushTouchN[args[1]].valueArray(false, args);
+    },
+    (0..8), 0),
+    // Left buttons
+    //... not ready yet
+
+    // Keys
+    MIDIFunc.noteOn({ |...args|
+      var note, row, col;
+      note = args[1] - 36;
+      col = note % 8;
+      row = (note/ 8).asInteger;
+      push.hcPushKeyOn(row, col, *push.ppca(*args));
+    },
+    (36..99), 0),
+
+    MIDIFunc.noteOff({ |...args|
+      var note, row, col;
+      note = args[1] - 36;
+      col = note % 8;
+      row = (note/ 8).asInteger;
+      push.hcPushKeyOff(row, col, *push.ppca(*args));
+    }, (36..99), 0),
+
+    MIDIFunc.polytouch({ |...args|
+      var note, row, col;
+      note = args[1] - 36;
+      col = note % 8;
+      row = (note/ 8).asInteger;
+      push.hcPushKeyPressure(row, col, *push.ppca(*args));
+    }, (36..99), 0),
+  ];
+
+  //============================== Binding hc to synth parameters
+
+  push.bindMul = { |zi, synth, param, divisor=1|
+    { |d|
+      synth.get(param, { |v|
+        var newVal = v*((d)/divisor).midiratio;
+        "%: % = %\n".postf(synth, param, newVal);
+        synth.set(param, newVal);
+      });
+    }
+  };
+
+  push.bindAdd = { |zi, synth, param, divisor=1|
+    { |d|
+      synth.get(param, { |v|
+        var newVal = v+(d/divisor);
+        "%: % = %\n".postf(synth, param, newVal);
+        synth.set(param, newVal);
+      });
+    }
+  };
+
+  push.bindRange = { |zi, synth, param, start, end|
+    { |v|
+      var newVal = v.linlin(0, 1, start, end);
+      "%: % = %\n".postf(synth, param, newVal);
+      synth.set(param, newVal);
+    }
+  };
+
+  //============================== LED control
+  MIDIClient.destinations.do({ |item|
+    if (item.name == "Ableton Push MIDI 2", {
+      push.pushOut = MIDIOut(0, item.uid).latency_(0);
+    });
+  });
+  if (push.pushOut==nil, {"Cannot control push LEDs!"});
+
+
+  push.hcPushPadLed = {|zi, row, col, light=3, color=0, whiten=false, mode=0|
+    if ((col < 0) || (col > 7) || (row < 0) || (row > 7), {}, {
+      zi.pushOut.noteOn(mode, 36+(row*8)+col, zi.pppc(color, light, whiten));
+    });
+  };
+
+  push.hcPushPadLedClear = { |zi|
+    for (0, 7, {|i|
+      for (0, 7, {|j|
+        zi.hcPushPadLed.value(i, j, 0);
+      });
+    });
+  };
+
+  push.freeHC = { |zi|
+    zi.controllerFuncs.do({ |item| item.free; });
+    zi.pushOut.free;
+  };
+
+  push;
+};
+)
\ No newline at end of file