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.
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.
- 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.
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.
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).
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
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.
- Getting started with SuperCollider
- CVCenter on GitHub
- CVCenter download
- Online-documentation for CVCenter
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
Sunday, September 8 2013, 18:20: edit .gitignore
Sunday, August 25 2013, 20:10: correct spelling
Saturday, May 25 2013, 12:01: Merge branch 'master' of github.com:nuss/CVCenter
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
Friday, April 5 2013, 18:55: CVCenter:*initClass - backwards compatibility fix
16 Comments
Hello Stefan,
hope you are doing well and keeping warm.
Sorry to keep bothering you but I feel the next few issues are better discussed here than the SC forum.
I have been using your extension for the last month and is really helping me a lot with my project. However, I have a couple of issues that I would like to discuss.
First the “save setup” and/or “load setup” command don’t seem to work when invoked form the CVCenter main window (the back one).
When I save a setup file it prompt me to type the file name and it seems it is saved, but when I recall it by clicking “load setup”, I chose the file but once is open no information is retrieved. It looks like nothing happen.
This is the code I use:
//////////////////////////////////
Server.default.waitForBoot { y = Synth(“fMod2S”) };
y.cvcGui
y.free
/////////////////////////////////
I wonder if I should load a setup via code.
Also the y.free does not seems to clear much, as when I run the same code again, the CVCenter that appears is not new but is the old one form before.
maybe I should use ///// y.removeAll //////????
————————————————————————————————
Another issue is the fact that the calibration works for one person but if someone enter the installation next, the calibration boundaries are the ones set by the previous person and are naturally not right for the new person interacting especially if they is smaller.
Their movements will be shorter and never reach the boundaries set by the previous user.
Not sure if I am clear but essentially every time a new user is detected the “OSC input constrain” and the “compensation” should be reset.
Hope what I wrote make sense,
Have a good day/night,
R
Hi Rudy,
sorry for the delayed reply – not only has the server hosting my website gone down (I’ve switched to a new ISP now) – I also had a busy day.
Yes, I can confirm there’s something broken: A setup should store all actions already added to widgets as well as MIDI- and OSC-responders. But they seem to get ignored mostly :\ (I had a look at the setup-file and indeed the actions get stored but not the responders. However, when I load the setup also the actions get ignored…).
I don’t think that will make a difference – the buttons just call CVCenter:*saveSetup resp. CVCenter:*loadSetup.
Hmm… do you at some point stop the calibration i.e. fix the boundaries before the next person comes in? Have you tried to just re-calibrate by activating calibration again? I vaguely remember that after having fixed calibration and then reactivating it it would pick up at the original zero-boundaries (not sure – would have to test again). So, maybe it would help if you first deactivate calibration and then reactivate it again after the new performer has come in… I understand the problem I think but I have to apologize as I’m not exactly sure how the mechanism behaves.
So much for now. I’ll have a look at the setup-problem as soon as I find time. Let me know if the calibration trick works for you.
Thanks so much for the feedback,
Stefan
P.s.: I filed a bugreport on github: https://github.com/nuss/CVCenter/issues/1
If you find more bugs don’t hesitate to add another bug-report there (don’t know if you need a github-account for that though)
Hi Rudy,
I’ve pushed a fix for the non-working “loadSetup” (also committed to the quarks-repository already). You were on the right track suspecting it something to do with the way it was working in the gui – the arguments were switched: if “load actions” was selected the opposite was happening… can you try if my fix works for you? (I really hope I haven’t messed up something else now…).
Thanks, Stefan
Hello Stefan,
I really don’t know how to thank you!
I managed to successfully install your CVCenter extensions via Quarks following your instructions and other tutorials online (sometimes it helps to read how things works before attempting to use them…..) .
I am still getting a warning though (I will post it next as I am away from my machine — I access the internet at work and school so it is difficult for me to have everything at hand — by the way, where are you? I’m originally from Europe but I am in New Zealand right now) but the extension seems to run fine as I am experimenting with the first example on your blog (dynKlank).
I am using the kinect via NImate free version (it is a proprietary software), the sensor is recognized as I get the correct list of OSC command names in the CVCenter- OSC editor widgets, I saved it and I am able to recall it after quitting and restarting. However there is something wrong as I am waving my hand (the joint I am testing) but the slider/knob is not moving. I tried to calibrate it but I am not sure how it works. I get the data into SC as I checked, but somehow CVCenter does not like what is fed.
I am getting to this conclusion as the slider does change sometimes; it just jump to a different number and stays there. NImate does not require to stand in a pose to be detected and I am testing from sitting down, I don’t know if that influence the calibration process. Also, the values for the x and y axises range from [-1.8000000 , 1.8000000] more or less (not sure about decimals). I wonder if that is a problem.
Anyway, I tried another way and followed all (almost all) your steps so I successfully installed openNI, SensorKinect , but having problems with OSCeleton (the easiest one). I am not sure where I should place it and what’s the command line to launch it in “QuartzComposer-mode” . I drag the app icon into the terminal and it was running (no error messages) but did not have the live monitor with kinect data.
Sorry to be a pain, but I feel I am really close to be up and running, so that I could concentrate on the fun part (the sound). I will definitely supply you with extensive feedback for your extension. By the way, I am running on a Macbook Pro with 10.7 on.
Thank you and take care,
Rudy
UPDATE:
sliders seems to work but I think I need to figure out how to scale and/or adapt the range somehow.
Hey Rudy,
I’m really, really happy hearing that I could help you and you basically got things working!
Is it a warning or an error? Post it if you can.
I’m currently living in Vienna, Austria. So, there’s a 12 hours timeshift between us ;). The dynKlank-example is working for you?
As far as external (Kinect-)software is concerned it’s really hard for me to tell what goes wrong. I don’t own a Kinect myself and I didn’t write CVCenter explicitely for the use with a connect – much rather it should work with any controller that sends numerical values via OSC (e.g. OSC-controllers installed on mobile phones).
When you say CVCenter doesn’t like what it’s fed, how does it complain? What might be wrong could e.g. be the formatting of the OSC-message which should somewhat look like the following:
CVCenter resp. CVWidgets expect(s) the command-name in the first slot of the incoming OSC-message (index 0) and all values in the subsequent slots. However, I found that not all software necessarily sticks to that scheme. As OSC-commandnames have a canonical structure (names divided by slashes) it could be that you get the ‘root’-name in the first slot and a sub-commandname in the second. That would be quite suboptimal (you could work around it in the widget’s action but that’s a bit clumsy).
Especially OSCeleton sends OSC in this form if QuartzComposer-mode isn’t activated. But it should be easy to activate by setting the -q flag:
(there are probably more flags to be set but as I said I don’t own a Kinect and I haven’t set up a working environment for it on my machine).
If you want to check what’s really coming in on your machine resp. SuperCollider you can execute the following commands in SC:
2
3
4
5
6
7
8
9
10
11
12
13
14
OSCFunc.trace(true); // Turn posting on
OSCFunc.trace(false); // Turn posting off
// SC 3.4
// post all incoming traffic except the server status messages
(
thisProcess.recvOSCfunc = { |time, addr, msg|
if(msg[0] != '/status.reply') {
"time: % sender: %\nmessage: %\n".postf(time, addr, msg);
}
}
);
// stop posting.
thisProcess.recvOSCfunc = nil;
With these code-snippets you should see incoming OSC-messages displayed as arrays like I described earlier (OSCCommands is using this mechanism behind the scenes).
This is easy (if I understand the problem correctly. What needs to be done is that the range of incoming values (e.g. 0.0-1.0) must be mapped to a reasonable output-range (e.g. if you want to set a frequency it might be a range of 20-20000 hz). Therefore I added the possibility to set ControSpecs. You can either do this in code:
2
3
// e.g. \freq.asSpec
CVCenter.cvWidgets[\myWidget].setSpec(<a ControlSpec>);
or – probably easier – use the widget’s Spec-editor (have a look at the screenshot in the article above) that can be opened by clicking the “edit Spec”-button.
Basically it doesn’t matter what the range of incoming values is – selecting an appropriate ControlSpec will scale the input automatically to the right output-range. There’s a number of predefined ControlSpecs (if you have cruciallib installed there will be even more). Here’s a little example how to define a custom one:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ControlSpec(20, 2000)
// this could also be written like
[20, 2000].asSpec
// choose an exponential curve instead of a linear one
// useful e.g. if you're dealing with frequencies
ControlSpec(20, 2000, \exp)
// or
[20, 2000, \exp].asSpec
// give the spec a default step-size
ControlSpec(20, 2000, \lin, 1.0)
[20, 2000, \lin, 1.0].asSpec
// give the spec a different default value
ControlSpec(20, 2000, \exp, 0.0, 440)
[20, 2000, \lin, 0.0, 440].asSpec
// predefined specs may also be addressed in the following manner
// within the Spec-editor you can select predefined specs from a drop-down menu
\freq.asSpec
I would strongly recommend to have a look at the ControlSpec-helpfile. There are some limitations due to the underlying math e.g. the following isn’t possible (outputs NaN-values:
2
3
// must be same-signed
ControlSpec(0, 1000, \exp)
… so musch for now. Hope that helps you to overcome the last hurdles (as always, let me know ;) )
good luck!
Stefan
Hey Rudy,
I see you got a couple of problems.
There’s no key required – you only have to accept the signature of the repository (not sure about the exact term but usually you would just have to type y or yes). From what you say I guess SVN is installed properly (note: on OS 10.6.x SVN comes preinstalled if I’m not mistaken). However, you could do the following to checkout the Quarks-repository on your machine: In Terminal cd into
First, let’s see if SVN is installed – type:
… which should give you a meaningful result if SVN is installed.
Then (if SVN is installed) execute the following command:
That will create a directory “quarks” but not yet install them
Next, open SuperCollider. Execute:
That will open a gui which should be quite self-explanatory – you can install and uninstall qurks as you like (note: before you install the CVCenter-quark remove the CVCenter-folder that you’ve put in “Extensions”! Otherwise you will get a “duplicate class” error).
However, the Quarks-mechanism should also take care of dependencies. E.g. CV (as part of the Conductor-qurk) and TabbedView are among them (it’s stated in the README). Without these CVCenter won’t work. You can also install quarks manually:
2
Quarks.install("Conductor");
Installing quarks doesn’t mean you have to download them again. If you have them already checked out all that happens is that there gets a symlink created in
Checking out all quarks will not interfere with SuperCollider’s functionality as long as you don’t install them!
Additionally you could install the following quarks:
2
Quarks.install("wslib");
These add some functionality but aren’t strictly necessary.
And one last word about SVN + Quarks: If you’re updating from within SuperCollider you should make sure SC finds the currently installed version of SVN. In Terminal execute:
That should give you the path to the SVN-executable
In your SuperCollider startup-file you can then add this folliwing line (replace /path/tosvn with the result of the above mentioned command)
2
QuarkSVNRepository.svnpath_("/path/to/your/svn/executable");
… hope, that brings you a bit further.
Good luck,
Stefan
Hello Stefan, my name is Rudy and I have some very basic questions (sorry) about SC and OSC in conjunction with Kinect and NImate.
I have the free version of NImate and can see OSC messages coming into SC when I ran
OSCFunc.trace(true); (screen shot if needed http://www.mediafire.com/?p5upqncoodvcazc)
Now, as I am fairly new to this I am wondering what I should do to actually understand the range of the values for each message and how can I use the value to modify parameters of synthDefs in SC. (basic syntax protocol)
I am not trying to take the shortcut by asking what to you might seems trivial, but I just would like to get something going while I am learning the basics.
Your CVCenter library seems to be useful to my purposes but it seems I had some trouble installing it.
Any help would be appreciated.
Thanks and congratulation for your hard work,
Rudy
Hi Rudy,
First of all, your screenshot proves you installed all prerequesits for using a Kinect with SC successfully – congratulations!
For a better understanding of how to set controls in a running synth I’d recommend to read the Synth-helpfile within SuperCollider’s help-system (You’re on Mac? Just type the word “Synth” in a document, select it and hit cmd+d and the regarding help should open. Or have a look at the online-version: http://doc.sccode.org/Classes/Synth.html
The basic procedure would be:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// putting it in brackets should allow you to easily select the hole code-block by
// clicking somewhere inbetween and execute it by hitting shift+return
(
SynthDef(\test, { arg freq;
Out.ar(0, SinOsc.ar(freq));
}).add;
)
// create a Synth-object
// you won't hear anything yet as we haven't defined a value for 'freq' yet
// execute the line by putting the cursor on the following line and hit shift+return
x = Synth(\test);
// set a value for 'freq'
x.set(\freq, 300);
// you should now hear a sine-tone at 300 hz coming out of one speaker
x.set(\freq, 500);
// the frequency should have changed to 500 hz
Regarding the “rnage of values” from the output of OSCFunc.trace: I guess output ranges from -1 to 1. I’m slightly surprised that there are only 2 values comming in (as e.g. in [ /joint, /Right_Shoulder, 0.0168…, -0.0455…]). I’d expect 3 – x, y, z. Also, OSC-messages coming in from the Kinect are a formatted a bit different from those I got in my tests. It would have been more convenient if the array returned in ‘msg’ had a command-name line /joint/Right_shoulder in its first slot, followed by the values in the remaining slot. This makes it necessary to add another if-condition in an OSCresponder ‘s action (OSCresponders in SC 3.4 have been replaced with OSCFunc resp. OSCdef in SC 3.5 – functionallity is basically very similar). Here’s one example OSCFunc (not tested, hopefully working and demonstrating what I mean):
2
3
4
5
6
7
8
9
10
11
OSCFunc({ |msg, time, addr, recvPort|
//[msg, time, addr, recvPort].postln // just for debugging
// "/Right_shoulder" could be a Symbol as well - don't know - try '/Right_Shoulder' instead
if(msg[1] == "/Right_Shoulder", {
// do something with the first numeric value in msg (msg[2])
// 'x' would be the Synth I posted above
// the value gets mapped from a range of [-1, 1] to [20, 20000] (frequency)
x.set(\freq, msg[2].linexp(-1, 1, 20, 20000);
}, '/joint')
)
The difference when using CVs is that you’re not directly setting a value in a synth but you’re setting a value of the CV (basically a model that is used by a controller that can disptch that value to many things like GUIs and Synths at once). Compared in a simplified diagram this would look like this:
2
new: OSCresponders captures input from Kinect -> function in the OSCresponder sets the value of the CV -> Synth-control gets set accordingly to the value of the CV
I’ve gone through all this. I think I understand what you mean. However, I can really recommend subscribing to the sc-users mailing-list: http://www.beast.bham.ac.uk/research/sc_mailing_lists.shtml (you can also follow and even post to the list using the nabble-forum: http://new-supercollider-mailing-lists-forums-use-these.2681727.n2.nabble.com/SuperCollider-Users-New-Use-this-f2676391.html ).
Can you elaborate what the troubles were? Information like this would be valuable for me. If possible I’d like to make things as easy as possible.
Thanks for your interest and good luck! If you’re running into troubles again or find your questions not answered sufficiantly please don’t hesitate to get in touch.
Stefan
Hey Stefan,
Thank you very much for your help!
Now I understand how to access a single value from the Kinect stream but I am still having trouble.
You are right, the values from the Kinect are in the form:
(\joint_type, X: x,xxxx, Y: y,yyyy, Z: z,zzzz)
essentially, the type of joint and a 3D vector of floats
I adapted your SynthDef example so that the frequency would be control by the X vakue of the right hand but it did not work.
SoI stepped back a little and I tried with a Line.kr as the feed for the freq argument but apparently SC Synths don’t like to be fed control rate values.
So I am wondering what’s the best way to implement a SynthDef that can be controlled while streaming.
Sounds like your CVCenter might be one answer but I was wondering if there is a more direct way. I want to learn to use CVCenter but first I want to make sure I understand the basics of SC.
Sorry I am not on my machine at present, so I will be sending the code examples asap.
Thank you and have a good day/evening
R
Hey Rudy,
good to see you’re back ;)
If I understand correctly you have successfully built the SynthDef (SynthDef(\test, {…}).add (‘add’ is important!) and instantiated a Synth-object like x = Synth(\test). Now, if your installation of CVCenter is working properly (did you install from a downloaded zip-file or the Quarks-mechanism in SC?) then there should only one more step be required to generate a widgt for \freq in CVCenter:
2
x.cvcGui;
This bit of code shouldn’t only create the widget (resp. the CVCenter-gui) but also add an action to it:
2
3
4
5
// |cv| is the same as arg cv;
{ |cv|
x.set(\freq, cv.value)
}
In each widget you can find a blue button labeled “actions” at the bottom. Click on it and you should see the action described above in a textfield. If it’s activated you can turn the widget’s knob and you should hear frequency change.
That surprises me. I’m pretty shure they take control-rate values (the main difference is that control-rate values get calculated only once each control-block while ar-values get calculated for every single sample).
Anyway, let me know how you get along.
Stefan
Hello Stefan;
I tried to download CVCenter via Quarks using uberSVN but I get this error:
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
CVCenter not found in local quarks; checking out from remote …
ERROR: Quark not found in repository.
CALL STACK:
]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
and then a bunch of code.
I think the problem is that uberSVN is not installed properly as I was supposed to enter a key but restarted the computer before that and could not figure out how to restart the software interface in order to enter the key.
Anyway, I then downloaded your CVCenter manually from :
https://github.com/nuss ,
placed the unzipped file into ~/library/application Support/Supercollider/Extensions and when I recompile the library I get this:
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
empty
compiling class library…
NumPrimitives = 853
compiling dir: ‘/Applications/SuperCollider/SuperCollider.app/Contents/Resources/SCClassLibrary’
compiling dir: ‘/Users/MrSilly/Library/Application Support/SuperCollider/Extensions’
pass 1 done
• ERROR: Class extension for nonexistent class ‘TabbedView’
In file:’/Users/MrSilly/Library/Application Support/SuperCollider/Extensions/nuss-CVCenter-cfbab4c/CVCenter/extTabbedView.sc’
numentries = 1213079 / 21659376 = 0.056
6348 method selectors, 3412 classes
method table size 20594384 bytes, big table size 173275008
Number of Symbols 16398
Byte Code Size 591261
compiled 549 files in 0.32 seconds
compile done
Help tree read from cache in 0.0022807729999386 seconds
Class tree inited in 0.02 seconds
RESULT = 0
WARNING: Called from SynthDef:buildUgenGraph, method Meta_Mix:arFill is deprecated and will be removed. Use Meta_Mix:fill instead.
For advice: [http://supercollider.sf.net/wiki/index.php/DeprecatedError]
WARNING: Called from SynthDef:buildUgenGraph, method Meta_Mix:arFill is deprecated and will be removed. Use Meta_Mix:fill instead.
For advice: [http://supercollider.sf.net/wiki/index.php/DeprecatedError]
Welcome to SuperCollider 3.5.5, type cmd-d for help
]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
Not sure what do do.
I trashed the “extTabbedView.sc” and it compile without the error but
i am not sure if it is the right move.
Thank you and take care,
Rudy
Ok,
I have tried to run some of the examples above and I get some error whenever I try to instantiate a CVCenter object:
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[
Execution warning: Class ‘CV’ not found
ERROR: Message ‘new’ not understood.
RECEIVER:
nil
ARGS:
Instance of ControlSpec { (0x104f43888, gc=D4, fmt=00, flg=00, set=04)
instance variables [9]
minval : Integer 20
maxval : Integer 20000
warp : instance of ExponentialWarp (0x104f43bc8, size=1, set=2)
step : Integer 0
default : Integer 440
units : ” Hz”
grid : nil
clipLo : Integer 20
clipHi : Integer 20000
}
Integer 440
CALL STACK:
]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
I am interested in generating sound from kinect data, and I came across your project. It looks really great! I have played with Morgan Packard’s Ripple which is a Supercollider project, so I wanted to use Supercollider.
I got OSCeleton working (Processing example works) and got CVCenter installed in Supercollider (playing tune from CVCenter.html), and can control amp using the knob. I am trying to get OSCeleton hooked up to CVCenter. I started CVCenter, started osceleton, and got the calibration complete message, and tried to capture osc data from 127.0.0.1:7110 (where osceleton reports it is running). However the OSC-command-name collector didn’t work as I expected. I only get n_go and n_end. I am not sure what OSC command-name to put in the box (I tried /joint). Screenshot: http://goo.gl/Gpaio
Thanks!
Hi Charles,
You may omitt the IP-address resp. the port or provide an IP-address only. If both are nil (default) SuperCollider will listen to any address and capture all values under the given command-name. If you want to make sure SC is only listening to one explicit machine it’s usually enough to provide the IP-address. I can’t see the full stacktrace in your screenshot but it looks like an error is triggered somewhere within
which means something’s going wrong during connection.
2 things:
As far as I remember an OSC-message coming from OSCeleton (started with the -q option) look somewhat like the following:
SuperCollider processes this message as an array, so, the command-name is slot 0 and the other slots are treated as value-slots. Try the following code see what messages are coming in (SC 3.4 compatible – OSCCommands.collect basically does the same though at the moment it’s likely SC 3.5 only and it’s rather adding command-names and the number of value-slots to a list than posting them):
2
3
4
5
6
7
8
9
10
11
(
thisProcess.recvOSCfunc = { |time, addr, msg|
if(msg[0] != 'status.reply') {
"time: % sender: %\nmessage: %\n".postf(time, addr, msg);
}
}
);
// stop posting.
thisProcess.recvOSCfunc = nil;
So much for now. It’s always useful to have the stacktrace if some error happens. Paste it here or maybe on pastebin.com. Tell me what SC-version you’re using.
Thanks for the feedback,
Stefan