Monday, April 07, 2008

Conductors: a fast GUI

I usually use Conductors because they're quick and dirty and can very easily be used to control a synth or a pbind. This class is from Ron Kuivila and it's included in the Wesleyan build or else available as quark. (See the Quarks helpfile for more on how to get it.)

Here's a quick example:

SynthDef("sin", {arg freq = 440;
  
  Out.ar(0, SinOsc.ar(freq))
}).store;
  
  
Conductor.make({arg this_conductor, freq;
  
  freq.spec_(\freq);
  
  this_conductor.synth_(
    ( instrument: "sin" ),
    [freq: freq]
  )
}).show
  

The constructor method for a conductor is make, which takes a function for an argument. The first argument to the function refers to the freshly-created conductor. Then, for the rest of the arguments, list things you want to control. So I put here "freq". freq is initalised as something called a CV.

CVs are very handy for scaling things. They have a low value, a high value, an initial value and can be linear or exponential. So a fader with a CV can slide back and forth and give you meaningful numbers in the range that you want. There's a bunch of pre-defined CV settings that can be useful for certain applications. Like here, the freq CV is being set to a pre-defined specification for audible frequencies.

Next, we're telling the conductor that it should be controlling a synth.

The first argument here is a list. We tell it which synth to use. We could also say which server to send it to and it's group and things like that.

The second argument is an array of name: value pairs. [name_of_synth_arg: name_of_cv, name_of_another_synth_arg: name_of_another_CV] This usage here ties the CV freq to the synth argument freq.

Finally we show the whole thing and you get a box with some buttons on it and a slider. The syntax of of the Conductor is slightly obtuse, but, as you can see from the box that popped up, you get a lot of stuff for free. If you click on the > button, it will start playing. Wiggle the fader. [] stops it.

We can modify the above example a little bit to see this maybe a bit clearer:

SynthDef("sin2", {arg freq1 = 440, freq2 = 10;
  
  Out.ar(0, SinOsc.ar(freq1, SinOsc.ar(freq2)))
}).store;
  
  
Conductor.make({arg this_conductor, freq, pm;
  
  freq.spec_(\freq);
  pm.spec_(\widefreq);
  
  this_conductor.synth_(
    ( instrument: "sin2" ),
    [freq1: freq, freq2: pm]
  )
}).show;

Ok, so the newer synth does some silly phase modulation.

The conductor now has two CVs called freq and pm. We set pm to have the pre-definied spec for frequencies that include the sub-audible range. Other such specs include: unipolar, bipolar, freq, lofreq, midfreq, widefreq, phase, rq, audiobus, controlbus, midi, midinote, midivelocity, db, amp, boostcut, pan, detune, rate, beats, delay If you want to see what those other ones are like, you can create a bunch of Conductors with them and wiggle the sliders around and see what you get for values.

And finally, if you look at the array to attach the synth, it's a bit clearer that freq1 belongs to the synth and freq comes from the conductor. freq2 belongs to the synth and pm comes from the conductor. And when you show it, you get two sliders.

Using a Conductor with a pattern is really straight forward:

Conductor.make({arg this_conductor, freq, amp;
  
  freq.spec_(\freq);
  amp.spec_(\amp);
  
  this_conductor.pattern_(Pbind(\freq, freq, \amp, amp)); }).show

When you play it, you'll have to turn up the amp. And you can put anything you want in that Pbind. It's just like any other Pbind. Anything you want on a gui, you can put in the argument for the Conductor. You can also do things like:

Conductor.make({arg this_conductor, freq, amp;
  
  freq.sp(3, 0, 5, 1, 'linear');
  amp.spec_(\amp);
  
  this_conductor.pattern_(
  Pbind(
    \amp, amp,
    \freq, Pfunc({[100, 250, 374, 580, 687, 910].at(freq.value)})
  ));
}).show

Here, the freq can be integers between 0 and 5. In the Pbind, a Pfunc uses the value of the freq slider as the index for an array. You need to do a whatver_cv.value to get the value that the slider is giving you. You can also set the value with whatever_cv.value_, which can make your sliders wiggle themselves around. If you want to wiggle them with a joystick or something, you might use whatever_cv.input_ and pass in a value between 0-1. This helps with the scaling.

So, for example, here's a change to the amp:

Conductor.make({arg this_conductor, freq, amp;
  
  freq.sp(3, 0, 5, 1, 'linear');
  amp.spec_(\amp);
  
  amp.value_(0.2);   
  this_conductor.pattern_(
    Pbind(
      \amp, amp,
      \freq, Pfunc({[100, 250, 374, 580, 687, 910].at(freq.value)})
  ));
}).show

Update

Conductors have been moved to become a Quark. This is a plugin system for SuperCollider that allows you to install extra libraries. If you are using the latest version of SuperCollider (any version of 3.7 alpha or higher or any version of 3.6 downloaded in the last several months), simply type: Quarks.gui and evaluate it to get a nice gui for all the quarks. Click the 'update quarks listing' button, then find Conductor in the list and mark it for install and click apply. Restart the interpreter (command-shift-l) before using any newly-installed Quark. If this does not work and you are on 3.6 or lower, see these instructions. For more information about Quarks in general, see the help page.