From a1bcb170b44a10145fa7acfcda6fa2243abb2e18 Mon Sep 17 00:00:00 2001 From: Eugene Petkevich Date: Tue, 31 May 2022 20:02:15 +0300 Subject: [PATCH] Improve mix101 handling, output speed and delta of wheel and duration of wheeling --- extensions/classes/midihandler.sc | 33 ++- extensions/classes/midimix.sc | 232 ++++++++++-------- .../push-control.scd" | 26 -- 3 files changed, 161 insertions(+), 130 deletions(-) diff --git a/extensions/classes/midihandler.sc b/extensions/classes/midihandler.sc index 817c333..0c7944c 100644 --- a/extensions/classes/midihandler.sc +++ b/extensions/classes/midihandler.sc @@ -1,7 +1,7 @@ MidiHandler { var reveal = true; 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 diff --git a/extensions/classes/midimix.sc b/extensions/classes/midimix.sc index fbb05bd..a64373b 100644 --- a/extensions/classes/midimix.sc +++ b/extensions/classes/midimix.sc @@ -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 chanrot; // modes var <>sampler, <>loop, <>fx, <>vinyl; - // wheel rotation - var <>jogrot, <>scratch; + // wheel rotation and start/stop + var <>jogrot, <>scratch, <>wheel; + 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 diff --git "a/\320\245\321\215\320\267\320\270\321\204\321\203/push-control.scd" "b/\320\245\321\215\320\267\320\270\321\204\321\203/push-control.scd" index 1cbe5f7..d499ba3 100644 --- "a/\320\245\321\215\320\267\320\270\321\204\321\203/push-control.scd" +++ "b/\320\245\321\215\320\267\320\270\321\204\321\203/push-control.scd" @@ -276,32 +276,6 @@ //============================================================================= 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; -- 2.17.1