Faust: Sequential Composition

Sequential composition is used for passing signals directly from one block to another block. In Faust, this is done with the : operator. The following example illustrates this with a square wave signal, which is processed with a low pass filter:

text


The square wave has a fixed frequency of $50\ \mathrm{Hz}$. The lowpass filter has two arguments, the first being the filter order, the second the cutoff frequency, which is controlled with a horizontal slider. Both blocks are defined and subsequently connected in the process function with the : operator. The adjustable cutoff parameter is additionally smoothed with si.smoo to avoid clicks.

Load this example in the Faust online IDE for a quick start:

import("stdfaust.lib");

freq  = hslider("frequency",100, 10, 1000, 0.001);

sig  = os.square(50);
filt = fi.lowpass(5,freq);

process = sig:filt;

Faust: Quick Introduction

Faust is a functional audio programming language, developed at GRAME, Lyon. It is a community-driven, free open source project. Faust is specifically suited for quickly designing musical synthesis and processing software and compiling it for a large variety of targets. The language works well with physical models and features many components for different physical approaches.


Tools for Working with Faust

Faust offers a large toolbox for different levels of expertise. Downloads are found here:

https://faust.grame.fr/downloads/index.html


Faust IDE

The Faust IDE is the fastest way to develop and test .dsp code: https://faustide.grame.fr/


Faust Compiler

The Faust compiler is the center-piece of the Faust development tools. Faust code is written in *.dsp files, which are converted to C++ code and then compiled for the desired system. The Faust compiler can be called directly from the command line or by other programs, such as the IDE FaustWorks. When called from the command line, Faust is compiled to the desired target using a faust2* command, which actually calls a build script.

Depending on your operating system and build target, additional libraries or tools may be required. Targets of interest can be:

Linux

  • faust2alsaconsole : ALSA command line program

  • faust2alqt : ALSA application with Qt UI

  • faust2alsa : ALSA application with GTK UI

Plugins

  • faust2ladspa : LADSPA plug-in

  • faust2lv2 : LV2 plug-in

  • faust2faustvst : VST plug-in

  • faust2au : Audio Unit plugin

Music Programming Environments

  • faust2supercollider : SuperCollider external

  • faust2puredata : PureData external

  • faust2max6 : MaxMSP 6 (and later) external and patch

  • faust2csound : CSOUND Opcode

Jack

  • faust2jackconsole : JACK command line program

  • faust2jack : JACK application with GTK UI

  • faust2jaqt : JACK application with Qt UI

MAC / IOS

  • faust2ios : iOS app

  • faust2caqt : CoreAudio application with Qt UI

  • faust2caqtios : iOS app with Qt UI

PI $ Co

  • faust2rpialsaconsole : Raspberry Pi ALSA command line program

  • faust2bela : BELA program

Microcontroller

  • faust2esp32 : ESP32 board

  • faust2teensy

JUCE

  • faust2juce : JUCE Procects

  • faust2unity

    ... and more ...

Compiling the first example as a PD external would be:

$ faust2puredata sine.dsp

FaustWorks

FaustWorks is an integrated development environment for Faust. It includes an editor and manages compilation. However, the software has not been maintained in a while.


Faust Libraries

Faust comes with a large set of libraries: Faust Library Website

They can be included individually with the import(delays.lib) command. Most examples in this class import all standard libraries with the import("stdfaust.lib"); command.

Pierre Schaeffer & Musique Concrète

Symphonie pour un homme seul

With Symphonie pour un homme seul (1949–1950), Pierre Schaeffer and Pierre Henry took the first approaches to Musique Concrète to a new level, beyond the scope of simple studies. Although not a multichannel composition, the artificial reverberation used in this piece can be considered a spatial audio production technique 1:

1

Artificial reverberation was first used in popular music productions in the 1930s.


Pupitre d'espace

The 'pupitre d'espace' was an electromagnetic interface for live diffusion of Musique Concrète.

/images/spatial/pupitre.jpg

Pierre Schaeffer with the 'pupitre d'espace'.


References

2018

  • Christoph von Blumröder. Zur bedeutung der elektronik in karlheinz stockhausens œuvre / the significance of electronics in karlheinz stockhausen's work. Archiv für Musikwissenschaft, 75(3):166–178, 2018.
    [abstract▼] [details] [BibTeX▼]

2015

  • Martha Brech and Henrik von Coler. Aspects of space in Luigi Nono's Prometeo and the use of the Halaphon. In Martha Brech and Ralph Paland, editors, Compositions for Audible Space, Music and Sound Culture, pages 193–204. transctript, 2015.
    [details] [BibTeX▼]
  • Michael Gurevich. Interacting with Cage: realising classic electronic works with contemporary technologies. Organised Sound, 20:290–299, 12 2015. doi:10.1017/S1355771815000217.
    [details] [BibTeX▼]

2011

  • John Chowning. Turenas: the realization of a dream. In Proceedings of the 17th Journées d\rq Informatique Musicale. 2011.
    [details] [BibTeX▼]

2010

2008

  • Marco Böhlandt. “kontakte” – reflexionen naturwissenschaftlich-technischer innovationsprozesse in der frühen elektronischen musik karlheinz stockhausens (1952–1960). Berichte zur Wissenschaftsgeschichte, 31(3):226–248, 2008.
    [details] [BibTeX▼]
  • Jonas Braasch, Nils Peters, and Daniel Valente. A loudspeaker-based projection technique for spatial music applications using virtual microphone control. Computer Music Journal, 32:55–71, 09 2008.
    [details] [BibTeX▼]

Binaural Spatialization with SC-HOA

The SC-HOA library by Florian Grond is a feature-rich toolbox for working with Ambisonics and binaural synthesis in SuperCollider. Once installed, it is well documented inside the SC help files. Additional information and install instructions are part of the Git repository. This section gives a brief introduction into the solution used for the SPRAWL server.

Installing SC-HOA

The SC-HOA library is shipped as a so called Quark and it can be installed from inside SC. Besides a GUI-based way, a single command is enough to install the complete library with all objects and classes in the system's directories:

Quarks.install("https://github.com/florian-grond/SC-HOA")

Make sure to reboot the interpreter after installing the Quark. The external classes need to be compiled.

To find out where SC has installed your external, run:

Platform.userExtensionDir

Network Audio

OSI Model

The OSI Model groups different services, functions and applications of telecommunication systems into seven hierarchically arranged layers:

OSI Model

Layer

Name

Description

7

Application Layer

End user layer, HCI layer

6

Presentation Layer

data conversion, syntax

5

Session Layer

connection management, sockets

4

Transport Layer

end-to-end connections (TCP, UDP)

3

Network Layer

packet routing

2

Data Link Layer

data formats (bits to frames, MAC addresses)

1

Physical layer

bit stream transmission over medium/hardware (Ethernet, WiFi, ...)


Network based audio systems can be based on different layers. This affects their capabilities and application areas. A comprehensive list can be found here: comparison on Wikipedia


Layer 1 Solutions

Layer 1 solutions only rely on the hardware used in telecommunication systems and use their own routing mechanisms. As a consequence, they usually need specific routers and are often used for direct peer-to-peer connections. The most widespread solution is the open AES50 format, which is found in devices by Behringer and Midas.

Layer 2 Solutions

Layer 2 solutions use the standard Ethernet protocol for transmitting data. Standard routers and hardware can thus be used for routing. Among the well known formats are AVB and AES51, as well as several proprietary solutions.

Layer 3 Solutions

Layer 3 solutions feature an IP header in their packages. Example solutions are DANTE, AES67, RAVENNA and AVB.

Layer 4 Solutions

Some solutions are based on Layer 4 protocols like TCP or UDP 1. Since UDP is faster due to the missing handshake and error-correction. Although this makes it prone to package loss, it is the preferred method for achieving acceptable latency at the cost of dropouts, depending on the quality of the connection.

Examples for Layer 4 solutions can be found in the free and open software community, including NetJack2 2, Zita-njbridge 3 and JackTrip.


1

This needs more references, since it is not unambiguous on which layer they are working.

2

https://github.com/jackaudio/jackaudio.github.com/wiki/WalkThrough_User_NetJack2

3

http://kokkinizita.linuxaudio.org/linuxaudio/index.html

Using SSH for Remote Access

SSH (Secure Shell Protocol) is necessary when working with the server but can also be helpful for configuring the Access Points. For remote machines - like the SPRAWL Server - SSH can be used for command-line operations and command execution.

Connecting to an SSH Server

For connecting to a remote machine, it needs to run an SSH server. On the client side, an SSH connection can be established without additional installations from the terminal on Linux and MAC machines and - since version 10 - from Windows. For older Windows versions, users can use Putty.

$ ssh username@address

X11 Forwarding

With X11 Forwarding, SSH can also be used to run applications with a GUI, remotely. Simply add the -X argument to do so:

$ ssh -X username@address

Remote Commands

SSH can also be used to send single commands, without starting a remote session. This example launches the jack_simple_client, which plays a continuing sine tone on the remote machine.

$ ssh -t username@address 'jack_simple_server'

Exercise

Log into the server with SSH.

Concept

This module focuses on fundamental principles of sound synthesis algorithms in C++, covering paradigms like subtractive synthesis, additive synthesis, physical modeling, distortion methods and processed recording. Theory and background of these approaches are covered in the contents of the Sound Synthesis Introduction.

The concept is based on Linux audio systems as development and runtime systems (von Coler & Runge, 2017). Using Raspberry PIs, classes can be supplied with an ultra low cost computer pool, resolving any compatibility issues of individual systems. Besides, the single board computers can be integrated into embedded projects for actual hardware instruments. Participants can also install Linux systems on their own hardware for increased performance.

Only few software libraries are part of the system used in this class, taking care of audio input and output, communication (OSC, MIDI), configuration and audio file processing. This minimal required framework allows the focus on the actual implementation of the algorithms on a sample-by-sample level, not relying on extensive higher level abstractions.


Although the concept of this class has advantages, there are different alternatives with their own benefits. There is a variety of frameworks to consider for implementing sound synthesis paradigms and building digital musical instruments with C/C++. The JUCE framework allows the compilation of 'desktop and mobile applications, including VST, VST3, AU, AUv3, RTAS and AAX audio plug-ins'. It comes with many helpful features and can be used to create DAW-ready software components. Environments like Puredata or SuperCollider come with APIs for programming user extensions. The resulting software components can be integrated into existing projects, easily.


References

2017

  • Henrik von Coler and David Runge. Teaching Sound Synthesis in C/C++ on the Raspberry Pi. In Proceedings of the Linux Audio Conference. 2017.
    [details] [BibTeX▼]

The JACK API

All examples in this class are implemented as JACK clients. Audio input and output is thus based on the JACK Audio API. The JACK framework takes over a lot of management and allows a quick entry point for programmers. Professional Linux audio systems are usually based on JACK servers, allowing the flexible connection of different software components. Read more in the JACK Section of the Computer Music Basics.


The ThroughExample

The ThroughExample is a slightly adapted version of the Simple Client. It wraps the same functionality into a C++ class, adding multi-channel capabilities.


Main

The file main.cpp creates an instance of the ThroughExample class. No command line arguments are passed and the object is created without any arguments:

ThroughExample *t = new ThroughExample();

Member Variables

jack_client_t   *client;

The pointer to a jack client is needed for connecting this piece of software to the JACK server.

The MIDI Protocol

The MIDI protocol was released in 1982 as a means for connecting electronic musical instruments. First synths to feature the new technology were the Prophet-600 and the Jupiter-6. Although limited in resolution from a recent point of view, it is still a standard for conventional applications - yet to be replaced by the newly released MIDI 2.0. Besides rare mismatches and some limitations, MIDI devices can be connected without complications. Physically, MIDI has been introduced with the still widespread 5-pin connector, shown below. In recent devices, MIDI is usually transmitted via USB.

MIDI jack  (5-pin DIN).

MIDI jack (5-pin DIN).



Standard MIDI Messages

MIDI transmits binary coded messages with a speed of $31250\ \mathrm{kbit/s}$. Timing and latency are thus not a problem when working with MIDI. However, the resolution of control values can be a limiting factor. Standard MIDI messages consist of three Bytes, namely one status Byte (first bit green) and two data bytes (first bit red). The first bit declares the Byte either a status Byte (1) or a data Byte (0).

/images/basics/midi-message.png

Standard MIDI message with three Bytes.


Some of the most common messages are listed in the table below. Since one bit is used as the status/data identifier, 7 bits are left for encoding. This results in the typical MIDI resolution of \(2^7 = 128\) values for pitch, velocity or control changes.

Voice Message           Status Byte      Data Byte1          Data Byte2
-------------           -----------   -----------------   -----------------
Note off                      8x      Key number          Note Off velocity
Note on                       9x      Key number          Note on velocity
Polyphonic Key Pressure       Ax      Key number          Amount of pressure
Control Change                Bx      Controller number   Controller value
Program Change                Cx      Program number      None
Channel Pressure              Dx      Pressure value      None
Pitch Bend                    Ex      MSB                 LSB

Pitch Bend

If you are stuck with MIDI for some reason but need a higher resolution, the Pitch Bend parameter can help. Each MIDI channel has one Pitch Bend, each with two combined data Bytes, resulting in a resolution of \(128^2 = 16384\) steps.


System Exclusive

SysEx messages can be freely defined by manufacturers. They are often used for dumping or loading settings and presets, but can also be used for arbitrary control purposes. SysEx messages can have any length and are not standardized.


MIDI Note to Hertz

When working with MIDI, a conversion from MIDI pitch to Hertz is often necessary. There are two simple formulas for doing that. They both refer to the MIDI pitch of 69, wich corresponds to a frequency of 440 Hz:

\begin{equation*} f[\mathrm{Hz}] = 2 \frac{\mathrm{MIDI}-69}{12} 440 \end{equation*}
\begin{equation*} \mathrm{MIDI} = 69 +12 \log_2 \left( \frac{f}{440 \mathrm{Hz}} \right) \end{equation*}

Getting Started with SuperCollider

Supercollider (SC) is a server-client-based tool for sound synthesis and composition. SC was started by James McCartney in 1996 and is free software since 2002. It can be used on Mac, Linux and Windows systems and comes with a large collection of community-developed extensions. The client-server principle aims at live coding and makes it a powerful tool for distributed and embedded systems, allowing the full remote control of synthesis processes.

There are many ways of approaching SuperCollider, depending on the intended use case. Some tutorials focus on sequencing, others on live coding or sound design. This introduction aims at programming remotely controlled synthesis and processing servers, which involves signal routing and OSC capabilities.


Getting SC

Binaries, source code and build or installation instructions can be found at the SC GitHub site. If possible, it is recommended to build the latest version from the repository:

https://supercollider.github.io/downloads

SuperCollider comes with a large bundle of help files and code examples but first steps are usually not easy. There are a lot of very helpful additional resources, providing step by step introductions.

Code snippets in this example are taken from the accompanying repository: SC Example. You can simple copy and paste them into your editor.


SC Trinity

SuperCollider is based on a client-server paradigm. The server is running the actual audio processing, whereas clients are used to control the server processes via OSC messages. Multiple clients can connect to a running server. The dedicated ScIDE allows convenient features for live coding and project management:

/images/basics/supercollider-components.png

Server, client and ScIDE.


sclang

sclang is the SuperCollider language. It represents the client side when working with SC. It can for example be started in a terminal by running:

$ sclang

Just as with other interpreted languages, such as Python, the terminal will then change into sclang mode. At this point, the class library is complied, making all SC classes executable. Afterwards, SC commands can be entered:

sc3>  postln("Hello World!")

ScIDE

Working with SC in the terminal is rather inconvenient. The SuperCollider IDE (ScIDE) is the environment for live coding in sclang, allowing the control of the SuperCollider language:

/images/basics/scide.png

ScIDE


When booting the ScIDE, it automatically launches sclang and is then ready to interpret. Files opened in the IDE can be executed as a whole. Moreover, single blocks, respectively single lines can be evaluated, which is especially handy in live coding, when exploring possibilities or prototyping. In addition, the IDE features tools for monitoring various server properties.


Some Language Details

Parentheses

Parentheses can help structuring SC code for live programming. Placing the cursor inside a region between parentheses and pressing Control + Enter evaluates the code inside the parentheses. This way of coding is not suited for scripts which are executed as one.

(
      post('Hello ');
      postln('World!');
)

Variable Names

Global variables are either single letters - s is preserved for the default server - or start with a tilde: ~varname). They can be declared and used anywhere in a language instance. The first letter of tilde variables must be lowercase. Local variables, used in functions or code blocks, need to be defined explicitly:

// single-letter-global variable:
x = 1.0;

// tilde-global variables:
~aValue = 1.1;

// local variable:
var foo;

Declare First

All declarations of local variables must happen in the beginning of a function or block. The following example throws an error:

(
var xValue = 1.0;

xValue.postln;

var yValue = 2.1;
)

Evaluating Selections

Some of the examples in the SC section of this class are in the repository, whereas other only exist as snippets on these pages. In general, all these examples can be explored by copy-pasting the code blocks from the pages into the ScIDE. They can then be evaluated in blocks or line-wise but can not be executed as complete files. This is caused by the problem of synchronous vs asynchronous processes, which is explained later: Synchronous vs Asynchronous

These features help to run code in the ScIDE subsequently:

  • Individual sections of code can be evaluated by selecting them and pressing Control + Enter.

  • Single lines of code can be evaluated by placing the cursor and pressing Shift + Enter


Functions

Functions in SC are defined inside curly brackets. Arguments can are declared in the very beginning. Once created, a function is used by calling the .value() method:

(
~poster = {

    arg a,b;

    var y = a+b;

    y.postln;

};
)

~poster.value(1,1);

Arguments can also be defined inside pipes:

~poster = {

    |a,b|

    a.postln;

};