ChucK : Extend

version: 1.5.x.x (chai)

ChucK provides a number of options for extending its standard library of functions, classes, and unit generators. The easiest way is through public classes, discussed in the ChucK language specification. Going futher, you can create new unit generators in ChucK code using Chugens and Chugraphs (previously "Chubgraphs"). Lastly, ChuGins allow near limitless possibilities for expansion of ChucK’s capabilities, but require programming in C++ (using the same interface as ChucK's native unit generators). This section describes the use-cases and methods for using these features.

For more information, see the links below, and/or read the ICMC paper Chugens, Chugraphs, ChuGins: 3 Tiers for Extending ChucK (pdf).



<= Chugens =>

Sample-rate processor unit generator in ChucK code

show me how!

<= Chugraphs =>

Combine a network of existing ugens into a single re-usable ugen

show me how!

<= ChuGins =>

Native-code audio processor and general-purpose extension (not for the faint of heart!). Can also be used to incorporate existing C/C++ code and libraries

show me how!

Chugens

Chugens (pronounced “chyoo-jens”) facilitate rapid prototyping of audio synthesis and processing algorithms. Chugens also provide a basic framework for extending ChucK’s built-in audio processing functionality. Using the Chugen system, a programmer can implement sample-rate audio algorithms within the ChucK development environment, utilizing the full array of programming facilities provided by ChucK. These processing units can be naturally integrated into standard ChucK programs, even in the same script file, providing seamless control of audio-rate processing, control-rate manipulation, and higher-level compositional organization.

A Chugen is created first by subclassing the built-in Chugen class. This subclass is required to implement a tick function, which accepts a single float argument (the input sample) and returns a single float (the output sample). The tick function is fundamental to a ChucK’s audio architecture; to produce a continuous audio stream, ChucK produces 44100 or 48000 samples per second, and each UGen in your program has its own tick function which generates its contribution to the current sample.

The following code uses a Chugen to synthesize a sinusoid using the cosine function, Math.cos.

class MyCosine extends Chugen
{
    0 => int p;
    440 => float f;
    second/samp => float SRATE;
    
    fun float tick(float in)
    {
        return Math.cos(p++*2*pi*f/SRATE);
    }
}

Note that a cosine wave is a sine wave that is 90° “behind” (out of phase with) a sine wave—in most cases it will sound exactly like a sine wave.

A Chugen, once defined, may then be integrated into audio graphs like any standard ChucK UGen.

MyCosine cos => NRev reverb => dac;

Since the tick function is a standard ChucK class member function, it can be as simple or as elaborate as required. Standard library calls, file I/O, multiprocessing (using spork), and other general ChucK programming structures can be integrated into the tick function and supporting code. In the case of an audio synthesizer that does not process an existing signal, the input sample may be ignored. For performance reasons, it’s important to consider that the tick function will be called for every sample of audio, so simple tick functions will typically perform better. Moreover, the intrinsic overhead of ChucK’s VM architecture will cause Chugens to underperform compared to a native C/C++ implementation.

Since Chugens are only a type of ChucK class, they may define functions to provide structured access to whichever parameters they wish to expose to the programmer.

class MyCosine extends Chugen
{
    0 => int p;
    440 => float freq;
    second/samp => float SRATE;
    
    fun void setFreq(float theFreq)
    {
        theFreq => freq;
    }
    
    fun float tick(float in)
    {
        return Math.cos(p++*2*pi*freq/SRATE);
    }
}

Here, we have added a setFreq function, which allows us to set the frequency of the cosine wave. As a general rule, you should always provide a function to set or get parameters from your Chugens, instead of allowing direct manipulation of member variables within the class. Providing a function to get and set a Chugen parameter indicates which parameters make sense to manipulate, and which ones are only important internally; messing with internal properties of any class is almost always a bad idea.

Lastly, we can make a public Chugen, just like normal classes, using the public keyword.

public class MyCosine extends Chugen

By making a Chugen public, we can use it in other ChucK scripts running in the same virtual machine.

Chugraphs

Chugraphs (pronounced “chuh-graphs”) provide a way to construct new unit generators by composition, arranging multiple existing UGens into a single unit. In this way, common arrangements of existing UGens can be defined and instantiated. Chugraph parameters can be exposed in a structured manner via class member functions.

A Chugraph is defined by extending the Chugraph class, which has built-in mem- ber variables named inlet and outlet. inlet is a UGen that represents the input signal to the Chugraph, and outlet is the output signal. The Chugraph’s internal audio processing graph is created by spanning a sequence of UGens between inlet and outlet. The following Chugraph implements a basic feedback echo processor:

class Feedback extends Chugraph
{
    inlet => Gain dry => outlet;
    dry => Delay delay => outlet;
    delay => Gain feedback => delay;
    0.8 => feedback.gain;
    1::second => delay.max => delay.delay;
}

(Chugraphs that don’t need to process an input signal, such as audio synthesis algorithms, may omit the connection from inlet.)

Compared to Chugens, Chugraphs have significant performance advantages, as audio-rate processing still occurs in the native machine code underlying its component UGens. However Chugraphs are limited to audio algorithms that can be expressed as combinations of existing UGens. Implementing, for example, intricate mathematical formulae or conditional logic in the form of a UGen graph is possible but fraught with hazard.

Chugraphs can be included in your audio patch like any other UGen. Like with Chugens, Chugraphs can be declared as public to be used in other ChucK scripts, and can define member functions to provide control over any parameters that are available.

For a complete example of creating and using Chugraphs, check out chugraph.ck.

ChuGins

ChuGins (pronounced “chug-ins”) allow near limitless possibilities for expansion of ChucK’s capabilities. A ChuGin is a distributable dynamic library, typically written in C or C++ compiled to native machine code, which ChucK can load at runtime. When loaded, the ChuGin defines one or more classes that are then made available to ChucK programs. These classes may define new UGens or provide general programming functionality beyond that built into ChucK. Since these classes are normal ChucK classes implemented with native code, member functions and variables can be used to provide an interface to control parameters.

ChuGins are best suited for audio algorithms that are reasonably well understood and stand to gain from the performance of compiled machine code. The write-compile-run development cycle and C/C++-based programming mandated by ChuGins make implementation of audio processors require more effort than the Chugraph or Chugen approaches. For UGens you intend to use over an extended period of time, the effort to implement a ChuGin will quickly pay off in the form of lower CPU usage.

An additional advantage of ChuGins is that they may provide functionality far outside the intrinsic capabilities of ChucK. Complex C/C++-based synthesis packages can be imported wholesale into ChucK, opening up an abundance of sonic possibilities. ChuGins have been implemented to bring audio processing programs from the Faust programming language into ChucK, for example (see Faust and faust2ck). Similarly, the SoundFont renderer FluidSynth has been packaged as a ChuGin (fluidsynth.chug). This functionality is not limited to audio processing, as they may also be used to create general purpose programming libraries.

Before programming your own ChuGins, you may wish to browse the GitHub repository of current ChuGins to get a feel for what is required: https://github.com/ccrma/chugins

If you're comfortable with writing C++/audio code and want to just dive in, fork or download the ChuGin repository and start hacking away at one of the simpler ChuGins. Also, the included Python script chuginate generates a C++ template and build files (makefile + Visual Studio project) for new ChuGins. For those who prefer a more in-depth tutorial, we are developing a guide presently and will update this page when it is ready.



chuck | ccrma | soundlab