************* 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);