Super Collision At Studio Dave: The New World Of SuperCollider3, Part 2

In the first part of this series I introduced SuperCollider3 and its most basic operations. Now let's make things a little more interesting by adding a little randomization, a neat GUI, and some MIDI control.

Creating A GUI

Let's add a simple GUI to control the synthesizer. We'll employ the services of a SuperCollider Quark called AutoGui to make things easy for us novices :

    a = SynthDef(\sinetest, {arg out = 1, freq = 440; Out.ar(out, SinOsc.ar(freq))}) ;
    z = SynthDefAutogui(\sinetest, scopeOn:false) ;

Easy, just two lines of code to produce the synthesizer control panel seen in Figure 1.

 

Figure 1. SuperCollider's AutoGui Quark at work.

As its name implies, the AutoGui class automatically creates a GUI to represent the elements of a SynthDef, i.e. a SuperCollider synthesizer definition. In the example, the SynthDef is built from our simple synth and an added output channel setter. AutoGui performs its magic on the SynthDef, and voila, we have a synthesizer with a graphic control panel, made with two lines of SuperCollider code.

AutoGui is one of many realizations of SuperCollider's GUI capabilities. Other interesting manifestations include Fredrik Olofsson's red* quarks, James Harkins' dewdrop library, the Crucial extensions, and the EZ-GUI classes. As in other aspects of the system, SuperCollider gives you more than one way to do the job.

 

photo of the hadron quark

Figure 2. The Hadron Quark on display. (Full size)

Before leaving our simple example let's look at something with a more ambitious GUI. Figure 2 shows off Batuhan Bozkurt's Hadron, a SuperCollider quark that include various GUI components. At first Hadron looks a little like SuperCollider in Pd's clothing, but Hadron is a personal system, not a general-purpose GUI. Like most examples of a SuperCollider GUI Hadron was designed originally for its creator's specific purposes, and thanks to its broader utility it's been packaged as a quark for other users to explore. My first experiments included the addition of more synths and effects processors on my canvas layout - with all states saveable and loadable - and I've started to look into the guidelines for writing my own Hadron plugins.

Notes On Notes

By now the sound designer might be a little interested in SuperCollider, but the composer might be wondering what the fuss is all about. Our tiny example merely plays a sine wave at a single frequency and a default amplitude value. However, consider the following code :

   a = {SinOsc.ar(Rand(200,400))}.play;

Now a different frequency value, randomized between 200 and 400 Hz, will be used for each run of the code. Composition-wise our example's getting a little more interesting, but it needs some repetition to get something like a phrase from it. The following code presents one solution - a Task - for generating a series of randomly selected tones :

    (
    SynthDef("Randy", {arg out = 0;    // Single-channel output.
        Out.ar(out,
            SinOsc.ar(
                // Randomize integer frequency values.
                Rand(200,400),       
                // Apply an amplitude envelope to each note.
                0, Line.kr(0.2, 0, 1, doneAction:2))   
            )
    }).send(s);    // Send the definition to the server.
    )

    (
    t = Task({
            16.do({
                    Synth.new("Randy"); 0.5.wait;   
            })
    }).play;
    )

When the Task is evaluated the synth named Randy will be played 16 times, each time at a different frequency, with half a second between notes. Now things are looking a lot more interesting to our composer, especially when she starts figuring out how to apply randomization to other variables, e.g. the wait time and the do length. She might get even more interested when she learns how to create a GUI for triggering this Task, but before we get further into SuperCollider's GUI capabilities let's look at its MIDI connectivity.

A Little MIDI, S'il Vous Plait

The next example takes our little sine-wave synthesizer and puts it under MIDI control. The example also introduces a more complex SynthDef, with a gate value added for constructing an envelope to shape the audio output for each note played, similar to the example above. I plugged an Akai LP25 keyboard into my laptop's USB port, then I opened the ALSA MIDI panel in QJackCtl to connect the LP25 to a SuperCollider MIDI input port. After evaluating each block of the following code I played a few notes on the keyboard and heard the now-modulated dulcet tones of our simple sine-wave synth :

    MIDIIn.connect;
    s = Server.local;
    s.boot;
    s.latency = 0;

    (
    SynthDef("sinetest", {arg out = 1, freq = 440, gate = 0.0;
        x = SinOsc.ar(freq);
        x = EnvGen.kr(Env.adsr, gate,Latch.kr(gate,gate)) * x;
        Out.ar(out, x);
    }).send(s);
    )

    x = Synth("sinetest");

    //set the action:
    (
    MIDIIn.noteOn = {arg src, chan, num, vel;
            x.set(\freq, num.midicps / 4.0);
            x.set(\gate, vel / 200 );
    };
    MIDIIn.noteOff = { arg src,chan,num,vel;
            x.set(\gate, 0.0);
    };
    )

(Props to the authors of the SuperCollider manual for providing the basic version of this code. However, a much better - and preferred - method may be seen in the Comments section, thanks to James Harkins).

Cool, and not too complicated. The documentation includes many other examples, so if MIDI's your musical medium you'll want to check out the relevant docs for more insight and useful code.

More Words About That GUI Stuff

SuperCollider's GUI elements are nicely integrated into the language, with considerable documentation regarding their use. The system is flexible, and only a little effort is required to bring older SuperCollider code into modern usage. Class redirection automatically assigns the GUI toolkit according to the recognized operating system, but the user can control the deployment of the supported GUI views.

SuperCollider 3.5 uses the new Qt interface elements for its default GUI. However, if necessary I can switch easily between Swing and Qt, and many code examples are written for cross-platform application. Being able to switch GUI views can be most helpful. For instance, if you try to open the SuperCollider Help document while the GUI is set to Swing you'll receive this error :

ERROR:_ViewRedirect_is_an_abstract_class_and_should_not_be_instantiated_directly._*new_method_not_valid.

You can solve the problem by momentarily switching GUI kits. Run GUI.qt, and you'll be able to access the Help files. Keep the help doc open, then run GUI.swing if you want to reassert Swing as the active GUI view for your project code.

SuperCollider's GUI capabilities have developed beyond those described in the book. Users familiar with SuperCollider should have no concerns - the Cocoa and Swing GUIs are still supported while the Qt graphics capabilities are integrated into SuperCollider's basic design. You can learn what GUI kits are present on your system by evaluating the GUI.schemes command in your favorite SuperCollider-savvy editor. My system returns this information :

    IdentityDictionary[ (swing -> class SwingGUI), (qt -> class QtGUI), (colpen -> class ColPenGUI) ]

which tells me that I have Swing and Qt as GUI view options. The dictionary also lists a specialized GUI class called ColPen that appears to be a component in the wslib quark but I've done nothing with it yet. The SuperCollider documentation indicates that it is also possible to construct GUIs from Emacs graphics widgets, though again I haven't yet experimented with that capability.

SuperCollider's GUI elements are components for constructing project-specific GUIs, i.e. you won't find a nice general-purpose SuperCollider front-end complete with knobs and sliders and other graphic elements. Typically you'll build your own GUI for your specific purposes, but if you need a starting point you can find one in the existing examples of project GUIs. They range from simple UIs with a few buttons and sliders to complex arrangements of controls in multiple windows, complete with colorization, text entry and number boxes, file selectors, waveform viewers, and other cool fancy graphics.

I promised to provide a code example that creates a GUI for controlling the Task previously seen in the Notes On Notes section. Here's the code, but you'll need to remove the .play command from the Task before the UI will work correctly :

    w = Window.new("A Task", Rect(400, 400, 200, 30)).front;
    w.view.decorator = FlowLayout(w.view.bounds);
    Button.new(w, Rect(0, 0, 100, 20)).states_([["Play/Resume", Color.black, Color.clear]])
      .action_({ t.resume(0);});
    Button.new(w, Rect(0, 0, 40, 20)).states_([["Pause", Color.black, Color.clear]])
      .action_({ t.pause;});
    Button.new(w, Rect(0, 0, 40, 20)).states_([["Finish", Color.black, Color.clear]])
      .action_({
        t.stop;
        x.release(0.1);
        w.close;
    });

Figure 3 shows off the results. It's not much to look at, but its code points to greater possibilities. And as we hoped, our composer friend is now much more interested in SuperCollider. She sees that she has complete control of the logic behind the buttons, something not possible with her commercial software, and her imagination has begun to process the implications of our little example.

photo of a task GUI

Figure 3. A GUI for a Task.

New users should read the Help system's Introduction To GUI, a guide to writing code for basic and advanced GUI construction. Consider it required reading if you plan on making your own GUIs for your projects. Some SuperCollider quarks include custom GUI components that are useful when considering your own interface designs. Interested users should look into the ixiViews, dewdrop_lib, crucial_lib, Hadron, and AutoGui quarks for some well-designed UIs. See also the Help files for the EZ-GUI classes, a handy set of graphic controls for fast interface development.

Outro, Part 2

Gotta go now, but I'll continue exploring SuperCollider's advanced features when I return. In the meanwhile you can download the latest official release - it may be up to 3.4.4 by now - or retrieve and build the source code for the unreleased version 3.5. Have fun, and I'll see you in a couple weeks.
 

Load Disqus comments