© 2010 Stefan Nussbaumer.
Creative Commons Lizenzvertrag

CVCenter pre1.0

CVCenter gui

Already some time ago now I “published” this extension for SuperCollider resp. SCLang, its inbuilt programming language. It lets you easily set controls of running synths or values within patterns from MIDI or OSC hardware-controllers. You may connect them from the graphical user interface (GUI).

I use the extension regularly in live performances as well as when writing code. It’s just a great convenience to be able to quickly set controls of a playing sound with a MIDI-slider or OSC-controllers (e.g. on my mobile phone) instead of having to type.

However, my extension is still under development and a lot of planned features are still missing. The screenshots you see on this page come from Mac OS X though I made them using the new cross-platform GUI, based on Qt (only the topmost teaser-image is Cocoa). QtGUI has become quite mature and I haven’t been using Cocoa for a couple of months now.

If you’re interested in the development of CVCenter you may follow the development via changelog, fork your own branch on Github or contact me.

CVWidgetEditor - OSC-editor

Connecting to an OSC-device requires the command-name resp. the message-index. In the recent version of CVCenter (resp. the various CVWidgets) I have implemented some features that

  • let you detect the valid command-names for a given device automatically and save them to disc for later reuse.OSC-commandname-collector
  • Once you’ve collected the command-names of a certain device you can simply select the device (either hardware or software) and then a suitable command-name.

Unlike MIDI OSC value-ranges are not restricted from 0-127. So CVCenter (resp. its widgets) have a built-in calibration-mechanism which detects the incoming value’s ranges automatically (can als be deactivated or set manually). Furthermore you may choose among several mappings for more fine-grained control – especially useful if you work with motion-sensors. However, not all mappings work for every input-range due to mathematical limitations. E.g. a mapping ‘explin’ (exponential to linear) won’t work if the upper and lower limits of the input range aren’t same-signed. The program will take care of these situations by adding a certain value to the incoming value, always keeping the upper and lower limit same-signed.
The connection button connects or disconnects your device with one click.

CVWidgetEditor - MIDI-editor

Connecting to MIDI-devices is equally simple. Here you don’t even have to enter the controller’s name or address – the mechanism will figure it out for you: Click the button ‘L’ (directly in the widget within CVCenter’s main-interface or the MIDI-editor), move a slider on your hardware and CVCenter should have ‘learned’ and remember to which slider it is connected (the device-id, the MIDI-channel and the controller-number should be be displayed automatically).
So far CVCenter (resp. its widgets) can work in 2 different modes:

  • 0: stands for the ‘absolute’ mode where the hardware-controller’s values (usually 0-127) will be mapped directly
  • 1: an in- resp. decremental mode – the device is expected to return an in- or decrement, not absolute values. The incoming values will be added or subtracted from the target-values inside the running program. Of course your hardware has to support this special mode, otherwise this won’t make sense. In this mode you may also set the resolution of your hardware-sliders (usually knobs).

Last but not least you may specify banks, corresponding to the hardware layout of your device: E.g. a Doepfer Pocket Dial (which was the reference device for development) has 16 knobs. However, it also has 4 banks which extends the number of assignable sliders to 64 (numbered 0-63). As it becomes difficult to see immediately which slider nr. 37 stands for you may set the bank-parameter to 16 (16 sliders per bank) which means number 37 will be displayed as 3:5 (bank 3, slider nr. 5 – for convenience numbering starts with 1 while SuperCollider internally starts from 0).
All preferences can be set even when the hardware-controller is already connected.

CVWidgetEditor - specs-editor

The ControlSpec editor lets you set an adequate spec for the value you’re controlling. E.g. for the frequency of a synth you will possibly choose a spec with an exponential curve (warp) with a range going from 20 to 20000 hz. You may either choose from a list of predefined (inbuilt) specs or define your own.
Specs can be changed at any time, even when controllers are already connected.

Basically CVCenter is just a collection of controllers (CVs), enhanced with the possibility to create GUIs for them – either within the CVCenter-gui or as single widget (CVWidgetKnob resp. currently under development: CVWidget2D – for 2-dimensional CVs and CVWidgetMS – for multidemensional CVs).

CV itsef inherits from Stream. It can be used for setting controls of (server-side) playing Synths as well as in Patterns (language-side).

CVWidgetEditor - actions-editor

CVCenter: Actions editor

Another powerfull feature added to the current version of CVCenter is the action-manger: a CV is basically nothing but a wrapper for a SimpleController. As such it can hold a number of actions that get executed any time it receives the ‘changed’-message. However, what actions and how many of them a SimpleController holds isn’t handled very transparently. Within the current version of CVCenter (resp. the CVWidgets contained in it) you may now add, remove or (de)activate an arbitrary number of actions at any time. This may be useful if e.g. you’re not sure what the controller is currently doing and you’ld like some debug-output. The number of actions currently assigned resp. the number of activated actions will also be displayed in the ‘actions’-button within the widget itself.

The CVCenter-gui is just a container for widgets which provide an inbuilt API that should allow you to integrate widgets in your own custom guis.

Code

CVWidgetSpecsEditor

CVCenter: Editor for the initial specs

The following snippet creates a full-fledged GUI from a running Synth. However, to make this work the SynthDef from which the Synth gets created must either be ‘stored’ or ‘added’ as the mechanism needs the SynthDefs description in the global SynthDescLib. Specs added to the SynthDef in its metadata will be considered automatically if the Spec’s name is contained in the list of predefined Specs. If not you can always set an adequate Spec like in the screenshot.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(
// a SynthDef with a couple of arrayed controls
// look at the actions to see how arrayed controls are handled
SynthDef('dynKlank', { |impFreq1, impFreq2, freqs1=#[800, 1071, 1153, 1723], freqs2=#[789, 1067, 1150, 1720], ringtimes1=#[1, 1, 1, 1], ringtimes2=#[1, 1, 1, 1]|
    var signal1, signal2;
    signal1 = DynKlank.ar(`[freqs1, nil, ringtimes1 ], Impulse.ar(impFreq1, 0, 0.1));
    signal2 = DynKlank.ar(`[freqs2, nil, ringtimes2 ], Impulse.ar(impFreq2, 0, 0.1));
    Out.ar(0, [signal1, signal2]);
},
// metadata, containing predfined specs
metadata: (
    specs: (
        freqs1: \freq,
        freqs2: \freq,
        impFreq1: [0.1, 5],
        impFreq2: [0.1, 5],
        ringtimes1: [1, 20],
        ringtimes2: [1, 20]
    )
)).add;
)

// wait until the server is booted
// then create the synth
s.waitForBoot { a = Synth(\dynKlank) };

// GUI-autocreation
// pairs2D-arguments will be coupled in a 2D-widget
a.cvcGui(pairs2D: (impFreqs: #[impFreq1, impFreq2]))

The same works with ProxySpaces, NodeProxies, Ndefs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// simple ProxySpace-example (not pushed)
p = ProxySpace.new;
p[\test] = { |freq| { |i| SinOsc.ar(freq+i) }!2 };
p[\test].play;
p[\test].cvcGui;
CVCenter.removeAll;
p.clear;
p.pop;

// ProxySpace, pushed
p = ProxySpace.push(s);
~test = { |freq| { |i| SinOsc.ar(freq+i) }!2 };
~test.play;
~test.cvcGui;
CVCenter.removeAll;
p.clear;
p.pop;

// NodeProxy
a = NodeProxy.new.play;
a.source = { SinOsc.ar(\freq.kr({ |i| 110+i }!2), 0, 0.2) };
a.cvcGui;
CVCenter.removeAll;
a.clear;

// simple Ndef-example
s.boot;
Ndef(\test, { |freq| { |i| SinOsc.ar(freq+(5*i)).tanh }!2 * \amp.kr });
Ndef(\test).cvcGui;
Ndef(\test).play;
Ndef(\test).clear;
CVCenter.removeAll;

Adding widgets to CVCenter and assigning actions explicitely

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// boot the server
s.boot;

// define some sound generating function with some controls
a = { |freq=220, amp=0.1| SinOsc.ar([freq, freq+1]) * amp };
b = a.play;

// add 2 CVs to CVCenter, one for freq, one for amp
CVCenter.use(\freq, \freq.asSpec);
// rather use addActionAt(key, name, action, slot, active) than CV's native
// action_(action) method if you want to store the action
// for later re-use in a setup
// the 'slot' paremeter is only needed for 2D-widgets
// actions will be set to 'active' by default
CVCenter.addActionAt(\freq, \default, { |cv| b.set(\freq, cv.value) });
CVCenter.use(\amp, \amp.asSpec);
CVCenter.addActionAt(\amp, \default, { |cv| b.set(\amp, cv.value) });

// remove the playing synth again when done
b.free;

Patterns

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
(
SynthDef(\hihat, { |out=0, atk=0.01, rel=0.1, curve=(-4.0), amp=0.5, freq=300, rq=0.5, pan=0|
    var env, son;
    env = Env.perc(atk, rel, curve:curve);
    son = BPF.ar(WhiteNoise.ar, freq, rq);
    Out.ar(out, Pan2.ar(son * EnvGen.ar(env, doneAction: 2) * amp, pos:pan));
}).add;
)

// the pattern
// no actions needed here - CVs can be embedded in patterns just like any other pattern
(
Pdef(\hiHat,
    Pbind(*[
        instrument: \hihat,
        dur: Pwrand([1/4, Pwrand([Pn(1/4, 4), Pn(1/8, 2)], [2, 5].normalizeSum, 1)], [16, 9].normalizeSum, inf),
        freq: 20000,
        atk: 0.0001,
        rel: Pgauss(0.04, Pwhite(0.02, CVCenter.use(\rel, value: 0.2))).abs,
        curve: Pgauss(-4.0, 1.0),
        amp: CVCenter.use(\amp, \amp),
        rq: Pwhite(0.1, 1.0),
        pan: Pgauss(0.0, 1.0),
    ])
)
)

Pdef(\hiHat).play;

You can add as many widgets as you like just from within your pattern-code. The class-method *use will allow you so:

1
2
3
4
5
6
Pbind(
    ...
    // params in square brackets are optional
    \patternKey, CVCenter.use(key, [spec[, value[, tab[, [slot]]]]),
    ...
)

CVCenter acts as a container for an unlimited number of CVs (CV is a part of the Conductor quark). CVs act as simple controllers which embed themselves in the Stream like any other object that inherits from Stream (like all Pattern derivates).

CVCenter lets you control your synths like you’re used to – with knobs faders sliders – and and do sequencing at the same time. However, you can concentrate at the fun part of coding (sequencing) while forgetting the boring side of it (writing CCResponders, Busses, mappings etc.).

Installation

the easy way

If you have SuperCollider installed and SVN is running on your machine (no yet? get it here) you may now do from within SuperCollider

1
2
Quarks.install("CVCenter");
// don't forget to recompile the library afterwards

still easy, yet not as comfortable

You need to have SuperCollider installed. CVCenter comes with help-files included if you’re already using SC >= 3.5 (if not you can view them here). Put all content of the zip-file into user-app-support-dir. You can easily find out where this is located by executing the following line from within SuperCollider:

1
Platform.userExtensionDir;

Under MacOS X this will resolve to:

~/Library/Application Support/SuperCollider/Extensions

If you’re on Ubuntu Linux, using the latest Developer Version of SuperCollider, it will resolve to

~/.local/share/SuperCollider/Extensions

Using CVCenter Linux will require QtGUI, the new Qt-based cross-platform gui-system, developed by Jakob Leben. Unfortunately CVCenter won’t work properly with SwingOSC, a Java-based cross-platform gui-system.

A little demonstration

Here’s a little video, demonstrating CVCenter being used together with a Kinect:

AtomRecent Commits to CVCenter:pre1.0

Wednesday, January 22 2014, 13:41: Yet another tweek reflecting the removal of GUI redirects

Wednesday, January 22 2014, 12:28: Minor update Overview

Wednesday, January 22 2014, 12:16: Correct sloppy English

Saturday, January 11 2014, 20:54: Correct link to Windows download

Saturday, January 11 2014, 18:08: get rid of some deprecation warnings

Saturday, January 11 2014, 13:30: update README

Saturday, January 11 2014, 12:40: fix History shortcuts in CVCenter

Saturday, January 11 2014, 12:35: fix History shortcut

Saturday, October 12 2013, 14:09: CVCenter:*removeAtTab: only perform CVCenter:*removeAll if the given …

Sunday, September 8 2013, 18:20: edit .gitignore

Sunday, August 25 2013, 20:10: correct spelling

Saturday, August 24 2013, 18:09: bugfixes: CVCenter: prevent errors if no preferences exist. CVCenterP…

Saturday, May 25 2013, 12:01: Merge branch 'master' of github.com:nuss/CVCenter

Saturday, May 25 2013, 12:00: OSCCommands: don't open another window if the window is already present

Wednesday, April 24 2013, 20:16: fix actions display in CVWidgetEditor

Sunday, April 14 2013, 13:26: bugfix: CVWidget:-oscConnect

Friday, April 12 2013, 13:27: update README.md

Thursday, April 11 2013, 20:31: CVCenter: rather use \UI.asClass.isNil to check if UI.registerForShut…

Friday, April 5 2013, 18:55: CVCenter:*initClass - backwards compatibility fix

Tuesday, March 19 2013, 22:39: bugfix in CVWidgetEditor: consider the slot when setting ctrlButtonBa…

One Comment

  1. Rudy
    Posted 26 Nov ’12 at 9:42 am | Permalink

    I get that error message when I click on the “edit OSC” button in the CVCenter main gui.
    Could it be that the sensor wasn’t connected properly or there was something wrong with it?

    sorry about this bit I am freaking out as I am suppose to install the work tomorrow and leave it on display for 4 days. Going through a lot of stress (not just for this). Now I am away from the sensor but I will be working on it before the set up around 9/9:30 your time.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>