Using Buses in SuperCollider

Control Rate vs Audio Rate

SC works with two internal signal types or rates. When something is used with the extension .ar, this refers to audio signals (audio rate), whereas .kr uses the control rate. For both rates, buses can be created.


Creating Buses

An audio bus with a single channel is created on the default server s with the following command:

~aBus = Bus.audio(s,1);

A control bus with a single channel is created on the default server s with the following command:

~cBus = Bus.control(s,1);

Bus Indices

The variable ~aBus is the client-side representation of the Bus. The server only knows it by its bus index. Bus indices are counted upwards and can be queried with the following command:

~aBus.index
~cBus.index

Monitoring Buses

Any bus can be monitored with the builtin scope with the following command. The first argument defines the number of buses to be shown, the second the index of the first buses:

s.scope(1,~aBus.index,rate:'audio')

There is a short version, which has limitations and does not specify the bus type:

~aBus.scope()

Control Buses

This simple sawtooth node will be used for showing how to use control buses. It has one argument freq, which affects the fundamental frequency and uses the first hardware output:

~osc  = {arg freq=100; Out.ar(0,Saw.ar(freq))}.play;

Mapping a Control Bus

The map() function of a node can connect a control bus, identified by its index, with a node parameter:

~osc.map(\freq,~cBus.index);

Setting a Control Bus

After mapping the bus, the synth stops its sound., since the control bus is still set to the default value 0. This can be visualized with the scope command. A simple and quick way for changing the control bus to a different value is the set() function of a node. It can be used for all arguments of the node which are internally used for control rates:

~cBus.set(50);

Multichannel Buses

Both control and audio rate buses can be created as multi channel buses. A scope will automatically show all channels. Individual channels can be mapped with an offset in relation to the index of the first channel. The setAt() function can be used for changing individual channel values:

~mBus = Bus.control(s,8);

~mBus.scope;

~osc.map(\freq,~mBus.index+3);

~mBus.setAt(3,150);

Patches and Subpatches in Pure Data

Arguments

The following examples are based on patches and additional files, called abstractions. To make them work, all involved patches need to be located in the same direction (by cloning the complete repository). Arguments are passed to objects after the name, separated by a white space. The patch arguments-help.pd shows this by creating an arguments object:

/images/basics/pd-arguments-1.png

Inside an abstraction, individual arguments can be accessed with the $ operator and their index. The loadbang is executed on the object's creation, thus printing both arguments on start. This is helpful for setting initial values in patches, as shown in arguments-help. Once created, it will print the arguments to the main Pd window:

/images/basics/pd-arguments-2.png

Subpatches

Subpatches can be very helpful for creating cleaner patches without addtional abstractions and files. To create a subpatch, use the object pd with an optional string argument for naming the subpatch. They can be used like abstractions but do not require an additional file.


Graph-on-Parent

When toggling Graph-on-Parent in an object's properties, it can expose GUI elements to its parent patch. This is a good way of cleaning your patch and showing only what is needed in a performance situation. It works for both abstractions and subpatches. The example patches.pd makes use of this to create a filter subpatch with controls. The left hand audio input of the suppatch is a fixed frequency sawtooth. The right hand control input sets the Q of the filter.

/images/basics/pd-patches-1.png

On the inside, the moog~ object is used. It is not part of PD vanilla and can be installed with the flatspace ggee extensions from Deken. The red rectangle marks the area visual in the parent patch. All GUI components inside this area will be visible:

/images/basics/pd-patches-2.png

Inlets and Outlets

The patch has two inlets - one in audio rate (inlet~) and one in control rate - and two outlets, also with audio rate (outlet~) and control rate. For inlets and outlets, their horizontal order determines their order in the object when patched from the parent. Changing them can mess up the complete patching.

Using OSC in Pure Data

Vanilla Only

Sending OSC

The default version of PD is referred to as Vanilla. OSC can be used in Puredata without further packages, by means of the ojects netsend, oscformat and oscparse. The patch osc-send-vailla.pd sends a message to port 6666 on the localhost (127.0.0.1). The message has the following structure and contains one float argument:

/oscillator/frequency/ [float]

/images/basics/pd-osc-send-vanilla.png

Receiving OSC

The corresponding receiver patch osc-receive-vanilla.pd listens on port 6666. Using the route object, the message is unwrapped until the single float argument can be processed by the number box:

/images/basics/pd-osc-receive-vanilla.png

Exercise

Send messages between the patches. If possible, use two computers and change the address in the send patch.

Using Externals

Dependencies

Sending OSC

The following example is based on additional externals. For using them, install the external mrpeach with the Deken tool inside Puredata: https://puredata.info/docs/Deken The send patch uses the hostname localhost instead of an IP address. The path /oscillator/frequency of the OSC message has been defined arbitrarily - it has to match between client and receiver. Before sending OSC messages, the connect message needs to be clicked.

/images/basics/pd-osc-send.png

Receiving OSC

Before receiving OSC messages, the udpreceive object needs to know which port to listen on. Messages are then unpacked and routed according to their path, using the routeOSC object.

/images/basics/pd-osc-receive.png

Exercise

Use both patches for a remote controlled oscillator. If possible, use two computers and change the address in the send patch.


References

  • Miller S. Puckette. Pure Data. In Proceedings of the International Computer Music Conference (ICMC). Thessaloniki, \\ Greece, 1997.
    [BibTeX▼]
  • Miller S. Puckette. The patcher. In Proceedings of the International Computer Music Conference (ICMC). Computer Music Association, 1988.
    [BibTeX▼]
  • More APIs

    There are many more APIs which can be used for real time or off line sonification. Several projects and meta sites list examples by category:


    NASA

    NASA offers a great variety of open APIs with data from astronomy: https://api.nasa.gov/



    Faust: Conditional Logic

    The select2() directive can be used as a switch condition with two cases, as shown in switch_example.dsp

    // switch_example.dsp
    //
    //
    // Henrik von Coler
    // 2020-05-28
    
    import("all.lib");
    
    // outputs 0 if x is greater 1
    // and 1 if x is below 0
    // 'l' is used as an implicit argument
    sel(l,x) = select2((x>=0), 0, 1);
    
    process = -0.1 : sel(2);
    

    Filter Characteristics and Parameters

    Filters have many applications in sound synthesis and signal processing. Their basic job is to shape the spectrum of a signal by emphasizing or supressing frequencies. They are the essential component in subtractive synthesis and their individual qualities are responsible for an instrument's distincive sound. Famous filter designs, like the Moog Ladder Filter, are thus standards in the design of analog and digital musical instruments.

    Filter Characteristics

    Regardless of the implementation details, both analog and digital filters can be categorized by their filter characteristics. These describe, which frequency components of the signal are passed through and which frequencies are rejected. This section describes the three most frequently used filer types.

    The central parameter for most filter types is the cutoff frequency $f_c$. Depending on the characteristic, the cutoff frequency is that frequency which separates passed from rejected frequencies.

    Lowpass

    The lowpass filter (LP) is the most frequently used characteristic in sound synthesis. It is used for the typical bass sounds known from analog and digital subtractive synthesis. With the right envelope settings, it creates the plucked sounds. An LP filter lets all frequencies below the cutoff frequency pass. $f_c$ is defined as that frequency where the gain of the filter is $-3\ \mathrm{dB}$, which is equivalent to $50\ \%$. The following plot shows the frequency-dependent gain of a lowpass with a cutoff at $100\ \mathrm{Hz}$.

    Highpass Filter

    The highpass (HP) filter is the opposite of the lowpass filter. It rejects low frequencies and lets high frequencies pass. The following plot shows the frequency-dependent gain of a highpass with a cutoff at $100\ \mathrm{Hz}$.

    Bandpass Filter

    The bandbass (BP) filter is a combination of lowpass and highpass. It lets frequencies between a lower cutoff frequency $f_{low}$ and an upper cutoff frequency $f_{up}$ pass. The BP filter can thus also be defined by its center frequency

    $f_{cent} = \frac{f_{up}+f_{low}}{2}$

    and the bandwith of the so called passband

    $b = f_{up}-f_{low}$.

    The following plot shows a bandpass with a center frequency of $f_{cent} = 100\ \mathrm{Hz}$ and a bandwidht of $50\ \mathrm{Hz}$.

    38
    

    Fourier Series: Square Wave

    Formula

    The square wave has a slightly faster decay towards higher partials. It can be found in spectra of wind instruments.

    • only odd harmonics
    • constant sign

    \(X(t) = \frac{4}{\pi} \sum\limits_{i=0}^{N} \frac{\sin(2 \pi (2i+1)ft)}{(2i + 1)}\)


    Interactive Example

    Pitch (Hz):

    Number of Harmonics:

    Output Gain:

    Time Domain:

    Frequency Domain:

    Like the sawtooth, the square wave shows the occurrence of ripples at the steep edges of the waveform. The higher the number of partials, the denser the ripples. This is referred to as the Gibbs phenomenon.

    Sampling & Aliasing: Sine Example

    In the following example, a sine wave's frequency can be changed with an upper limit of $10\ \mathrm{kHz}$. Depending on the sample frequency of the system running the browser, this will lead to aliasing, once the frequency passes the Nyquist frequency:

    Pitch (Hz):

    Output Gain:

    Time Domain:

    Frequency Domain:

    Sampling & Aliasing: Theory and Math