Introduction

What is Faust?

Faust (Functional Audio Stream) is a functional programming language for sound synthesis and audio processing with a strong focus on the design of synthesizers, musical instruments, audio effects, etc. Faust targets high-performance signal processing applications and audio plug-ins for a variety of platforms and standards. It is used on stage for concerts and artistic productions, in education and research, in open source projects as well as in commercial applications.

The core component of Faust is its compiler. It allows us to "translate" any Faust digital signal processing (DSP) specification to a wide range of non-domain specific languages such as C++, C, JAVA, LLVM IR, WebAssembly, etc. In this regard, Faust can be seen as an alternative to C++ but is much simpler and intuitive to learn.

Thanks to a wrapping system called "architectures," codes generated by Faust can be easily compiled into a wide variety of objects ranging from audio plug-ins to standalone applications or smartphone and web apps, etc.

This manual gives an overview of the Faust programming language and of its features through various interactive examples.

What is Faust Good For?

Faust's syntax allows us to express any DSP algorithm as a block diagram. For example, + is considered as a valid function (and block) taking two arguments (signals) and returning one:


process = +;

Blocks can be easily connected together using the : "connection" composition:


process = + : *(0.5);

In that case, we add two signals together and then scale the result of this operation.

Thus, Faust is perfect to implement time-domain algorithms that can be easily represented as block diagrams such as filters, waveguide physical models, virtual analog elements, etc.

Faust is very concise, for example, here's the implementation of a one pole filter/integrator equivalent to (where is the pole):


a1 = 0.9;
process = +~*(a1);

Codes generated by Faust are extremely optimized and usually more efficient that handwritten codes (at least for C and C++). The Faust compiler tries to optimize each element of an algorithm. For example, you shouldn't have to worry about using divides instead of multiplies as they get automatically replaced by multiplies by the compiler when possible, etc.

Faust is very generic and allows us to write code that will run on dozens of platforms.

What is Faust Not (So) Good For?

Despite all this, Faust does have some limitations. For instance, it doesn't allow for the efficient implementation of algorithms requiring multi-rates such as the FFT, convolution, etc. While there are tricks to go around this issue, we're fully aware that it is a big one and we're working as hard as possible on it.

Faust's conciseness can sometimes become a problem too, especially for complex algorithms with lots of recursive signals. It is usually crucial in Faust to have the "mental global picture" of the algorithm to be implemented which in some cases can be hard.

While the Faust compiler is relatively bug-free, it does have some limitations and might get stuck in some extreme cases that you will probably never encounter. If you do, shoot us an e-mail!

From here, you can jump to the Quick Start Tutorial section of this manual.

Design Principles

Since the beginning of its development in 2002, Faust has been guided by various design principles:

Signal Processor Semantic

A Faust program describes a signal processor. The role of a signal processor is to transforms a (possibly empty) group of input signals in order to produce a (possibly empty) group of output signals. Most audio equipments can be modeled as signal processors. They have audio inputs, audio outputs as well as control signals interfaced with sliders, knobs, vu-meters, etc.

More precisely :

As an example, let's express the semantic of the Faust primitive +. Like any Faust expression, it is a signal processor. Its signature is . It takes two input signals and and produces an output signal such that .

Numbers are signal processors too. For example the number has signature . It takes no input signals and produce an output signal such that .