SuperCollider AU, Part 2: Creating Our First Plug-In

If you worked your way here through Part 1, you now have SuperCollider and Xcode installed on your system, and you also have a working copy of the [Download not found] in your default Plug-Ins folder (do make sure you have the Xcode command line tools installed as well — depending on which version of Xcode you’re using, this may require a separate download).

You should also, at this point, have a pretty good high-level grip on how the various entities involved — Apple’s Core Audio and Audio Unit APIs, SuperCollider, SuperColliderAU and the AudioUnitBuilder quark — join forces to make some real magic happen.

Next up? We need to install AudioUnitBuilder.

It would be a good idea at this point for you to work through a few of the ‘Getting-Started’ tutorials that come with SuperCollider, to get your bearings with the basics of operation – starting and stopping the servers, compiling blocks of code, and so forth. Under the SuperCollider ‘Help’ menu, select ‘Browse Documentation’ and hit the ‘Tutorials link’ in the resulting window.

Install the AudioUnitBuilder Quark

‘Quarks’ are extensions to the SuperCollider environment — read: plug-ins — which are developed and distributed using a built-in packaging system. A repository of all currently available quarks is maintained by the SuperCollider development team and one of these quarks is AudioUnitBuilder, which we described briefly in Part 1.

Installation is simple, the only prerequisite being that you need to have a copy of the Quarks repository sitting on your system. Getting the repository — and activating AudioUnitBuilder — is a snap:

  • Launch SuperCollider, open a fresh document (Cmd-N), type the command ‘Quarks.updateDirectory’ and, with your cursor still on the same line, hit ENTER (not RETURN — these two keys are distinct in SuperCollider!);

This will launch a Terminal window, execute a series of Subversion commands and place a copy of the Quarks repository in ~/Library/Application Support/SuperCollider/quarks/DIRECTORY.

Note: if you get a Terminal error saying Subversion is not available, it probably means you don’t have the Xcode command line tools installed.

  • Next, type the command ‘Quarks.install(“AudioUnitBuilder”)’ and again hit ENTER;

After a few seconds, you should see a message in the Post window that reads “AudioUnitBuilder installed”.

  • Recompile SuperCollider using Lang -> Compile Library (or Cmd-K).

That’s it! If you browse over to ~/Library/Application Support/SuperCollider/quarks you’ll find a new subfolder called ‘AudioUnitBuilder’ which contains source code (‘AudioUnitBuilder.sc’), a help file (‘AudioUnitBuilder.html’), a resource file (‘SuperColliderAU.r’) and a pair of example plug-ins.

Take the time now to read through the help file. When you’re done, keep the AudioUnitBuilder folder open – we’ll be working with some of the other files momentarily.

By the way, you can access the Quarks Help file at any time by typing Cmd-D to bring up the SuperCollider help system, and then running a search for ‘Quarks’ from the Quick Lookup field.

Modify AudioUnitBuilder To Work With Lion and Mountain Lion

Recent updates to Xcode and SuperCollider have made things a little bumpy for AudioUnitBuilder.

How so? Both Xcode (as of version 4.3) and SuperCollider (as of 3.5) now come packaged as self-contained application bundles (in contrast to their former incarnations as directories of applications and files.) And that means that any resource files required by the applications have been moved into the application bundles themselves.

The upshot: any file paths used by AudioUnitBuilder to point to those resources – previously located in SuperCollider’s pre-3.5 application directory and Xcode’s old /Developer directory – are now invalid.

Let’s fix.

Launch SuperCollider and open the AudioUnitBuilder.sc file. There are two path adjustments we need to make: one for Xcode’s Rez executable (which is required for AudioUnitBuilder to work its magic) and one for SuperCollider’s plug-ins folder (which the Builder needs to copy from when creating custom components).

At the very top of AudioUnitBuilder.sc, find the following line of code:

classvar <>rez="/Developer/Tools/Rez", <>unitDict, <>displayDict;

And change it to:

classvar <>rez="/Applications/Xcode.app/Contents/Developer/Tools/Rez", 
<>unitDict, <>displayDict;

Then scroll down to the copyPlugins method (3 methods from the bottom) and change the grep command:

cmd = "grep  -e _"++ugens.asSequenceableCollection.join("_ -e _") + 
"_ plugins/*.scx";

to:

cmd = "grep  -e _"++ugens.asSequenceableCollection.join("_ -e _") 
+ "_ SuperCollider.app/Contents/Resources/plugins/*.scx";

Save, close the file and recompile the SuperCollider library (Cmd-K).

And that’ll do it. Next, let’s get our feet wet by having a look at one of those example files.

Exploring One of the Example Files

Open the Examples folder (inside the AudioUnitBuilder directory), right-click the ‘fedDelay’ file and choose ‘Open with SuperCollider’.

The first thing that may strike you is the size of the file: it’s quite small, only about 40 lines total. Here are some key points to take note of:

  • The entire file is bracketed by a pair of parentheses:
    (
    var ...;
    ....
    builder.makeInstall;
    )
  • The file begins by declaring six variables:
    var name, func, specs, componentType, componentSubtype, builder;

The first five variables will identify the plug-in and define its functionality; they will all be passed to AudioUnitBuilder – using the sixth variable – when we build the plug-in. Except for the last two lines of the file, everything that follows is dedicated to defining what goes into those variables:

  • name holds a quoted character string representing the name of the plug-in:
    name = "fedDelay";
  • componentType – we’re deliberately skipping down a bit here – gets the appropriate 4-character Type code required by Apple for this particular plug-in type, as discussed in Part 1. In this case, the code is ‘aufx’ to denote an Effects unit:
    componentType = \aufx;

Note the leading backslash and lack of quotes: this is not a character string, it is a constant.

  • componentSubtype gets a unique 4-character code which will identify this specific plug-in to the host and system (and this time, the code is a quoted string):
    componentSubtype = "FEDL";

In Part 1 we described how this subtype code is provided by the developer. In other words: you simply make something up that will uniquely identify the plug-in to the system. There are some rules, of course: (1) the code must be unique within the collection of SCAU-manufactured plug-ins on your system; (2) you may only use alpha letters, no numbers or special characters are allowed; and (3) the code must be 4 characters in length – no more, no less.

  • specs is assigned an array — i.e. a list of comma separated values surrounded by opening and closing brackets — preceded by an opening hash symbol (‘#’):
    specs =  #[
    	[0, 2 , \Linear, 0.1,\Seconds ] ,
    	[0, 0.5 , \Linear, 0.1,\LinearGain ] ,
    	[0, 2 , \Linear, 0.1,\Seconds ] ,
    	[0, 0.5 , \Linear, 0.1,\LinearGain ] ,
    	[0, 2 , \Linear, 0.1,\Seconds ] ,
    	[0, 0.5 , \Linear, 0.1,\LinearGain ] ,
    	[0, 2 , \Linear, 0.1,\Seconds ] ,
    	[0, 0.5 , \Linear, 0.1,\LinearGain ]
    ];

Notice that each item in the array is itself an array (i.e., another comma-separated list of values surrounded by brackets). The items in this specs array correspond to our function arguments – the real-time controls we will present to users of the plug-in – and are listed in the same order here as they will be at the top of our yet-to-be-defined DSP function (more on this below).

The recipe for each specs array item is: minimum value, maximum value, type of display, default value (which needs to match whatever default values we set in the DSP function below) and display units. Note that the final item in each array, including the enclosing parent array, is not followed by a comma.

Also note the use of indents and line breaks to keep the whole thing nice and readable to human eyes. This is optional, of course, but you’ll want to follow the example in your own plug-ins.

  • func — we’ve saved the most complex for (almost) last — defines the plug-in’s DSP function.

Now, this particular plug-in (fedDelay) is a four-tap delay unit — not exactly the simplest effect to tackle first — so let’s skim over the actual DSP algorithm for now and focus on the structure of the DSP processing graph that’s being built here.

At the top of the function we have a comma-separated list of terms surrounded by a pair of pipe (‘|’) characters:

| tap1Time=0.1,  tap1Feedback=0.1,
  tap2Time=0.1,  tap2Feedback=0.1,
  tap3Time=0.1,  tap3Feedback=0.1,
  tap4Time=0.1,  tap4Feedback=0.1 |

The pipes tell us these terms are arguments to be used in the DSP function: they represent the real-time controls the plug-in interface will present to the user, and the values set by those UI controls are the values that will be fed — at any given instance — into the DSP algorithm.

At this stage the developer is stating that the plug-in will have 8 controls: 4 for delay time (1 for each delay tap) and 4 for feedback level. Note each argument is also assigned a default value, reflecting the initial value the control will display when the plug-in launches.

As noted earlier, these arguments should map to the entries in the specs array, and the default values set there need to match the default values assigned here.

Next, we have a series of declared variables (indicated by use of the keyword ‘var’):

var tap1, tap2, tap3, tap4;
var local, in, amp, feedBackMix, tapArray;
var maxDelay = 3;

These variables are internal to the DSP function and will be used to hold elements of the signal path as it is being built.

The next section builds that signal path. Remember our discussion of audio streams in Part 1? First, of course, we need an input for taking in audio:

in = Mix.new(AudioIn.ar([1,2]));

Next, we take that input and feed it into whatever DSP is being set up:

local = LocalIn.ar(4);
feedBackMix = Mix.new(local);

tap1 = AllpassN.ar((feedBackMix * tap1Feedback) +in*(1-tap1Feedback),
         maxDelay, tap1Time,  0.2);
tap2 = AllpassN.ar((feedBackMix * tap2Feedback) +in*(1-tap2Feedback),
         maxDelay, tap2Time, 0.2);
tap3 = AllpassN.ar((feedBackMix * tap3Feedback) +in*(1-tap3Feedback),
         maxDelay, tap3Time, 0.2);
tap4 = AllpassN.ar((feedBackMix * tap4Feedback) +in*(1-tap4Feedback),
         maxDelay, tap4Time,  0.2);

tapArray = [ tap1, tap2, tap3, tap4 ];

LocalOut.ar(tapArray);

Notice how the ‘in’ variable — which contains our incoming audio — figures into the delay signal calculations?

And finally, the processed audio is passed (in this case, through a Pan UGen for some spatial effects) to the output:

Out.ar(0, Pan2.ar(Mix.new(tapArray)));

We’ve glossed over a fair amount of detail here, so here’s the gist of what’s going on:

(1) we take in stereo input on channels 1 and 2 (denoted by the ‘[1, 2]’ array passed to AudioIn), feed it to a Mix UGen (which does like it says) and store the result in the ‘in’ variable;

(2) we next set up an internal bus of 4 channels (‘LocalIn.ar(4)’) for the feedback mix;

(3) ‘in’ (our input) is processed as part of the delay calculations and the result is passed into the four ‘tap’ variables. Note the use of our real-time control arguments (tap1Time, tap1Feedback, etc) — these represent values that will be passed in from the user interface controls;

(4) the tap variables are placed into an array (‘tapArray’) which is fed both to the internal 4-channel bus (LocalOut.ar, for the feedback mix) and to output (into another Mix UGen, through the afore-mentioned Pan UGen and, finally, to Out.ar).

The bus channel thing can be a little confusing: first off, it is SuperCollider convention that bus channels begin with channel 0. In the case of inputs, those channels need to be designated explicitly (how else would SuperCollider know how many inputs you’re feeding?). However, in the case of outputs, only the starting channel is specified (because the Out UGen figures out how many channels are required for output, based on whatever it is that’s being output.

Now, you may be scratching your head because AudioIn, in this example, specifies channels 1 and 2 (for stereo input) rather than 0 and 1, as you might expect from the above description. That’s because AudioIn designates input channels as starting with channel 1, not channel 0. But AudioIn, in the time since the fedDelay example was written, has been deprecated and replaced with a newer input UGen, SoundIn, which follows SC convention and defines input channels as starting with channel 0 (we’ll use SoundIn when we build our own example AU, below).

Put more succinctly, if you were to writing fedDelay today you would replace AudioIn[1,2] with SoundIn[0,1]. Got that?

The .ar suffix on some of the UGens indicates ‘audio rate’ (as opposed to .kr, for ‘control rate’). Of course, you knew this already from going through the Getting-Started tutorials.

And that’s about all we need to say here on func.

  • The last two lines in the file are where our custom audio unit is created:
  • builder =
    AudioUnitBuilder.new(name, componentSubtype, func, specs, componentType);
    
    builder.makeInstall;

We take everything that’s just been defined, pass it to the AudioUnitBuilder class’s ‘new’ method (which returns a new AudioUnitBuilder object, built to our specifications) and place the resulting object into a variable called ‘builder’ — our sixth variable defined at the top of the file.

We then tell ‘builder’ (aka our new AudioUnitBuilder object) to run its makeInstall method, which (1) calls Rez, (2) copies any required SC UGens from the SuperColliderAU component’s internal plug-ins folder, (3) produces a finished component and (4) places it in the default plug-ins folder (~/Library/Audio/Plug-Ins/Components).

I highly recommend, as an additional exercise, that you take the time to trace the sequence of execution within the AudioUnitBuilder source code – it will give you a feel for what happens when that last line of code in the template file is run. Start with the call from the file we just created — AudioBuilder.new (hint: the dot syntax indicates we’re calling AudioBuilder’s ‘new’ method) — and try to follow the thread from there.

Compile the Plug-In

Compiling the plug-in in SuperCollider couldn’t be simpler: just select everything between the opening and closing parentheses — or double-click just to the right of the opening paren and let SuperCollider do the selecting for you — then hit ENTER (not RETURN).

The Post window should respond with this message:

Created ~/Library/Audio/Plug-Ins/Components/fedDelay.component
an AudioUnitBuilder

Now take a look inside ~/Library/Audio/Plug-Ins/Components where you should find a copy of the new plug-in. Easy-peezy, yah?

Next we’ll want to validate our new plug-in, which we do using an Apple-supplied tool called auval.

Validate the Plug-in

auval is a command line tool designed for validating audio unit components. Documentation for auval can be found on the Apple Developer site in Technical Note TN2204.

Note ‘validate’ here means verifying that a component conforms to the semantics of the Audio Unit API. In other words, auval does not test a plug-in’s functionality, it simply confirms that the plug-in meets Apple standards for ‘playing nice’ with the OS and with Audio Unit-supporting host applications.

Nonetheless, passing auval‘s battery of tests is an important step in the development process: if an audio unit doesn’t validate, chances are it will be rejected by — or may even crash — your host application.

So, let’s validate. Open Terminal and, at the prompt, type:

auval -h

then hit RETURN (or ENTER).

The ‘-h’ switch is for ‘help’ and so auval will respond by displaying a full set of instructions describing its usage, along with a list of available options.

Our purpose here is to validate a single, specific plug-in (fedDelay), not every audio unit sitting on our system. So we’re going to use the -v command, which (the help file tells us) takes three arguments: TYPE (type), SUBT (subtype) and MANU (manufacturer), in that order. Plug-ins created with SuperColliderAU will always bear the manufacturer code “SCAU”. The Type and Subtype we can grab from the template file we just compiled.

And so, again at the prompt, type:

auval -v aufx FEDL SCAU

and hit RETURN (or ENTER).

auval will do its thing and drop you back at the command prompt when it’s done. If you’re curious, you can scroll back up the Terminal window to see exactly what was tested. But the main thing we’re interested in is the final line deposited by auval, which hopefully reads:

* * PASS
--------------------------------------------------
AU VALIDATION SUCCEEDED
--------------------------------------------------

Use the Plug-in!

Ok, let’s give it a run. Open your AU-supporting DAW of choice, create an audio track, find the SuperColliderAU collection among your list of AUs (‘SuperColliderAU’ is the ‘manufacturer’ name used by AudioUnitBuilder), pull up fedDelay as an insert, hit ‘play’ and start messing around with the controls.

Ableton Live Users Take Note: if you find that audio is breaking up when you insert the plug-in, open Live’s Preferences pane, hit the ‘CPU’ tab and change ‘Plug-in Buffer Size’ from ‘As Audio Buffer’ to a buffer size appropriate for your system. As near as I can tell, this only occurs with SuperColliderAU plug-ins running in relatively recent editions of Live (approx. version 8.3 and up) – and only on OS X 10.7 (strangely, the problem disappears on Mountain Lion). Whatever. Altering the buffer size seems to do the trick.

Here’s what my copy of fedDelay looks like in Logic:

SuperColliderAU Plug-In Running In Logic Pro

And here it is in Ableton Live, complete with assignable controls:

SuperColliderAU Plug-In Running in Ableton Live

So: is this not awesomeness?

C’mon, let’s do one from scratch.

Create Our First Custom Plug-in

Since this is our first custom plug-in, let’s keep things simple and create a basic low pass filter with a single control for adjusting the cutoff frequency.

First, of course, we need to give our plug-in a name. I’m gonna stick with our ‘give a man a fish…’ theme from Part 1 and call mine geFilter (yes, here at Mojo Lama we like to inject a little humor into our audio effects whenever we can.) Feel free to call yours whatever you like.

So let’s begin by making of a copy of the fedDelay file, stripping out the values for name, func, specs, componentType and componentSubtype (’cause we’re gonna fill those in with our own stuff) and saving it under the new name. Then, assign the name — as a quoted character string — to the name variable. Here’s my entry:

name = "geFilter";

Next, we’ll start building the DSP function. We’ll do this step-by-step, so start by sketching out an empty function and assigning it to the func variable, like so:

func = { 

};

geFilter, we’ve decided, has a single user control for the filter’s cutoff frequency. So, let’s set up an argument for that control and give it a default value of, oh, 15,000 Hz:

func = {
    | cutOff = 15000 | // our single control
};

Next, we’ll define a pair of variables, one to hold the input UGen and the other to hold the filter itself:

func = {
    | cutOff = 15000 | // our single control
    var in, filter; // declare our variables
};

To the ‘in’ variable we assign a SoundIn UGen set up for stereo input on the first two channels.

func = {
    | cutOff = 15000 | // our single control
    var in, filter; // declare our variables
    in = SoundIn.ar([0,1]); // get our audio input
};

Next we assign an LPF UGen to our ‘filter’ variable. Note the construction here. LPF expects, at the very least, two parameters: one for input and one for cutoff frequency. How do we know this? Type ‘LPF’ into the SuperCollider help window and know all.

For input we give LPF our ‘in’ variable, and for cutoff frequency we give it whatever value is coming in from our cutoff control: 15,000Hz when the plug loads, and anything within the minimum/maximum range we’re going to set in specs, once the user starts moving the slider.

We’ll also feed LPF a mul: parameter — mul scales the UGen’s output, so think ‘gain’ here — and set it to 0.8 to give ourselves a little bit of headroom (’cause we don’t want our signal going above 1.0):

func = {
    | cutOff = 15000 | // our single control
    var in, filter; // declare our variables
    in = SoundIn.ar([0,1]); // get our audio input
    filter = LPF.ar(in, cutOff, mul: 0.8); // define our filter
};

Finally, we take ‘filter’ – which is really just a reference to our LPF UGen (which in turn contains a reference to our SoundIn UGen) – and pass it to our output — an Out UGen:

func = {
    | cutOff = 15000 | // our single control
    var in, filter; // declare our variables
    in = SoundIn.ar([0,1]); // get our audio input
    filter = LPF.ar(in, cutOff, mul: 0.8); // define our filter
    Out.ar(0, filter); // create our output
};

Notice how the variables act as placeholders. We could have gotten by without using variables here, by simply putting everything straight into the Out.ar parameter list, like so:

Out.ar(0, LPF.ar(SoundIn.ar([0,1]), cutOff, mul: 0.8));

But by putting each element into its own little variable placeholder we bring an added level of clarity to our thinking and to our code.

Next up is specs. Recall the ‘recipe’ format we discussed earlier: min, max, display style, default value and units (see the AudioUnitBuilder help file for a summary of available values). Recall also that specs is an array of arrays (in this case, it’s an array containing a single array). With that in mind, here’s our entry for specs:

specs = #[ [50, 22000 , \Logarithmic, 15000,\Hertz ] ];

Finally, we set the componentType and componentSubtype. The type is always going to be \aufx. The subtype is up to you, but must be 4 characters — no numbers — and must be unique among your installed SuperColliderAU plug-ins.

componentType = \aufx;
componentSubtype = "GFLT";

The last two lines in the file remain as they were in fedDelay:

builder =
AudioUnitBuilder.new(name, componentSubtype, func, specs, componentType);
builder.makeInstall;

Save and compile as we did with the example file: select everything between the opening and closing parentheses and hit ENTER.

Now check your default plug-ins folder (~Library/Audio/Plug-Ins/Components) where you should find a new custom plug-in, with the name you’ve given it, waiting for its first test run.

If you don’t, or if SuperCollider threw an error to the Post window — or let’s say the component is there but the file size is 4KB (a sure sign of something amiss) — check your work for typos. Something as simple as a missing ‘;’ or ‘(’ is enough to derail the build process, and this will often occur silently.

Should you find you need to make a correction and recompile the plug-in, be sure to remove the existing component from ~/Library/Audio/Plug-Ins/Components first. The recompiled component will not overwrite the existing one: you need to first remove the old one, then generate the new one.

Wrap-up

So that should give you enough juice to get started. Can you see what a wonderfully useful tool SuperColliderAU can be for the rapid prototyping of audio DSP ideas? Or for quickly cobbling together that effect you’re hearing in your head, in time for your next session or live set?

Where to go next? The first thing I suggest is subscribing to the SuperCollider forums (there are two of them: one for users and the other for developers — I suggest subscribing to both). The SC community is diverse and the forums very active. If (or rather, when) you run into a problem or have a question, this is where you’re likely to get the answer.

Then roll up your sleeves and dive headlong into SuperCollider-land: start trawling through the documentation, familiarize yourself with the UGens and their capabilities, poke around some of the resources over at SourceForge’s SuperCollider sub-site, get yourself a copy of The SuperCollider Book, ask questions and, above all, experiment.

But stick around, we’ll do a bit more with SuperColliderAU, and next time maybe we’ll try something a little bit more ambitious. See you then.

Post to Twitter

6 thoughts on “SuperCollider AU, Part 2: Creating Our First Plug-In

  1. Hi,

    I now worked my way through Part2 and I have to say your tutorial is excellent, with the right degree of detail to be able to follow each stepp and clear explanations where needed (also suitable for the less experienced programmer.). All steps described worked right away. I appreciate very much the work you put into this tutorial!
    It is only in the last step (“auval”) that I am stuck somehow and I don’t know how to proceed. Hopefully you can point me in the right direction. In my case “auval” terminates with “AU VALIDATION SUCCEEDED”
    BUT I also get some errors during the validation process saying:

    *** ERROR: SynthDef fedDelay not found
    FAILURE /s_new SynthDef not found
    PASS
    Bad Max Frames – Render should fail
    PASS

    I can finally load the plug-in in Logic and also see the GUI and change the sliders but there is no effect on the sound. Please help! Would love to create my own AU plug-ins.
    By the way I am using Lion 10.7.4 and SC 3.5.5.
    Thanks in advance.

  2. Hi Amir,

    Indeed, the latest version of SuperCollider (3.5.5) appears to have broken either SuperColliderAU or the AU Builder (I suspect the former, but I’ll need to look further into it).

    In the meantime, I suggest downloading an earlier version of SuperCollider… 3.5.1 (link here: http://sourceforge.net/projects/supercollider/files/Mac%20OS%20X/3.5.1/) seems to work just fine…

    FWIW, SuperCollider has received (and continues to receive) some pretty significant upgrades since 3.5, so I’m not too surprised to see something like this… I’ll post an update first chance I get.

    Thanks for reading!

    Abel

  3. Hi Abel,
    Thank you very much for your fast reply and for pointing me in the right direction. Plug-ins created with SC 3.5.1 and SuperColliderAU finally pass the validation process and I am able to load them in Logic9 and everything works great!
    Thanks again for that great tutorial. I will definitely share it.
    Kind regards,
    Amir

  4. Hey, thanks for your great article. I too, like Amir, experience the SynthDef not found error during validation, and so my plugin does nothing. The SynthDef file inside the component is definitely there. Perhaps there was a big change to the SynthDef specification? since the original SuperColliderAU was compiled? I’m running 10.8 and Supercollider 3.6, which may be part of the problem. Have you run into any new info, especially concerning making AU plugins with the latest version of SuperCollider?

  5. Hi Zach,

    To my knowledge, all recent binaries of Supercollider (everything after 3.5.1) are provided as 64bit builds, whereas the component is still 32bit… the result: generated plugins show up in your host application (and contain a valid SynthDef file) but do absolutely nothing…

    Yes, SCAU is badly in need of an update!

    Unfortunately, I have no new info concerning when we might actually see one (other than the fact that an update is apparently in the works)…

    In the meantime, your options are: (a) build the latest version of Supercollider as 32bit from source (instructions for compiling a 32bit build are included with the source download); or (b) install an older 32bit binary of Supercollider (see the 3.5.1 link in the comments above)…

    I would also encourage you to express your interest in SupercolliderAU on the Supercollider forums… the more requests there are, the more likely the devs will take notice…

    Best,
    Abel

  6. Hi,
    I updated the repository but when i wanted to install “AudioUnitBuilder” i get the folloving error from post window:
    [code]
    export LANG=” && cd /Users/py/Library/Application\ Support/SuperCollider/quarks && /usr/bin/svn update DIRECTORY 2>&1

    a QuarkSVNRepository
    ERROR: Class not defined.
    in file ‘selected text’
    line 1 char 34:

    Quarks.install(“AudioUnitBuilder”)

    ———————————–
    nil
    [/code]

    thanks in advance.
    Alper

Comments are closed.