OSC Mapper
A high level library to interact with SuperCollider via an OSC controller.
I found myself writing way too many OSCdefs in a project and decided to wrap common OSC routing functionality in a library.
The basic idea is to attach a Class which handles the incoming data to an address. This data can be a float, a button, a 2 dim XY … I tried to cover everything that gets used in TouchOSC and beyond that.
Declaring a layout of address: Class
mapping can be done via
- Using a pre-defined layout - useful for quick interaction
- Writing the layout by oneself - useful for custom controllers and bigger works
- Learning an OSC controller: A good way to start the addresses to Class mapping
The layout of a controller can be changed on the fly and also allows to
- Use the values in sclang [e.g. patterns, callbacks] and on server [via Ndef/Bus]
- Add a callback when new values are received
- Modify the range of the input data via a function (e.g.
linlin
, …) - Access and modify the controller in
def
style - Allow to access multiple elements, e.g. on a XY graph we can access both components via
.x
and.y
If you have any feedback, comments, improvements or found a bug please write it here or on GitHub
Have fun!
Quickstart
Installation
// install the quark
Quarks.install("https://github.com/capital-G/OSCMapper.git");
// restart the interpreter so the new classes are available
thisProcess.recompile;
// open documention
HelpBrowser.openHelpFor("Classes/OSCMapper");
Creating a layout
You can either define the layout manually
(
o = OSCMapper(\myLayout, (
'/1/fader1': OSCMapperFader(
altName: \fader1,
defaultValue: 0.5,
transformer: linlin(_, 0.0, 1.0, 0.5, 10.0),
callback: {|v| ["received a value", v].postln;},
lag: 0.5,
),
'/1/xy1': OSCMapperXY(
altName: \touchPanel
),
));
or use a preset like Mix 2
from TouchOSC like
o = OSCMapper.mix2(\myLayout);
or learn a custom controller on the fly
OSCMapper.learn;
// move controls
o = OSCMapper.finishLearn(\myLayout);
Using the controller within SuperCollider
As Ndef
// the osc mapper we created earlier can also be accessed in def style
o = OSCMapper(\myLayout);
Ndef(\mySine, {SinOsc.ar!2 * o['/1/fader1'].asNdef}).play;
Ndef(\mySine).clear(2);
As bus
// use the default synth
s = Synth(\default);
s.map(\amp, o['/1/fader1'].asBus);
s.free;
In a pattern via Pdefn
(
p = Pbind(
\instrument, \default,
\dur, 0.5,
\degree, Pxrand((0..10), inf),
\amp, o['/1/fader1'].asPdefn,
).play;
)
p.stop;
As raw value access
o['/1/fader1'].value;
Add a callback on change
o['/1/fader1'].callback = {|v| "value is now %".format(v).postln};
// and free the callback
o['/1/fader1'].callback = {};