Improve mix101 handling, output speed and delta of wheel and duration of wheeling
authorEugene Petkevich <nasedil.genio.code@gmail.com>
Tue, 31 May 2022 17:02:15 +0000 (20:02 +0300)
committerEugene Petkevich <nasedil.genio.code@gmail.com>
Tue, 31 May 2022 17:02:15 +0000 (20:02 +0300)
extensions/classes/midihandler.sc
extensions/classes/midimix.sc
Хэзифу/push-control.scd

index 817c333..0c7944c 100644 (file)
@@ -1,7 +1,7 @@
 MidiHandler {
   var <name, <midiNames;
+  var <>reveal = true;
   var <midiout, <idin;
-  var <>reveal = false;
 
   noCallback {|handlerName...args|
     if (reveal) {
@@ -20,4 +20,33 @@ MidiHandler {
     midiout = MIDIOut.newByName(dest.device, dest.name).latency_(0);
     idin = MIDIClient.sources.detect{|i| i.device == midiNames[0]}.uid;
   }
-}
\ No newline at end of file
+}
+
+// Test incoming midi messages
+/*
+
+(
+MIDIdef.cc(\testcc, {|...args|
+(["cc"] ++ args).postln;
+});
+MIDIdef.noteOn(\testnoteon, {|...args|
+(["note on"] ++ args).postln;
+});
+MIDIdef.noteOff(\testnoteoff, {|...args|
+(["note off"] ++ args).postln;
+});
+MIDIdef.touch(\testtouch, {|...args|
+(["touch"] ++ args).postln;
+});
+MIDIdef.polytouch(\testpolytouch, {|...args|
+(["polytouch"] ++ args).postln;
+});
+MIDIdef.bend(\testbend, {|...args|
+(["bend"] ++ args).postln;
+});
+MIDIdef.sysex(\testsysex, {|...args|
+(["sysex"] ++ args).postln;
+});
+)
+
+*/
\ No newline at end of file
index fbb05bd..a64373b 100644 (file)
@@ -1,15 +1,17 @@
 MidiMix101 : MidiHandler {
   classvar ledValues, ledControls;
-  classvar controlNotes;
+  classvar buttonNotes, modeNotes, rangeControls, biRangeControls, rotaryControls, wheelControls, wheelNotes;
+  const wheelStep = 0.013333333333333; // 1/75
   var <channel = 5;
   // channel selector
   var <>chanrot;
   // modes
   var <>sampler, <>loop, <>fx, <>vinyl;
-  // wheel rotation
-  var <>jogrot, <>scratch;
+  // wheel rotation and start/stop
+  var <>jogrot, <>scratch, <>wheel;
+  var <wheelStartTime, <wheelStopTime, <wheelLastTime;
   // buttons
-  var <>lpfA, <>lpfB, <>but1, <>but2, <>select, <>sync, <>play, <>cue, <>deck, <>rotbut1, <>rotbut2, <>rotbutload, <>jogact;
+  var <>lpfA, <>lpfB, <>but1, <>but2, <>select, <>sync, <>play, <>cue, <>deck, <>rotbut1, <>rotbut2, <>rotbutload;
   // knobs
   var <>again, <>bgain, <>ahi, <>amid, <>alow, <>bhi, <>bmid, <>blow;
   // faders
@@ -41,7 +43,7 @@ MidiMix101 : MidiHandler {
       \vinyl -> 20,
     ];
 
-    controlNotes = IdentityDictionary[
+    buttonNotes = IdentityDictionary[
       1 -> \lpfA,
       2 -> \lpfB,
       3 -> \but1,
@@ -54,15 +56,55 @@ MidiMix101 : MidiHandler {
       11 -> \rotbut1,
       12 -> \rotbutload,
       13 -> \rotbut2,
-      21 -> \jogact,
+    ];
+
+    modeNotes = IdentityDictionary[
+      17 -> \sampler,
+      18 -> \loop,
+      19 -> \fx,
+      20 -> \vinyl,
+    ];
+
+    rangeControls = IdentityDictionary[
+      33 -> \afade,
+      34 -> \bfade,
+      36 -> \again,
+      37 -> \bgain,
+    ];
+
+    biRangeControls = IdentityDictionary[
+      35 -> \crossfade,
+      38 -> \ahi,
+      39 -> \bhi,
+      40 -> \amid,
+      41 -> \bmid,
+      42 -> \alow,
+      43 -> \blow,
+    ];
+
+    rotaryControls = IdentityDictionary[
+      16 -> \rot1,
+      18 -> \rot2,
+      17 -> \rotload,
+    ];
+
+    wheelControls = IdentityDictionary[
+      19 -> \jogrot, // Rotating in sampler/loop/fx mode: -1/1
+      21 -> \scratch, // Rotating in cue/vinyl mode: -1/1; one rotation 150 events
+    ];
+
+    wheelNotes = IdentityDictionary[
+      21 -> \wheel,
     ];
   }
 
-  *new {|name='DJ-Tech MIX-101', midiNames=#["Mix-101", "Mix-101 MIDI 1", "Mix-101 MIDI 1"]|
-    ^super.newCopyArgs(name, midiNames).midiInit.controlInit;
+  *new {|name='DJ-Tech MIX-101', midiNames=#["Mix-101", "Mix-101 MIDI 1", "Mix-101 MIDI 1"], reveal=true|
+    ^super.newCopyArgs(name, midiNames, reveal).midiInit.controlInit;
   }
 
   controlInit {
+    wheelLastTime = thisThread.seconds;
+    wheelStopTime = wheelLastTime;
     // MIDI out channel selector (back of the device)
     // velocity is the channel
     MIDIdef.noteOn(\chanrot++name, {|...args|
@@ -70,117 +112,90 @@ MidiMix101 : MidiHandler {
       chanrot.value(*args);
     }, 14, srcID: idin);
 
-    // == Jog wheel
-    // Rotating in sampler/loop/fx mode: -1/1
-    MIDIdef.cc(\jogrot+name, {|...args|
-      jogrot.value(args[0]-64, *args);
-    }, 19, srcID: idin);
-    // Rotating in cue/vinyl mode: -1/1
-    MIDIdef.cc(\scratch+name, {|...args|
-      scratch.value(args[0]-64, *args);
-    }, 21, srcID: idin);
-
     // == modes
-    // sampler mode activated
-    MIDIdef.noteOn(\sampler++name, {|...args|
-      sampler.value(*args);
-    }, 17, srcID: idin);
-    // loop mode activated
-    MIDIdef.noteOn(\loop++name, {|...args|
-      loop.value(*args);
-    }, 18, srcID: idin);
-    // fx mode activated
-    MIDIdef.noteOn(\fx++name, {|...args|
-      fx.value(*args);
-    }, 19, srcID: idin);
-    // cue/vinyl mode activated
-    MIDIdef.noteOn(\vinyl++name, {|...args|
-      vinyl.value(*args);
-    }, 20, srcID: idin);
-
-    // == faders
-    // channel A fader
-    MIDIdef.cc(\afade+name, {|...args|
-      afade.value(args[0].linlin(0, 127, 0, 1), *args);
-    }, 33, srcID: idin);
-    // channel B fader
-    MIDIdef.cc(\bfade+name, {|...args|
-      bfade.value(args[0].linlin(0, 127, 0, 1), *args);
-    }, 34, srcID: idin);
-    // cross fader
-    MIDIdef.cc(\crossfade+name, {|...args|
-      crossfade.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
-    }, 35, srcID: idin);
-
-    // == knobs
-    // channel A gain
-    MIDIdef.cc(\again+name, {|...args|
-      again.value(args[0].linlin(0, 127, 0, 1), *args);
-    }, 36, srcID: idin);
-    // channel B gain
-    MIDIdef.cc(\bgain+name, {|...args|
-      bgain.value(args[0].linlin(0, 127, 0, 1), *args);
-    }, 37, srcID: idin);
-    // channel A hi
-    MIDIdef.cc(\ahi+name, {|...args|
-      ahi.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
-    }, 38, srcID: idin);
-    // channel B hi
-    MIDIdef.cc(\bhi+name, {|...args|
-      bhi.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
-    }, 39, srcID: idin);
-    // channel A mid
-    MIDIdef.cc(\amid+name, {|...args|
-      amid.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
-    }, 40, srcID: idin);
-    // channel B mid
-    MIDIdef.cc(\bmid+name, {|...args|
-      bmid.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
-    }, 41, srcID: idin);
-    // channel A low
-    MIDIdef.cc(\alow+name, {|...args|
-      alow.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
-    }, 42, srcID: idin);
-    // channel B low
-    MIDIdef.cc(\blow+name, {|...args|
-      blow.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
-    }, 43, srcID: idin);
+    MIDIdef.noteOn((\mode++name).asSymbol, {|...args|
+      var handler, modeName;
+      modeName = modeNotes[args[1]];
+      handler = this.perform(modeName);
+      handler.value(*args);
+    }, modeNotes.keys.asArray, srcID: idin);
+
+    // == faders/knobs with uniform range
+    MIDIdef.cc((\rangeControl++name).asSymbol, {|...args|
+      var handler, controlName;
+      controlName = rangeControls[args[1]];
+      handler = this.perform(controlName);
+      handler.value(args[0].linlin(0, 127, 0, 1), *args);
+    }, rangeControls.keys.asArray, srcID: idin);
+
+    // == faders/knows with dual ranges
+    MIDIdef.cc((\biRangeControl++name).asSymbol, {|...args|
+      var handler, controlName;
+      controlName = biRangeControls[args[1]];
+      handler = this.perform(controlName);
+      handler.value(args[0].bilin(64, 0, 127, 0, -1, 1), *args);
+    }, biRangeControls.keys.asArray, srcID: idin);
 
     // == endless rotators
-    // channel A rotator: -1/1
-    MIDIdef.cc(\rot1+name, {|...args|
-      rot1.value(args[0]-64, *args);
-    }, 16, srcID: idin);
-    // channel B rotator: -1/1
-    MIDIdef.cc(\rot2+name, {|...args|
-      rot2.value(args[0]-64, *args);
-    }, 18, srcID: idin);
-    // load/preview rotator: -1/1
-    MIDIdef.cc(\rotload+name, {|...args|
-      rotload.value(args[0]-64, *args);
-    }, 17, srcID: idin);
+    MIDIdef.cc((\rotaryControl++name).asSymbol, {|...args|
+      var handler, controlName;
+      controlName = rotaryControls[args[1]];
+      handler = this.perform(controlName);
+      handler.value(args[0]-64, *args);
+    }, rotaryControls.keys.asArray, srcID: idin);
+
+    // == wheel
+    MIDIdef.cc((\wheelControl++name).asSymbol, {|...args|
+      var handler, controlName, wheelSpeed, step;
+      controlName = wheelControls[args[1]];
+      handler = this.perform(controlName);
+      step = args[0] - 64;
+      wheelSpeed = wheelStep / (thisThread.seconds - wheelLastTime);
+      wheelLastTime = thisThread.seconds;
+      handler.value(step, wheelSpeed * step, wheelStep * step, *args);
+    }, wheelControls.keys.asArray, srcID: idin);
 
     // == buttons, first arg is true if pressed, false if released
     // button pressed
-    MIDIdef.noteOn(\buttonDown++name, {|...args|
+    MIDIdef.noteOn((\buttonDown++name).asSymbol, {|...args|
       var handler, buttonName;
-      buttonName = controlNotes[args[1]];
+      buttonName = buttonNotes[args[1]];
       handler = this.perform(buttonName);
       handler.value(true, *args);
-    }, controlNotes.keys.asArray, srcID: idin);
+    }, buttonNotes.keys.asArray, srcID: idin);
     // button released
-    MIDIdef.noteOff(\buttonUp++name, {|...args|
+    MIDIdef.noteOff((\buttonUp++name).asSymbol, {|...args|
       var handler, buttonName;
-      buttonName = controlNotes[args[1]];
+      buttonName = buttonNotes[args[1]];
       handler = this.perform(buttonName);
       handler.value(false, *args);
-    }, controlNotes.keys.asArray, srcID: idin);
+    }, buttonNotes.keys.asArray, srcID: idin);
+
+    // == wheel start/stop, first arg is true if pressed, false if released
+    // button pressed
+    MIDIdef.noteOn((\wheelStart++name).asSymbol, {|...args|
+      var handler, buttonName, wheelDuration;
+      buttonName = wheelNotes[args[1]];
+      handler = this.perform(buttonName);
+      wheelStartTime = thisThread.seconds;
+      wheelDuration = wheelStartTime - wheelStopTime;
+      handler.value(true, wheelDuration, *args);
+    }, wheelNotes.keys.asArray, srcID: idin);
+    // button released
+    MIDIdef.noteOff((\wheelStop++name).asSymbol, {|...args|
+      var handler, buttonName, wheelDuration;
+      buttonName = wheelNotes[args[1]];
+      handler = this.perform(buttonName);
+      wheelStopTime = thisThread.seconds;
+      wheelDuration = wheelStopTime - wheelStartTime;
+      handler.value(false, wheelDuration, *args);
+    }, wheelNotes.keys.asArray, srcID: idin);
 
     // initialize handlers with revealing code
     [
       \chanrot, \sampler, \loop, \fx, \vinyl, \jogrot, \scratch,
       \lpfA, \lpfB, \but1, \but2, \select, \sync, \play, \cue, \deck,
-      \rotbut1, \rotbut2, \rotbutload, \jogact,
+      \rotbut1, \rotbut2, \rotbutload, \wheel,
       \again, \bgain, \ahi, \amid, \alow, \bhi, \bmid, \blow,
       \afade, \bfade, \crossfade,
       \rot1, \rot2, \rotload
@@ -217,4 +232,17 @@ MidiMix101 : MidiHandler {
     }.fork();
   }
 
-}
\ No newline at end of file
+}
+
+// Example
+/*
+(
+~m = MidiMix101();
+)
+
+(
+~m.jogrot_{|v, s, d|
+  "Wheel speed is %".format(s).postln;
+};
+)
+*/
\ No newline at end of file
index 1cbe5f7..d499ba3 100644 (file)
 
 //============================================================================= Testing
 
-/* Test incoming MIDI messages from push
-(
-MIDIdef.cc(\testcc, {|...args|
-(["cc"] ++ args).postln;
-});
-MIDIdef.noteOn(\testnoteon, {|...args|
-(["note on"] ++ args).postln;
-});
-MIDIdef.noteOff(\testnoteoff, {|...args|
-(["note off"] ++ args).postln;
-});
-MIDIdef.touch(\testtouch, {|...args|
-(["touch"] ++ args).postln;
-});
-MIDIdef.polytouch(\testpolytouch, {|...args|
-(["polytouch"] ++ args).postln;
-});
-MIDIdef.bend(\testbend, {|...args|
-(["bend"] ++ args).postln;
-});
-MIDIdef.sysex(\testsysex, {|...args|
-(["sysex"] ++ args).postln;
-});
-)
-*/
-
 /*  Test all LED colors via rotaning left rotary control
 ~push = ~pushFactory.value;
 ~col = 0;