FAUST (programming language)

Last updated
FAUST
Original author(s) Yann Orlarey, Dominique Fober, Stéphane Letz
Developer(s) GRAME, Centre National de Création Musicale
Initial release2002 (2002)
Stable release
2.60.3 [1] / June 14, 2023 (2023-06-14)
Written in C++
Operating system Linux, OS X, Windows, Unix
Type Functional programming language for audio signal processing
License GPL
Website faust.grame.fr

FAUST (Functional AUdio STream) is a domain-specific purely functional programming language for implementing signal processing algorithms in the form of libraries, audio plug-ins, or standalone applications. A FAUST program denotes a signal processor: a mathematical function that is applied to some input signal and then fed out.

Contents

Overview

The FAUST programming model combines a functional programming approach with a block diagram syntax:

A FAUST program doesn’t describe a sound or a group of sounds, but a signal processor. The program source is organized as a set of definitions with at least the definition of the keyword process (the equivalent of main in C):

process=...;

The FAUST compiler translates FAUST code into a C++ object, which may then interface with other C++ code to produce a full program.

The generated code works at the sample level. It is therefore suited to implement low-level DSP functions like recursive filters. The code may also be embedded. It is self-contained and does not depend on any DSP library or runtime system. It has a very deterministic behavior and a constant memory size.

The semantics of FAUST is driven to be simple and well-defined. It allows the FAUST compiler to be semantically driven. Instead of compiling a program literally, it compiles the mathematical function it denotes. This may promote component reuse. Moreover, having access to the exact semantics of a FAUST program can simplify preservation issues.

FAUST is a textual language but block diagram oriented. It combines two approaches: functional programming and algebraic block diagrams, which are constructed via function composition. For that, FAUST relies on a block diagram algebra of five composition operations.

Example code

FAUST programs define a process function that operates on incoming data. This is analogous to the main function in most programming languages. The following is an example that produces silence:

process=0;

The second example copies the input signal to the output. It involves the _ primitive that denotes the identity function for signals:

process=_;

Another example sums a stereo signal into a mono signal using the + primitive:

process=+;
Block diagrams generated by Faust from some simple programs Faust-simple-block-diagram.jpg
Block diagrams generated by Faust from some simple programs

Most FAUST primitives are analogous to their C counterpart on numbers, but lifted to signals. For example, the FAUST primitive sin operates on a signal X by applying the C function sin to each sample X[t]. All C numerical functions have their counterpart in FAUST. Some signal processing primitives are specific to FAUST. For example, the delay operator @ takes two input signals: X (the signal to be delayed) and D (the delay to be applied), and produces an output signal Y such that Y(t) = X(t − D(t)).

Block diagram composition

Contrary to Max-like visual programming languages where the user does manual connections, FAUST primitives are assembled in block diagrams by using a set of high-level block diagram composition operations.

Simple examples of block diagram composition Faust-simple-block-diagrams.jpg
Simple examples of block diagram composition
The block diagram composition operators used in FAUST
f~gRecursive composition (precedence 4)
f,gParallel composition (precedence 3)
f:gSequential composition (precedence 2)
f<:gSplit composition (precedence 1)
f:>gMerge composition (precedence 1)

Using the sequential composition operator : the output of + can be routed to the input of abs to compute the absolute value of the signal:

process=+:abs;

Here is an example of parallel composition using the , operator that arranges its left and right expressions in parallel. This is analogous to a stereo cable.

process=_,_;

These operators can be arbitrarily combined. The following code multiplies an input signal with 0.5:

process=_,0.5:*;

The above may be rewritten in curried form:

process=*(0.5);

The recursive composition operator ~ can be used to create block diagrams with cycles (that include an implicit one-sample delay). Here is an example of an integrator that takes an input signal X and computes an output signal Y such that Y(t) = X(t) + Y(t−1):

process=+~_;

Generating full applications

Using specific architecture files, a FAUST program can be used to produce code for a variety of platforms and plug-in formats. These architecture files act as wrappers and describe the interactions with the host audio and GUI system. As of 2021, more than 30 architectures are supported and new ones may be implemented by anyone.

Screenshot of mixer.dsp (available in the FAUST distribution) using the jack-qt architecture Faust-mixer-jackqt.jpg
Screenshot of mixer.dsp (available in the FAUST distribution) using the jack-qt architecture
Some architecture files available for FAUST
alsa-gtk.cppALSA application + GTK
alsa-qt.cppALSA application + QT4
android.cppAndroid applications
au.cppAudio Unit plug-in
ca-qt.cppCoreAudio application + QT4
ios-coreaudio.cppiPhone and iPad applications
jack-gtk.cppJACK application + GTK
jack-qt.cppJACK application + QT4
ladspa.cppLADSPA plug-in
max-msp.cppMax MSP plug-in
pd.cppPuredata plug-in
q.cppQ language plug-in
supercollider.cppSupercollider plug-in
vst.cppVST plug-in
vsti-mono.cppMonophonic VST Instrument plug-in
vsti-poly.cppPolyphonic VST Instrument plug-in

Generating block diagrams

A useful option makes it possible to generate the block diagram representation of the program as one or more SVG graphic files.

It is useful to note the difference between the block diagram and the generated C++ code. As stated, the key idea here is not to compile the block diagram literally, but the mathematical function it denotes. Modern C/C++ compilers also don’t compile programs literally. But because of the complex semantics of C/C++ (due to side effects, pointer aliasing, etc.) they can’t go very far in that direction. This is a distinct advantage of a purely functional language: it allows compilers to do very advanced optimisations.

Arrows-like semantics

The Faust semantics is almost the same as that of Haskell's Arrows type class. However, the Arrow type class is not bound to signal processors.

Equivalences between FAUST and Arrow combinators
f~gloop((\(a,b)->(b,a))^>>f>>>id&&&(delay>>>g)) where delay is not a method of the Arrow type class, but is specific to signal processing arrows
f,gf***g
f:gf>>>g
f<:gf>>^h>>>g with appropriate function h (or &&& in special cases)
f:>gf>>^h>>>g with appropriate function h

The Arrow combinators are more restrictive than their FAUST counterparts, e.g., the nesting of parallel composition is preserved, and inputs of the operands of &&& must match exactly.

Related Research Articles

In computing, a compiler is a computer program that translates computer code written in one programming language into another language. The name "compiler" is primarily used for programs that translate source code from a high-level programming language to a low-level programming language to create an executable program.

In computing and computer programming, exception handling is the process of responding to the occurrence of exceptions – anomalous or exceptional conditions requiring special processing – during the execution of a program. In general, an exception breaks the normal flow of execution and executes a pre-registered exception handler; the details of how this is done depend on whether it is a hardware or software exception and how the software exception is implemented. Exception handling, if provided, is facilitated by specialized programming language constructs, hardware mechanisms like interrupts, or operating system (OS) inter-process communication (IPC) facilities like signals. Some exceptions, especially hardware ones, may be handled so gracefully that execution can resume where it was interrupted.

Verilog, standardized as IEEE 1364, is a hardware description language (HDL) used to model electronic systems. It is most commonly used in the design and verification of digital circuits at the register-transfer level of abstraction. It is also used in the verification of analog circuits and mixed-signal circuits, as well as in the design of genetic circuits. In 2009, the Verilog standard was merged into the SystemVerilog standard, creating IEEE Standard 1800-2009. Since then, Verilog is officially part of the SystemVerilog language. The current version is IEEE standard 1800-2017.

In computer science, a compiler-compiler or compiler generator is a programming tool that creates a parser, interpreter, or compiler from some form of formal description of a programming language and machine.

In computer engineering, a hardware description language (HDL) is a specialized computer language used to describe the structure and behavior of electronic circuits, and most commonly, digital logic circuits.

Csound is a domain-specific computer programming language for audio programming. It is called Csound because it is written in C, as opposed to some of its predecessors.

In computer science, formal methods are mathematically rigorous techniques for the specification, development, analysis, and verification of software and hardware systems. The use of formal methods for software and hardware design is motivated by the expectation that, as in other engineering disciplines, performing appropriate mathematical analysis can contribute to the reliability and robustness of a design.

Parsing, syntax analysis, or syntactic analysis is the process of analyzing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar. The term parsing comes from Latin pars (orationis), meaning part.

In programming language theory, semantics is the rigorous mathematical study of the meaning of programming languages. Semantics assigns computational meaning to valid strings in a programming language syntax.

<span class="mw-page-title-main">ChucK</span> Audio programming language

ChucK is a concurrent, strongly timed audio programming language for real-time synthesis, composition, and performance, which runs on Linux, Mac OS X, Microsoft Windows, and iOS. It is designed to favor readability and flexibility for the programmer over other considerations such as raw performance. It natively supports deterministic concurrency and multiple, simultaneous, dynamic control rates. Another key feature is the ability to live code; adding, removing, and modifying code on the fly, while the program is running, without stopping or restarting. It has a highly precise timing/concurrency model, allowing for arbitrarily fine granularity. It offers composers and researchers a powerful and flexible programming tool for building and experimenting with complex audio synthesis programs, and real-time interactive control.

Real-Time Cmix (RTcmix) is one of the MUSIC-N family of computer music programming languages. RTcmix is descended from the MIX program developed by Paul Lansky at Princeton University in 1978 to perform algorithmic composition using digital audio soundfiles on an IBM 3031 mainframe computer. After synthesis functions were added, the program was renamed Cmix in the 1980s. Real-time capability was added by Brad Garton and David Topper in the mid-1990s, with support for TCP socket connectivity, interactive control of the scheduler, and object-oriented embedding of the synthesis engine into fully featured applications.

<span class="mw-page-title-main">Visual programming language</span> Programming language written graphically by a user

In computing, a visual programming language or block coding is a programming language that lets users create programs by manipulating program elements graphically rather than by specifying them textually. A VPL allows programming with visual expressions, spatial arrangements of text and graphic symbols, used either as elements of syntax or secondary notation. For example, many VPLs are based on the idea of "boxes and arrows", where boxes or other screen objects are treated as entities, connected by arrows, lines or arcs which represent relations.

In computer science, Linda is a coordination model that aids communication in parallel computing environments. Developed by David Gelernter, it is meant to be used alongside a full-fledged computation language like Fortran or C where Linda's role is to "create computational activities and to support communication among them".

In computer programming, dataflow programming is a programming paradigm that models a program as a directed graph of the data flowing between operations, thus implementing dataflow principles and architecture. Dataflow programming languages share some features of functional languages, and were generally developed in order to bring some functional concepts to a language more suitable for numeric processing. Some authors use the term datastream instead of dataflow to avoid confusion with dataflow computing or dataflow architecture, based on an indeterministic machine paradigm. Dataflow programming was pioneered by Jack Dennis and his graduate students at MIT in the 1960s.

<span class="mw-page-title-main">Block diagram</span> Graphical system analysis method

A block diagram is a diagram of a system in which the principal parts or functions are represented by blocks connected by lines that show the relationships of the blocks. They are heavily used in engineering in hardware design, electronic design, software design, and process flow diagrams.

VisSim is a visual block diagram program for simulation of dynamical systems and model-based design of embedded systems, with its own visual language. It is developed by Visual Solutions of Westford, Massachusetts. Visual Solutions was acquired by Altair in August 2014 and its products have been rebranded as Altair Embed as a part of Altair's Model Based Development Suite. With Embed, you can develop virtual prototypes of dynamic systems. Models are built by sliding blocks into the work area and wiring them together with the mouse. Embed automatically converts the control diagrams into C-code ready to be downloaded to the target hardware.

Verilog-AMS is a derivative of the Verilog hardware description language that includes Analog and Mixed-Signal extensions (AMS) in order to define the behavior of analog and mixed-signal systems. It extends the event-based simulator loops of Verilog/SystemVerilog/VHDL, by a continuous-time simulator, which solves the differential equations in analog-domain. Both domains are coupled: analog events can trigger digital actions and vice versa.

In computer programming, flow-based programming (FBP) is a programming paradigm that defines applications as networks of "black box" processes, which exchange data across predefined connections by message passing, where the connections are specified externally to the processes. These black box processes can be reconnected endlessly to form different applications without having to be changed internally. FBP is thus naturally component-oriented.

<span class="mw-page-title-main">Function model</span>

In systems engineering, software engineering, and computer science, a function model or functional model is a structured representation of the functions within the modeled system or subject area.

SIGNAL is a programming language based on synchronized data-flow : a process is a set of equations on elementary flows describing both data and control.

References