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
\vinyl -> 20,
];
- controlNotes = IdentityDictionary[
+ buttonNotes = IdentityDictionary[
1 -> \lpfA,
2 -> \lpfB,
3 -> \but1,
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|
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
}.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