************* Not updated for new JITGuis yet! ****************
UC33Ktl a class for handling mappings of the Evolution UC33 controller
Inherits from: MIDIKtl
The Evolution UC33 produces only MIDI controller events. It has 4 switchable scenes,
in which all controllers (sliders, knobs, upper and lower buttons) have different cc numbers.
The 6 transport controls remain the same in all scenes.
UC33Ktl keeps a dictionary of actions for all mapped controllers.
See also: UsingMIDI, CCResponder, MIDIIn
First example
// make a ProxySpace and a mixer for it, map the NanoKtl to it
p = ProxySpace.push(s.boot);
m = ProxyMixer(p, 16);
// put some proxies in it
(
8.do { |i| p[("test_bla" ++ i).asSymbol] = { |ring = 0.02|
Pan2.ar(Ringz.ar(Impulse.ar(exprand(0.5, 4)), exprand(300, 3000), ring), 1.0.rand2, 0.2) };
};
Spec.add(\ring, [0.0001, 1, \exp]);
)
// make a UC33Ktl, and map it to the mixer:
// the sliders control the first 8 volumes,
// the lower buttons play the proxy,
// the upper buttons send to the editor,
// the knobs control the editor parameters,
// and the last slider controls server volume!
(
g = UC33Ktl.new;
g.mapToPxMix(m, 1);
)
Creation / Class Methods
*new (srcID, dict) create a UC33Ktl object.
srcID - every MIDI port (e.g. from a USB plug) gets a unique ID.
This can be used to distinguish multiple controller which may have
overlapping MIDI channel/controller numbers.
dict - a dictionary of the actions that are mapped to controllers.
// simple example
g = UC33Ktl.new; // listen to all midi in ports
// g = UC33Ktl(1643926019); // only listen to the left USB input on my laptop
g.ccDict; // a dict where the maps will live
g.ccresp; // a midi CCResponder listing to that MIDI port
// map transport buttons 'play' and 'rec' to simple actions:
g.mapCCS(1, 'play', { |ccval| " 'play': %.\n".postf(ccval) });
g.mapCCS(1, 'knu1', { |ccval| " 'knu1': %.\n".postf(ccval) });
g.mapCCS(1, 'knm2', { |ccval| " 'knm2': %.\n".postf(ccval) });
g.mapCCS(1, 'knl3', { |ccval| " 'knl3': %.\n".postf(ccval) });
g.mapCCS(1, 'sl4', { |ccval| " 'sl4' : %.\n".postf(ccval) });
g.mapCCS(1, 'sl9', { |ccval| " 'sl9' : %.\n".postf(ccval) });
// the actions are now in the dict:
g.ccDict.postcs;
// clean up
// ( g.free; )
Class Variables
verbose
can be set to true to post info for debugging.
UC33Ktl.verbose = true;
//
UC33Ktl.verbose = false;
Instance Variables
ctlSceneNames
a dictionary of names such as \sl1 to controller keys as used for lookup.
the keys are symbols like '0_42' meaning midichannel 0, ctl num 42.
// controls that remain the same in all scenes:
g.ctlNames[0];
// the names in scene 1
g.ctlNames[1] // scene 1 is quite usable
g.ctlNames[2] // in scene 2 buttons 4-9 and 0 turned off, some midi cc overlap...
g.ctlNames[3] // scene 3 is complete again, but some overlap
g.ctlNames[4] // scene 4: buttons 0 - 9 do nothing, again some overlap.
// unfortunately, the default control maps for the UC33
// have quite a bit of overlap of channel/cc combinations.
// so one should make non-overlapping setups, e.g. with separate midi channels,
/// in order to be able to really use multiple scenes fully!
g.ctlNames[1].values.sect(g.ctlNames[2].values)
g.ctlNames[1].values.sect(g.ctlNames[3].values)
g.ctlNames[1].values.sect(g.ctlNames[4].values)
g.ctlNames[2].values.sect(g.ctlNames[3].values)
g.ctlNames[3].values.sect(g.ctlNames[4].values)
Instance Methods
mapCCS (editor, scene)
map one of the controls in a scene to a general function.
// map transport buttons 'play' and 'rec' to simple actions:
g.mapCCS(1, 'play', { |ccval| " 'play': %.\n".postf(ccval) });
g.mapCCS(1, 'knu1', { |ccval| " 'knu1': %.\n".postf(ccval) });
g.mapCCS(1, 'knm2', { |ccval| " 'knm2': %.\n".postf(ccval) });
g.mapCCS(1, 'knl3', { |ccval| " 'knl3': %.\n".postf(ccval) });
g.mapCCS(1, 'sl4', { |ccval| " 'sl4' : %.\n".postf(ccval) });
g.mapCCS(1, 'sl9', { |ccval| " 'sl9' : %.\n".postf(ccval) });
mapToPxEdit (editor, scene)
map the knobs in a scene to a NodeproxyEditor or Ndef.
The first 8 knobs go to the parameters of the proxy, the 9th control the proxy's volume.
(
p = ProxySpace.push;
~test = { |freq=250, intv=19, timescale=1, curve=0, loopnode=0, formfact=2, widfact=0.5, spread=1, amp=0.1|
var env = EnvGen.kr(
Env(
{ 1.0.rand2 }!11,
{1.0.rand}!10 * timescale,
curve,
releaseNode: 9,
loopNode: loopnode)
);
var pitch = (env * [1, 0.33, -1] * intv).midiratio * freq;
Splay.ar(
Formant.ar(pitch, pitch.scramble * formfact, pitch.scramble * widfact), spread) * amp;
};
// add specs for all the parameter ranges - required!
Spec.add(\intv, [0, 36, \lin]);
Spec.add(\timescale, [0.001, 10, \exp]);
Spec.add(\curve, [-10, 10]);
Spec.add(\loopnode, [0, 7, \lin, 1]);
Spec.add(\formfact, [0.1, 10, \exp]);
Spec.add(\widfact, [0.1, 10, \exp]);
Spec.add(\spread, \unipolar);
n = NodeProxyEditor(~test, 12);
);
g = UC33Ktl.new; // make a new UC33Ktl
g.mapToPxEdit(n, 1); // and map its scene 1 to the editor n
// shift by hand which params are mapped
g.paramShift(0); // show which params are mapped
g.paramShift(1); // shift by one; when hitting the end, jumps back.
// test using a second proxy, UC33Ktl scene 2:
~test2 = ~test.source;
o = NodeProxyEditor(~test2);
g.mapToPxEdit(o, 2); // scene
mapToPxMix (mixer, scene)
Maps one scene of the UC33Ktl to a proxymixer.
The first 8 sliders control individual proxy volumes; these can be shifted.
The rightmost slider controls server volume.
The knobs in the scene are mapped to the proxymixer's editor:
The first 8 knobs go to the parameters of the proxy, the 9th control the proxy's volume.
The upper buttons send the corresponding proxy to the editor,
the lower buttons toggle play/stop of the respective proxy.
upper button 9 - shifts the mapped proxy volumes,
lower button 9 - shifts the mapped editor's params.
slider9 controls server volume.
// make a proxymixer and some more proxies to test
p = ProxySpace.push(s.boot);
(
m = ProxyMixer(p, 16);
20.do { |i| p[("test_bla" ++ i).asSymbol] = { |ring = 0.02|
Pan2.ar(Ringz.ar(Impulse.ar(exprand(0.5, 4)), exprand(300, 3000), ring), 1.0.rand2, 0.2) };
};
Spec.add(\ring, [0.0001, 1, \exp]);
)
g = UC33Ktl.new;
g.mapToPxMix(m, 1);
g.pxShift(1);