Faust News

2018-07-23: View Faust’s Evolution

View the evolution of the Faust project from 2004 to 2018.

The visualization was done using Gource. Here is the command used (as suggested by fullybacked):

gource --hide dirnames,filenames --seconds-per-day 0.1 --auto-skip-seconds 1 -1920x1024 -o - | ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i - -vcodec libx264 -preset ultrafast -pix_fmt yuv420p -crf 1 -threads 0 -bf 0 faust-hd.mp4

2018-07-23: Faust Awards 2018 to iPlug 2 !

The Faust Open Source Software Competition aims at promoting innovative high-quality free audio software developed with Faust, a functional programming language for realtime signal processing and sound synthesis. The competition is sponsored by GRAME, Centre National de Création Musicale.

Faust Award 2018 to iPlug 2

The Faust Award 2018 was attributed by an international committee composed of :

  • Jean-Louis Giavitto (IRCAM, Paris, France),
  • Albert Graef (Johannes Gutenberg U., Mainz, Germany),
  • Pierre Jouvelot (Ecole des Mines, Paris, France),
  • Victor Lazzarini (Maynooth U., Maynooth, Ireland),
  • Romain Michon (Stanford U., Palo Alto, USA)
  • Yann Orlarey (GRAME, Lyon, France),
  • Laurent Pottier (U. Jean Monnet, Saint-Etienne, France),
  • Julius Smith (Stanford U., Palo Alto, USA)

to iPlug 2 a free open source C++ audio plug-in framework, allowing developers to create audio plug-ins and apps across a wide range of formats from the same code, including graphical user interface and DSP components. Amongst many other new features and a reworked code base, version 2 includes support for FAUST, allowing sections of audio DSP to be implemented using the FAUST language, and easily integrated with other C++ elements.

iPlug 2 is developed by Oliver Larkin and Alex Harker from the original iPlug, by Cockos inc. that was open sourced in 2008. The project is under active development and will be publicly released at the end of 2018.

The jury praised the quality, the ambition, and the usefulness of iPlug 2 as a Faust development framework! Check the demo here. We hope that the Faust Award will help the authors to fully finalize the project.

Faust Student Software Competition to Cloud Generator

In parallel to the main competition, the Faust Student Software Competition, is intended to promote small, but innovative Faust applications, typically developed in the framework of student projects.

The student prize 2018 was awarded to Cloud Generator a nine-voice polyphonic synthesizer developed by Rittik Wystup.

The jury praised the audio quality and the care taken by Rittik Wystup in his project! Check the Cloud Generator demo here.


2018-07-10: International Faust Conference (IFC) 2018

International Faust Conference IFC18: July 17-18, 2018

The International Faust Conference IFC18 will take place at the Johannes Gutenberg University of Mainz (Germany) on July 17-18, 2018. It aims at gathering developers and users of the Faust programming language to present current projects and discuss future directions for Faust and its community.

Participants will be able to share their work through paper presentations. A series of round tables on various topics will serve as a platform to brainstorm on Faust’s features, semantics, tools, applications, etc. to determine future directions for this language. Open spaces for demos and workshops will be available for participants to openly share their ongoing projects with the rest of the community.

As a special event, the winner of GRAME’s Faust Open-Source Software Competition will be announced during IFC18.

IFC-18 is free and everyone is welcome to attend! Please register here

2018-02-18: Faust Award 2018

Faust Award 2018: deadline June 1, 2018

The Faust Open-Source Software Competition is intended to promote innovative high-quality free audio software developed with the Faust programming language, as well as development tools built around the Faust compiler itself. The Faust Open-Source Software award will be attributed to the best submission by an international committee of leading experts in the field. The competition is sponsored by Grame, centre national de création musicale. The winning software will receive a 2000€ price to encourage its authors. The results will be announced July 17, 2018 during the International Faust Conference in Mainz IFC18.

To participate, the software must be provided with source code and licensed with a Free/Open Source license. A substantial part of the software must be written in Faust and the Faust source code must be provided. As part of the review process, the software will be built from the sources. All source code, license, video demonstration, installation instructions, and any other documentation must be available on a public web page. License compatibility with other open source software is encouraged. Dependencies on non-open source third-party software are discouraged, with the exception of operating systems and freely available commercial packages.

Authors are required to prepare a video demonstrating the software. This video must be done carefully, and should convincingly present the qualities of the software. The submission must also contain any useful documentation, including examples of how the provided software might be used, existing prototypes that use the software, download statistics or other public usage information. The criteria for judging submissions includes broad applicability and potential impact, novelty, technical depth, reusability, etc.

Junior Competition

In parallel to the Faust Open-Source Software Competition we have a junior competition, the Faust Student Software Competition, with a 200€ prize for the winner. The Faust Student Software Competition is intended to promote interesting audio processing and synthesis applications written in Faust in a single file in less than 1000 words. The word count is done after removing the comments from the code:

cat foo.dsp | stripcmt | wc -w.

The use of the standard Faust libraries is strongly encouraged. They don’t take part in the word count.

Important dates

  • Start of the competition: February 18, 2018
  • Software Submission Deadline: June 1, 2018
  • Results of the competition: July 17, 2018

Submission Guidelines

Authors interested in participating in the Faust Open Source Software Competition or the Faust Student Software Competition should send a submission email to faustaward@grame.fr with a PDF file attached containing the following information:

  • Title of submission,
  • Category of submission (Faust Open Source Software Competition or Faust Student Software Competition),
  • Name, email and affiliation of the main author,
  • Names, emails and affiliations of other authors,
  • A permanent link for the open source software (e.g., Sourceforge, GitHub, Google Code, etc.),
  • A permanent link for the video demonstration (e.g., YouTube, Vimeo, etc.),
  • A link to a compressed archive file that contains the software (source code, documentation, build/install instructions, and licenses). Comprehensive and clear build/install instructions will be a crucial component of any submission. The committee will make a reasonable effort to build the software for the top contributions, but if they are unable to make the software run, it will be excluded from the competition.

International Committee

  • Jean-Louis Giavitto (IRCAM, Paris, France),
  • Albert Gräf (Johannes Gutenberg U., Mainz, Germany),
  • Pierre Jouvelot (Ecole des Mines, Paris, France),
  • Victor Lazzarini (Maynooth U., Maynooth, Ireland),
  • Romain Michon (CCRMA, Stanford , USA)
  • Yann Orlarey (Grame, Lyon, France),
  • Laurent Pottier (U. Jean Monnet, Saint Etienne, France),
  • Julius Smith (CCRMA, Stanford , USA)

Previous Winners

  • 2015: Guitarix, by Hermann Meyer and Andreas Degert
  • 2016: Ambitools, by Pierre Lecomte; Student prize: TouchVoices, by Pierre-Adrien Théo.

2017-12-12: WebAudio wasm benchmark pages and tools

WebAudio wasm benchmark pages and tools allow to test statically generated HTML pages from Faust DSP. Audio generating pages in ScriptProcessor or AudioWorklet mode can be tested first. DSP CPU benchmark pages can be used to test the perfomance of wasm code across different browsers.

Tools to generate new DSP CPU benchmark pages are also available, and finally a page allowing to test the dynamic compilation chain can be acccesed.

Simple pages

Simple pages can be used to test simple monophonic and polyphonic DSP, generated as ScriptProcessor or AudioWorklet WebAudio nodes.

Note that as 12/12/17, AudioWorklet pages can ony be tested with Chrome Canary. Be sure to activate AudioWorklet mode first. On a MacBook Pro OSX El Capitan 2,2 GHz Intel Core i7, we still hear audio glitches when testing them, for example when opening the JavaScript console, or interacting with other applications (like scrolling in the XCode editor, scrolling in the terminal…)

Polyphonic MIDI aware pages

More complex statically generated polyphonic MIDI aware pages can be tested.

ScriptProcessor based pages:

AudioWorklet based pages:

Benchmark pages

A set of statically generated pages allow to measure the DSP CPU use of Faust generated WebAssemby code. The compute method is repeatedly called in a loop (taking 100% of a core) which duration is measured. Results as MBytes/sec as well a DSP CPU load in % of a 1024 frames, 44.1 kHz audio buffer are displayed.

On the following pages, just hit the Start benchmark button, and wait for the result to be displayed. Note that since the computation is done in the main JavaScript thread, don’t disturb your machine too much to get a reliable result. The pages can typically be used to compare the performances of different browsers:

Testing the denormal issue

A specific problem occurs when audio computation produces denormal float values, which is quite common with recursive filters, and can be extremely costly to compute on some processors like the Intel family for instance. Loog at the following page for more explanations. Even with the software FTZ mode, we still see huge DSP CPU issue in some cases like this djembe physical model based on simple biquad filters:

On OSX for instance, open the Activity Monitor tool and look as your browser CPU use. Then hit the checkbox to start playing, and hit it again to stop it. Silence should be produced, but actually very small sample values (= subnormals) are generated. If your machine uses an Intel CPU, you will see CPU raise quite rapidly ! (tested on a MacBook Pro OSX El Capitan 2,2 GHz Intel Core i7).

Benchmark tools

For developers, benchmark tools allow to generate HTML pages to test your DSP. Look in particular at the faust2benchwasm script.

Dynamic compilation chain testing page

A more complete testing page for monophonic and polyphonic MIDI aware DSP, ScriptProcessor or AudioWorklet mode, FTZ selection mode is available here.


2017-11-07: 1st International Faust Conference

1st International Faust Conference - Johannes Gutenberg University, Mainz (Germany), July 17-18, 2018

The International Faust Conference IFC-18 will take place at the Johannes Gutenberg University of Mainz (Germany) on July 17-18, 2018. It aims at gathering developers and users of the Faust programming language to present current projects and discuss future directions for Faust and its community. Participants will be able to share their work through paper presentations. A series of round tables on various topics will serve as a platform to brainstorm on Faust’s features, semantics, tools, applications, etc. to determine future directions for this language. Open spaces for demos and workshops will be available for participants to openly share their ongoing projects with the rest of the community.

As a special event, the winner of GRAME’s Faust Open-Source Software Competition will be announced during IFC-18.

IFC-18 is free and everyone is welcome to attend!

Call for Papers

We welcome submissions from academic, professional, independent programmers, artists, etc. We solicit original papers centered around the Faust programming language in the following categories:

  • Original research
  • Technology tutorial
  • Artistic project report (e.g., installation, composition, etc.)

Paper should be up to 14 pages in length, non anonymous, and formatted according to this template. Submissions should be carried out via our EasyChair portal.

All submissions are subject to peer review. Acceptance may be conditional upon changes being made to the paper as directed by reviewers.

Accepted papers will be published on-line as well as in the IFC-18 proceedings paper version. They will be presented by their author(s) at IFC-18 as 15 minutes presentations (+ 5 minutes for questions).

Feel free to contact us if you have any question.

Important Dates

  • Papers submission deadline: March 2, 2018
  • Notification of Acceptance: May 1, 2018
  • Camera-Ready Version: June 1, 2018

Call for Round Table Topics

A series of round tables on the following themes will take place both afternoons of IFC-18:

  • Faust Tools (e.g., Architectures, IDE, Faust Code Generator, On-Line Services, etc.)
  • DSP in Faust and Faust Libraries (e.g., New Algorithms, New Libraries, Missing Functions, etc.)
  • Faust Compiler and Semantics
  • Other Topics/Open Session

We solicit topic suggestions from the Faust community for each of these themes. Topics can be submitted by means of this Google form. They will be introduced during the round tables by the session chair.

Contact

Please, address your questions to: ifc18@muwiinfa.geschichte.uni-mainz.de

Conference website: http://www.ifc18.uni-mainz.de


2017-10-20: New Faust Editor

We are very happy to announce the online Faust Editor. It can be used to edit, compile and run Faust code from any recent Web Browser with WebAssembly support. This editor works completely on the client side and it is therefore very convenient for situations with many simultaneous users (workshops, classrooms, etc.). It embeds the latest version of the Faust compiler with an efficient WebAssembly backend and offers polyphonic MIDI support.

Features

The editor engine is based on codemirror. It offers syntax highlighting, auto completion and direct access to the online documentation. The documentation command (ctrl-d) uses the function name at the cursor position to locate to the relevant information.

The recommended browsers are the latest versions of Firefox and Chrome. Chrome is recommended for MIDI, but it requires an https connexion to use the audio inputs. On the other hand MIDI is not supported by Firefox.


2017-09-15: Performances of audio DSP code compiled in WebAssembly

Porting and running large C/C++ code base on the Web have been the subject of several competing projects in the recent years, from Google NaCl/PNaCl to Mozilla asm.js. Recently standardized WebAssembly language inherits from ideas experimented in both approaches, with the Mozilla vision finnally winning as Robert O’Callahan explains here. Coupled with the WebAudio API, running real-time audio code in the Web now appears to be an achievable goal.

WebAssembly is a hot topic in the JavaScript ecosystem. The WebAudio community is eagerly waiting for the AudioWorklet specification, with its promised reduced latency and glitch-free audio rendering, to land in browser development versions, and be tested. Porting well established C/C++ codebase with Emscripten, like the Csound framework as an example, or using DSL languages like Faust, will then naturally beneficiate from improved and more stable performances.

The Faust ecosystem already allows to generate static or dynamically compiled WebAssembly based WebAudio nodes. These nodes are still using the deprecated ScriptProcessor WebAudio interface. Premillinary work has been started to be ready as soon at the AudioWorklet model will be testable.

In the meantime, work have been started using the WAVM, a standalone VM for WebAssembly, that can load both the standard binary and text wasm format, compiling it in native code using the LLVM chain (generating LLVM IR and compiling it on the fly to native code using LLVM JIT compiler), and running it at (near) native speed.

Glue code to load and run Faust generated wasm modules has been written. Validation and benchmarking tools have been developed. Performances comparison with the C++ and LLVM IR Faust backends is the subject of this post.

Comparing the Faust C++, LLVM IR and wast/wasm backends

The WebAssembly approach promises near native performances for C/C++ written code compiled to WebAssembly using the Emscripten tool chain. Other languages like Rust (using the mir2wasm tool) experiment direct WebAssembly generation. It seems clear that as WebAssembly specification and implementation stabilize, more and more languages will directly generate wasm to be deployed in browsers. The question of the quality of code generation at each step of the compilation chain will rapidly emerge.

While WebAssembly is initially designed to run on the Web, it may be deployed in non Web environnement like nodejs, or even in standalone VM like WAVM. Thus WebAssembly becomes a portable binary format that can be used in a large variety of situations. This is especially of interest for a DSL language like Faust.

Faust wast/wasm backend

Faust wast/wasm backend directly produce WebAssembly code from the Faust internal FIR (Faust Imperative Representation) code. Generated modules are rather light since they define a very simple ABI to be used by the loader code. Two generation models have been defined:

  • in monophonic mode the wast/mast module internally allocates a memory block to be used for the DSP state (controllers, delays lines, waveforms…) as well as audio buffers.

  • in polyphonic mode, the memory block will be allocated by the loader environnement. This block will typically be sized to contain all the needed voices for the polyphonic DSP.

In both cases, a full description of the DSP state as a JSON string is generated in the module data segment (including memory indexes of all controllers). Loader code will get and decode this JSON description, and use whatever parts of the description it needs to run the DSP code. In particular, control memory zones (corresponding to the UI items like buttons, sliders, bargraph…) can be directly read/written by the wrapper code.

Benchmark of C++, LLVM IR and wast/wasm generated code

Since Faust already generates C++ or LLVM IR code, the performances of those two backends can be compared with the new wasm one. Using the WAVM C++ written machine allows to deploy the same measuring code. The first benchmark compares the speed of C++, LLVM IR and wasm backends running a set of DSP, running on a MacBook Pro 2,2 GHz Core I7 with OSX El capitan. The same 4.0 version of LLVM toolchain has been used with the three backend. C++ and LLVM IR code has been compiled with the -Ofast optimization flag, the WAVM runtime is the standard version one (without any specific audio optimization, see later):

The diagrams clearly shows that the wasm code is still slower than C++ or LLVM IR code, but speed difference is not so high in most cases. Some DSP behaviours need to be understood in more details.

Optimizing the WAVM runtime for audio code

The WAVM runtime strictly conforms to the WebAssembly specification, thus behaving as a interesting base reference. In the audio domain, the deployed code is usually compiled with specific optimization flags. Since C++ WAVM runtime can be hacked quite easily, we did several changes into the reference implementation to gain some speed:

Here is the diagram of DSP examples run with reference WAVM runtime, and the three specific optimizations:

After generating the LLVM IR code, the WAVM runtime runs a set of LLVM IR to IR optimizations passes. It remains to be tested if adding more optimization passes (especially the auto-vectorizations ones) could help producing even better code.

WebAssembly module optimization with Binaryen

Binaryen is a compiler and toolchain infrastructure library for WebAssembly, written in C++. We tested the wasm-opt tool at -O3 level on Faust generated wasm modules to estimate which speedup we can expect. The following diagram shows limited gains, with no more than 5% in some of the tested cases:

Float denormal handling

A specific problem occurs when audio computation produces denormal float values, which is quite common with recursive filters, and can be extremely costly to compute on some processors like the Intel family for instance. A Flush To Zero (FTZ) mode for denormals can usually be set at hardware level, but it not yet available in the WebAssembly MVP version, which strictly conform to the IEEE 754 norm 8.

Thus an automatic software strategy which consists in adding FTZ code in all recursive loops has been implemented in the Faust compiler. To activate it, the -ftz compilation parameter must be used at compilation time.

The -ftz 1 mode adds a test in each recursive loop which uses the fabs function and a threshold to detect subnormal samples (slower). The -ftz 2 mode adds a test in each recursive loop which uses a mask to detect subnormal samples (faster).

Even if using software ftz is not strictly needed in our benchmark chain (since the C++ WAVM uses the ftz hardware protection mode), we can still compare the speed of the different ftz options. Here is the result of code generated with -ftz from 0 to 2:

Comparing three browsers on OSX El Capitan

HTML test pages were prepared to compare the performances of the three main browsers on OSX El Capitan. The DSP code is compiled with float denormal protection on (-ftz 2). The generated wasm module compute method is called repeatedly in a timed loop, using successive slices of a big allocated circular audio buffer to avoid cache effects. Here are the results:

The fasted one (Chrome for now) can be compared with C++, LLVM IR, WAVM native engines, all compiled with float denormal protection on (-ftz 2):

Comments and Conclusion

Testing wasm JIT machines inside browsers is not an easy task. The C++ WAVM runtime revealed to be an excellent tool to compare the Faust C++, LLVM IR and wasm backend. Since its code can be easily adapted, one can estimate also what can be expected deploying wasm DSP modules in pure native environments, outside of the browser, where some audio specific optimizations may be considered.

Measures done on a set of Faust DSP show that WebAssembly code still run slower than C++ or LLVM IR generated code in most cases, up to almost 66% slower in the less favorable examples. This value will typically be a bit worse when deploying in browsers, since float denormal protection code has to be used. Benchmarks in browser wasm runtime still need to be done to confirm or refine these findings.

Comparing the Chrome, Firefox and WebKit browsers on OSX El Capitan shows that Chrome is currently the fastest engine in most cases, with Firefox and WebKit quite similar (with a slight plus for WebKit).

Comparing the Chrome browser with native engines shows results from 4,8 times slower (filterBank.dsp), 2,8 times slower (sTunedBar6.dsp) up to much more favorable cases (karplus32.dsp). Note that filterBank.dsp example is a bit of a pathological case, since Chrome is significantly slower than Firefox and WebKit in this case, and filterBank.dsp uses a lot of pow(10, x) code that is rewritten an optimized as exp10(x) with the C++ backend path.


2017-08-18: Deploying Faust DSP on the Web

EDIT : we are at the Web Audio conference 2017, and it appears that the way we currently extend the ScripProcessorNode with Faust code is not the Right Way… Part of the post concerning the exposed API will probably change a bit in the near future…

Using latest developments done for the Web (the new WebAssembly backends and libfaust library compiled in WebAssembly with Emscripten), statically and dynamically Faust generated WebAudio nodes can be easily produced and deployed on the Web.

Deploying statically compiled Faust WebAudio nodes

From a foo.dsp source file, JavaScript and the associated WebAssembly files can be produced with the following script:

faust2wasm foo.dsp 

This will generate a foo.wasm file with the WebAssembly module as binary code, as well as a foo.js wrapper file containing the code needed to turn the Faust DSP in a fully working WebAudio node (using an extended ScriptProcessor node). The name of the Faust DSP code file is used to define the final ScriptProcessorNode constructor name. So for instance if osc.dsp file is compiled, the following faust.createosc function will be generated:

/** 
* Create a 'monophonic' ScriptProcessorNode Web Audio object 
* by loading and compiling the Faust wasm file
*
* @param context - the Web Audio context
* @param buffer_size - the buffer_size in frames
* @param callback - a callback taking the created ScriptProcessorNode as parameter, 
* or null in case of error
*/
faust.createosc = function(context, buffer_size, callback)

The resulting object is an extended ScriptProcessorNode, to be used as a regular node (like connected to other WebAudio nodes), but which also adds the Faust specific API as defined in the equivalent C++ generated dsp class (see the architecture/faust/dsp/dsp.h header for more technical details), as well as JavaScript more specific functions. For instance the following ones will have to be used to control the node:

var paths = node.getParams(); // get the set of paths to read/write input control parameters

Then knowing the path for a given parameter, the following function is used to change the parameter value:

node.setParamValue("/Oscillator/freq", 0.6);

A full JSON description of the node with the complete UI, can be retrieved with:

var json = node.getJSON(); 

The complete usable API is fully documented in the generated JavaScript file in the Public API to be used to control the WebAudio node section.

A simple example Web page

A simple Web page using the files generated by faust2wasm on the noise.dsp file can be defined with the following parts:

<!-- Load 'faust2wasm' script generated .js file -->
<script src="noise.js"></script>

A slider to control the noise volume parameter is defined with:

<P> Noise volume:
<input type="range" oninput="changeVolume(event) "min="0" max="1" value="0.5" step="0.01"/>

The WebAudio context is created and the noise slide hander is defined with:

var isWebKitAudio = (typeof (webkitAudioContext) !== "undefined");
var audio_context = (isWebKitAudio) ? new webkitAudioContext() : new AudioContext();
var noise = null;

// Slider handler to change the 'noise' volume
function changeVolume(event)
{
    noise.setParamValue("/Noise/Volume", parseFloat(event.target.value));
}

A startnoise function which creates the Faust WebAudio node is defined with:

function startnoise()
{
    // Create the Faust generated node
    faust.createnoise(audio_context, 1024,
        function (node) {
            noise = node;
            console.log(noise.getJSON());
            // Print paths to be used with 'setParamValue'
            console.log(noise.getParams());
            // Connect it to output as a regular WebAudio node
            noise.connect(audio_context.destination);
        });
}

An finally the load handler is defined to activate the code:

window.addEventListener("load", startnoise);

Look at the Noise and OSC online pages for the complete code.

Note that pages loading an additional .wasm file cannot directly be loaded in Chrome. You’ll have to start a local server (using the python -m SimpleHTTPServer command for instance) and access them with their http:// based URL.

Generating Polyphonic WebAudio nodes

Assuming that the compiled Faust DSP file is polyphonic ready, a polyphonic ready WebAudio node can be created with the -poly parameter, and will generate the following constructor for the node (where the mydsp part will be replaced by the actual DSP name):

/**
* Create a 'polyphonic' ScriptProcessorNode Web Audio object 
* by loading and compiling the Faust wasm file 
* to be use for the voice, and allocating the number of needed voices
*
* @param context - the Web Audio context
* @param buffer_size - the buffer_size in frames
* @param polyphony - the number of polyphonic voices
* @param callback - a callback taking the created ScriptProcessorNode 
* as parameter, or null in case of error
*/
faust.createmydsp_poly = function(context, buffer_size, polyphony, callback)

Polyphonic nodes have an extended API to be controled with MIDI messages:

/**
* Instantiates a new polyphonic voice. 
*
* @param channel - the MIDI channel (0..15, not used for now)
* @param pitch - the MIDI pitch (0..127)
* @param velocity - the MIDI velocity (0..127)
*/
keyOn = function (channel, pitch, velocity) 
/**
* De-instantiates a polyphonic voice. 
*
* @param channel - the MIDI channel (0..15, not used for now)
* @param pitch - the MIDI pitch (0..127)
* @param velocity - the MIDI velocity (0..127)
*/
keyOff = function (channel, pitch, velocity)
/**
* Gently terminates all the active voices.
*/
allNotesOff = function ()

Look at the JavaScript public documentation section for the complete description.

Extended control with -comb parameter

The faust2wasm tool can be used with the -comb parameter to compile several DSP files and contatenate all JavaScript code in a unique resulting comb.js file (possibly to be used in -poly mode also).

Generating fully working self-contained HTML pages

The faust2webaudiowasm script can be used to generate a fully working self-contained HTML page, with a SVG/CSS a Graphical User Interface. From the osc.dsp Faust DSP source file, it will generate an osc.html file:

faust2webaudiowasm osc.dsp

Assuming that the compiled Faust DSP file is polyphonic ready, the -poly parameter can be used to generate a polyphonic MIDI controlable instrument, to be used with a MIDI application or device.

The -links generates the DSP processor SVG representation, and links to the original DSP file as well as generated SVG files, so that the HTML page can possibly be deployed as a reusable Faust DSP resource.

WebAssembly module optimization

Assuming that you have Binaryen tools installed on your machine, the faust2wasm and faust2webaudiowasm scripts can take an additional -opt parameter to allow WebAssembly module optimization.

Deploying dynamically compiled Faust WebAudio nodes

Since the libfaust library is available for the Web, it becomes possible to embed the complete dynamic compilation chain in a Web page, from the Faust DSP source to the executable WebAudio node. First the following resources (located on the Faust GitHub in architecture/webaudio folder) have to be loaded in the page:

<!-- Load 'libfaust' library and wrapper code -->
<script src="libfaust-wasm.js"></script>
<script src="webaudio-wasm-wrapper.js"></script>

Then the two following functions are used to generate factories, creating later on monophonic or polyphonic instances (this is necessary because of the way internal WebAssembly memory is managed):

/**
* Create a DSP factory from source code as a string to be used to create monophonic DSP 
*
* @param code - the source code as a string
* @param argv - an array of parameters to be given to the Faust compiler
* @param callback - a callback taking the created DSP factory as parameter, 
* or null in case of error
*/
faust.createDSPFactory = function (code, argv, callback) 
/**
* Create a DSP factory from source code as a string to be used to create polyphonic DSP 
*
* @param code - the source code as a string
* @param argv - an array of parameters to be given to the Faust compiler
* @param callback - a callback taking the created DSP factory as parameter, 
* or null in case of error
*/
faust.createPolyDSPFactory = function (code, argv, callback) 

The two following functions are used to generate monophonic or polyphonic Faust WebAudio nodes:

/**
* Create a ScriptProcessorNode Web Audio object from a factory
*
* @param factory - the DSP factory
* @param context - the Web Audio context
* @param buffer_size - the buffer_size in frames
* @param callback - a callback taking the created ScriptProcessorNode as parameter, 
* or null in case of error
*/
faust.createDSPInstance = function (factory, context, buffer_size, callback) 
/**
* Create a 'polyphonic' 'ScriptProcessorNode Web Audio object from a factory
*
* @param factory - the DSP factory
* @param context - the Web Audio context
* @param buffer_size - the buffer_size in frames
* @param polyphony - the number of polyphonic voices
* @param callback - a callback taking the created ScriptProcessorNode as parameter, 
* or null in case of error
*/
faust.createPolyDSPInstance = function (factory, context, buffer_size, polyphony, callback) 

The resulting nodes have the same API as statically compiled nodes described in the first section, so can be controlled the same way, including the polyphonic ones. Here is a code example using faust.createDSPFactory and faust.createDSPInstance:

var isWebKitAudio = (typeof (webkitAudioContext) !== "undefined");
var audio_context = (isWebKitAudio) ? new webkitAudioContext() : new AudioContext();
var dsp_code = "import(\"stdfaust.lib\"); vol = hslider(\"volume [unit:dB]\", 0, -96, 0, 0.1) : ba.db2linear : si.smoo; freq = hslider(\"freq [unit:Hz]\", 1000, 20, 24000, 1); process = vgroup(\"Oscillator\", os.osc(freq) * vol);";
var osc = null;
var libraries_url = "/modules/libraries/";

function startosc()
{
    // Prepare argv list
    var argv = [];
    argv.push("-ftz");
    argv.push("2");
    argv.push("-I");
    argv.push(libraries_url);

    // Dynamically create the Faust generated node from explicit DSP source in 'dsp_code'
    faust.createDSPFactory(dsp_code,
                            argv,
                            function (factory) {
                                faust.createDSPInstance(factory, audio_context, 1024
                                                        function (node) {
                                                            osc = node;
                                                            console.log(osc.getJSON());
                                                            // Print paths to be used with 'setParamValue'
                                                            console.log(osc.getParams());
                                                            // Connect it to output as a regular WebAudio node
                                                            osc.connect(audio_context.destination);
                                                        })});
}

The Dynamic OSC page demonstrates the dynamic OSC complete code (based on the example seen before). The Dynamic Organ page demonstrates a polyphonic organ instrument, which loads a DSP from an url, and ready to be controlled with a MIDI device or application. Look at the Dynamic Faust compiler page for a more complete use-case of the dynamic compiler.

Float denormal handling

A specific problem occurs when audio computation produces denormal float values, which is quite common with recursive filters, and can be extremely costly to compute on some processors like the Intel family for instance. A Flush To Zero (FTZ) mode for denormals can usually be set at hardware level, but it not yet available in the WebAssembly MVP version, which strictly conform to the IEEE 754 norm 8.

Thus an automatic software strategy which consists in adding FTZ code in all recursive loops has been implemented in the Faust compiler. To activate it, the -ftz compilation parameter must be used at compilation time.

The -ftz 1 mode adds a test in each recursive loop which uses the fabs function and a threshold to detect subnormal samples (slower). The -ftz 2 mode adds a test in each recursive loop which uses a mask to detect subnormal samples (faster).

Use for example the following line to active software denormal handing when using faust2wasm tool:

faust2wasm -ftz 2 foo.dsp 

The same for the faust2webaudiowasm tool:

faust2webaudiowasm -ftz 2 foo.dsp 

For dynamic compilation, the -ftz v flag will have to be added in the argv parameter in faust.createDSPFactory or faust.createPolyDSPFactory, like for instance:

faust.createPolyFactory(dsp_code, ['-ftz', '2'], callback);

2017-06-16: Using a custom memory allocator

From a DSP source file, the Faust compiler typically generates a C++ class. When a rdtable item is used on the source code, the C++ class will contain a table shared by all instances of the class. By default, this table is generated as a static class array, and so allocated in the application global static memory.

In some specific case (usually in more constrained deployment cases), managing where this data is allocated is crucial. By extension this post explains how a custom memory allocator can be used to precisely control the DSP memory allocation.

A new -mem compiler parameter has been added in the Faust compiler, starting from the 0.9.103 version (or 2.1.4 in Faust2 branch). This parameter will change the way static shared tables are generated. The table is allocated as a class static pointer allocated using a custom memory allocator, which has the following propotype:

struct dsp_memory_manager {

    virtual ~dsp_memory_manager() {}

    virtual void* allocate(size_t size) = 0;
    virtual void destroy(void* ptr) = 0;
};

Taking the following Faust DSP example:

process = (waveform {10,20,30,40,50,60,70}, %(7)~+(3) : rdtable), 
          (waveform {1.1,2.2,3.3,4.4,5.5,6.6,7.7}, %(7)~+(3) : rdtable);

Here is the generated code in default mode:

...
int mydsp::itbl0[7];
float mydsp::ftbl0[7];

static void classInit(int samplingFreq) {
    SIG0 sig0;
    sig0.init(samplingFreq);
    sig0.fill(7,itbl0);
    SIG1 sig1;
    sig1.init(samplingFreq);
    sig1.fill(7,ftbl0);
}

virtual void init(int samplingFreq) {
    classInit(samplingFreq);
    instanceInit(samplingFreq);
}

virtual void instanceInit(int samplingFreq) {
    instanceConstants(samplingFreq);
    instanceResetUserInterface();
    instanceClear();
}
...

The two itbl0 and ftbl0 tables are static class arrays. They are filled in the classInit method. The architecture code will typically call the init method (which calls classInit) on a given DSP, to allocate class related arrays and the DSP itself. If several DSP are going to be allocated, calling classInit only once then the instanceInit method on each allocated DSP is the way to go.

In the new -mem mode, the generated C++ code is now:

...
int* mydsp::itbl0 = 0;
float* mydsp::ftbl0 = 0;
dsp_memory_manager* mydsp::fManager = 0;

static void classInit(int samplingFreq) {
    SIG0 sig0;
    itbl0 = static_cast<int*>(fManager->allocate(sizeof(int) * 7));
    sig0.init(samplingFreq);
    sig0.fill(7,itbl0);
    SIG1 sig1;
    ftbl0 = static_cast<float*>(fManager->allocate(sizeof(float) * 7));
    sig1.init(samplingFreq);
    sig1.fill(7,ftbl0);
}

static void classDestroy() {
    fManager->destroy(itbl0);
    fManager->destroy(ftbl0);
}

virtual void init(int samplingFreq) {}

virtual void instanceInit(int samplingFreq) {
    instanceConstants(samplingFreq);
    instanceResetUserInterface();
    instanceClear();
}
...

The two itbl0 and ftbl0 tables are generated a class static pointers. The classInit method takes the additional dsp_memory_manager object used to allocate tables. A new classDestroy method is available to deallocate the tables. Finally the init method is now empty, since the architecure file is supposed to use the classInit/classDestroy method once to allocate and deallocate static tables, and the instanceInit method on each allocated DSP.

Control of the DSP memory allocation

An architecture file can now define its custom memory manager by subclassing the dsp_memory_manager abstract base class, and implement the two required allocate and destroy methods. Here is an example of a simple heap allocating manager:

struct malloc_memory_manager : public dsp_memory_manager {

    virtual void* allocate(size_t size)
    {
        void* res = malloc(size);
        cout << "malloc_manager: " << size << endl;
        return res;
    }

    virtual void destroy(void* ptr)
    {
        cout << "free_manager" << endl;
        free(ptr);
    }

};

Controlling the table memory allocation

To control table memory allocation, the architecture file will have to do:

// Allocate a custom memory allocator
malloc_memory_manager manager; 

// Setup manager for the class
mydsp::fManager = &manager;

// Allocate the dsp instance using regular C++ new
mydsp* dsp = new mydsp();

// Allocate static tables (using the custom memory allocator)
mydsp::classInit(48000);

// Initialise the given instance
dsp->instanceInit(48000);

...
...

// Deallocate the dsp instance using regular C++ delete
delete dsp;

// Deallocate static tables (using the custom memory allocator)
mydsp::classDestroy();

Controlling the complete DSP memory allocation

Full control the DSP memory allocation can be done using C++ placement new:

#include <new>

// Allocate a custom memory allocator
malloc_memory_manager manager; 

// Setup manager for the class
mydsp::fManager = &manager;

// Placement new using the custom allocator
mydsp* dsp = new(manager.allocate(sizeof(mydsp))) mydsp();

// Allocate static tables (using the custom memory allocator)
mydsp::classInit(48000);

// Initialise the given instance
dsp->instanceInit(48000);

...
...

// Calling the destructor
dsp->~mydsp();

// Deallocate the pointer itself using the custom memory allocator
manager.destroy(dsp);

// Deallocate static tables (using the custom memory allocator)
mydsp::classDestroy();

More complex custom memory allocators can be developed by refining this malloc_memory_manager example, possibly defining real-time memory allocators…etc… The OWL architecture file already uses this new custom memory allocator model.

This is a work in progress:

  • in the Faust2 branch, this model is still not supported yet beside the C++ backend
  • custom memory allocator is not yet supported is additional DSP classes (like the mydsp_poly defined in the achitecture/faust/dsp/poly-dsp.h header).

2017-04-26: Optimizing the DSP CPU usage

The Faust compiler has as lot of different compilation parameters to play with. Discovering them for a given DSP program is something that can be automated. Two measure_dsp and dsp_optimizer classes are available for developers to measure DSP CPU use directly in their code. Two more friendly faustbench and faustbench-llvm tools have been developed using them. They allow to discover the best Faust compiler parameters, to be used later on with faust2xx scripts, faustgen~ Max/MSP external or FaustLive.

The measure_dsp and dsp_optimizer DSP decorator classes

The measure_dsp class defined in the faust/dsp/dsp-bench.h file allows to decorate a given DSP object and measure its compute method CPU consumption. Results are given in Megabytes/seconds (higher is better). Here is a C++ code example of its use:

static void bench(dsp* dsp, const string& name)
{
    // Init the DSP
    dsp->init(48000);
    // Wraps it with a 'measure_dsp' decorator
    measure_dsp mes(dsp, 1024, 5);
    // Measure the CPU use
    mes.measure();
    // Print the stats
    cout << name << " CPU use : " << mes.getStats() << endl;
}

Only part of the Faust2 branch and defined in the faust/dsp/dsp-optimizer.h file, the dsp_optimizer class uses the libfaust library and its LLVM backend to dynamically compile DSP objects produced with different Faust compiler options, and then measure their DSP CPU. Here is a C++ code example of its use:

static void dynamic_bench(const string& dsp_source)
{
    // Init the DSP optimizer with the dsp_source to compile 
    // (either the filename or source code string)
    dsp_optimizer optimizer(dsp_source, "/usr/local/share/faust", "", 1024);
    double value;
    // Discover the best set of parameters
    vector<string> options = optimizer.findOptimizedParameters(value);
    // Print the result
    cout << "Best value is for '" << argv[1] << "' is : " << value << " with ";
    for (int i = 0; i < options.size(); i++) {
        cout << options[i] << " ";
    }
    cout << endl;
}

Using the faustbench tool

The faustbench tool uses the C++ backend to generate a set of C++ files produced with different Faust compiler options. All files are then compiled in a unique binary that will measure DSP CPU of all versions of the compiled DSP. The tool is supposed to be launched in a terminal, but it can be used to generate an iOS project, ready to be launched and tested in Xcode. Here are the available options:

faustbench [-ios] [Additional Faust options (-vec -vs 8...)] <file.dsp>
Use '-ios' to generate an iOS project
Use 'export CXX=/path/to/compiler' before running faustbench to change the C++ compiler
Use 'export CXXFLAGS=options' before running faustbench to change the C++ compiler options

Here is a trace of its use:

faustbench karplus32.dsp 
Selected compiler is g++ with CXXFLAGS = -Ofast
-scal : 77.5123
-vec -lv 0 -vs 4 : 64.2194
-vec -lv 0 -vs 8 : 80.8951
-vec -lv 0 -vs 16 : 106.244
.....
-vec -lv 1 -vs 128 -g : 130.635
-vec -lv 1 -vs 256 -g : 134.335
-vec -lv 1 -vs 512 -g : 135.352
Best value is : 136.235 with -vec -lv 0 -vs 512

Using the faustbench-llvm tool

Available in the faust2 branch only, the faustbench-llvm tool uses the libfaust library and its LLVM backend to dynamically compile DSP objects produced with different Faust compiler options, and then measure their DSP CPU. In the main Faust folder, use make bench && sudo make install to build and install the tool. Here is a trace of its use:

faustbench-llvm karplus32.dsp 
Estimate timing parameters
-scal : 21.1269
duration = 0.102801 count = 24318
Discover best parameters option
-scal : 21.1034
-vec -lv 0 -vs 4 : 42.0734
-vec -lv 0 -vs 8 : 55.3725
-vec -lv 0 -vs 16 : 85.3855
.....
-vec -lv 1 -vs 128 -dfs : 133.974
-vec -lv 1 -vs 256 -dfs : 139.12
-vec -lv 1 -vs 512 -dfs : 91.8424
Refined with -mcd
-vec -lv 0 -vs 256 -g -mcd 2 : 83.5555
-vec -lv 0 -vs 256 -g -mcd 4 : 138.519
-vec -lv 0 -vs 256 -g -mcd 8 : 140.122
-vec -lv 0 -vs 256 -g -mcd 16 : 141.558
-vec -lv 0 -vs 256 -g -mcd 32 : 139.454
-vec -lv 0 -vs 256 -g -mcd 64 : 143.405
-vec -lv 0 -vs 256 -g -mcd 128 : 142.975
-vec -lv 0 -vs 256 -g -mcd 256 : 139.345
Best value is for 'karplus32.dsp' is : 142.473 with -vec -lv 0 -vs 256 -dfs -mcd 64 w

2017-02-21: Faust meets JUCE

JUCE is an open-source cross-platform C++ application framework, used for the development of desktop and mobile applications. JUCE is used in particular for its GUI and plugins libraries.

A set of architecture files have been developed to deploy standalone or plugins built from Faust code. They allow to automatically generate the GUI from the Faust program, possibly supporting polyphonic instruments, and be controlled by MIDI or OSC messages.

The architecture files are then combined to produce ready to compile JUCE applications or plugins, using tools that are part of the Faust distribution. They can also be accessed using the Faust online compiler.

faust2juce script

faust2juce transforms a Faust DSP program into a fully working JUCE standalone application or plugin, which can possibly be controlled with MIDI or OSC messages. Read its complete description here. You’ll have to get a recent github version of Faust tree to use it.

Using the online compiler

The Faust online compiler has been updated to provide new ‘juce’ targets. Note that only some of the possible compilation options are availble for now:

  • the application target produces a standalone MIDI controlable application (using Faust polyphonic code if the Faust source code is polyphonic aware)

  • the plug-in target produces a MIDI controlable mono or polyphonic plugin (using Faust polyphonic code if the Faust source code is polyphonic aware)

  • the jsynth target produces a MIDI controlable mono or polyphonic plugin (using JUCE polyphonic Synthesizer if the Faust source code is polyphonic aware)

Directly using faust2juce provides the full control of the generated target with access to all possible compilation parameters.

Graph of Faust generated plugins

Here is an example of three Faust generated plugins running in JUCE plugin host:

Using libfaust and LLVM

An alternative to faust2juce static-compilation model, is to use Oliver Larkin’s juce_faustllvm module, also used in his pMix2 tool.


2017-01-13: Faust WebAssembly backend

WebAssembly was born with the premise of creating a safe, portable and fast to load and execute format suitable for the web. WebAssembly its not a programing language but a compilation target with a text and binary specs. That means that other low level languages like C/C++, Rust, Swift, etc. can compile to WebAssembly.

Specified and developed by principal browser compagnies (Google, Mozilla, Microsoft and Apple), this new format aims to finally replace the more hackish “asm.js” format initialy developed by Mozilla.

Development versions of Chrome and Firefox can already execute it. To get an early preview of this experimental technology, at your own risk:

  • on Chrome Canary, open chrome://flags/#enable-webassembly and enable the switch

  • on Firefox Nightly, open about:config and set javascript.options.wasm to true

See a preview of Microsoft Edge support and follow Safari support on WebKit’s feature status.

WebAssembly backends

New WebAssembly backends have been added in the faust2 development branch. They allow to generate textual or binary WebAssembly code.

‘wast’ textual backend

The ‘wast’ backend allows to generate textual WebAssembly code (in s-expression like format). Note that as of january 2017, the official textual format is not yet fully specified, thus we follow the format used in the binaryen tool.

Use the following command to generate the textual output in the terminal for a given foo.dsp file.

faust -lang wast foo.dsp

The following command:

faust -lang wast foo.dsp -o foo.wast

will generate the foo.wast textual WebAssembly output file as well as an additional foo.js JavaScript file containing glue code.

‘wasm’ binary backend

The ‘wasm’ backend allows to generate binary WebAssembly code.

Use the following command to generate the binary output in the terminal for a given foo.dsp file.

faust -lang wasm foo.dsp

The following command:

faust -lang wasm foo.dsp -o foo.wasm

will generate the foo.wast binary WebAssembly output file as well as an additional foo.js JavaScript file containing glue code.

Generating static HTML pages

WebAssembly code can be feeded into WebAudio JavaScript nodes, which can then be used like any other native WebAudio node. Two scripts are available to generate static WebAudio html pages from a given foo.dsp source file with the generated html/css/svg user interface:

faust2webaudiowast foo.dsp

will generate the textual WebAssembly output, use binaryen wasm-as tool to convert the wast to wasm format (you’ll have to compile and install the binaryen tools on your machine), and produce a self-contained html page.

faust2webaudiowasm foo.dsp

will generate the binary WebAssembly output that can directly be loaded by the produced self-contained html page.

Page containing polyphonic instruments can be generated with the following commands:

faust2webaudiowast -poly foo.dsp 

to use the ‘wast’ backend and a polyphonic ready foo.dsp, and create a self-contained html page ready to be used with a MIDI instrument.

faust2webaudiowasm -poly foo.dsp 

to use the ‘wasm’ backend and a polyphonic ready foo.dsp, and create a self-contained html page ready to be used with a MIDI instrument.


2016-10-17: Faust Awards 2016: Ambitools !

The Faust Open Source Software Competition aims at promoting innovative high-quality free audio software developed with Faust, a functional programming language for realtime signal processing and sound synthesis. The competition is sponsored by GRAME, Centre National de Création Musicale

Faust Award 2016 to Ambitools

The Faust Award 2016 was attributed by an international committee composed of :

  • Jean-Louis Giavitto (IRCAM, Paris, France),
  • Albert Graef (Johannes Gutenberg U., Mainz, Germany),
  • Pierre Jouvelot (Ecole des Mines, Paris, France),
  • Victor Lazzarini (Maynooth U., Maynooth, Ireland),
  • Romain Michon (Stanford U., Palo Alto, USA)
  • Yann Orlarey (GRAME, Lyon, France),
  • Dave Phillips (musician, journalist, and educator, USA)
  • Laurent Pottier (U. Jean Monnet, Saint-Etienne, France),
  • Julius Smith (Stanford U., Palo Alto, USA)

to Ambitools, a set of tools for real-time 3D sound field synthesis using higher order ambisonics (HOA).

Ambitools is developed by Pierre Lecomte, a PhD candidate at Conservatoire National des Arts et Métiers and Sherbrooke University. The core of the sound processing is written in Faust. The tools contain HOA encoders, decoders, binaural-filters, HOA signals transformations, spherical VU-Meter, etc. and can be compiled in various plug-ins format under Windows, Mac OSX, and Linux.

The jury praised the quality and the usefulness of Ambitools: a really useful and technically advanced Faust app and an impressive technical achievement ! Check the demo.

The committee was also very impressed by the quality of two other projects :

  • Voice of Faust, a voice synthesizer/effects machine by Bart Brouns (demo).
  • PMix, a graphical patcher, preset interpolator and JIT compiler for FAUST by Oliver Larkin (demo).

Faust Student Software Competition to TouchVoices

In parallel to the main competition, we introduced this year a junior competition: the Faust Student Software Competition, intended to promote small but interesting Faust applications, typically written as student projects.

The student prize was awarded to TouchVoices (by Pierre-Adrien Théo, RIM Master student at University Jean Monnet) a real-time web application allowing to capture, playback and transform sound loops. Here is a video of Pierre-Adrien Théo during a performance with TouchVoices.

A very close competitor was SuperBeatRepeater (by Vincent Rateau, of SuperDirt fame), a sample accurate beat repeater. Don’t miss the demo!


2016-08-30: The first FAUST book is Korean !

Sound Programming using FAUST”, written by Jin-Wook Chae, an experienced audio developer and sound engineer (right) and Hyun-Hoo Jung (left), is the very first book ever published on FAUST.

While the book is written in Korean, I was able to really appreciate the choice of the examples and the elegance as well as the high quality of the code. I am sure it will be an invaluable tool to promote FAUST in Korea among sound engineering, computer music students and more generally any person interested in sound programming.

This book is for people desiring to produce musical instruments or sound processors. I have always been instructing my students that the ultimate importance is to discover interesting ideas about the sound. In spite of that, I have often relied on an unflattering response such as “you may need to learn a programming language like C/C++…” when a student asked for help with how to execute his/her ideas related to sound.

Now I am pleased to recommend the use of FAUST to bring such ideas into execution. This is an easy self-study guide that can help to do just that. Now I can confidently tell anybody pursuing sound or electronic music that their exciting and brilliant idea about sound is what truly counts!

So, really, how do we execute our ideas? Today I am introducing you to FAUST and to this book which you will find immensely helpful in terms of how to use FAUST to bring your fabulous ideas into reality.

Jinwook Chae


2016-06-30: Faust interpreter backend

A new ‘interpreter’ backend has been added in the faust2 development branch. It allows to execute Faust programs without using the LLVM dynamic compiler chain.

Interpreter compilation chain

The dynamic compilation chain allows developers to embed the Faust compiler technology directly in their application or plugins. Faust2 development branch uses an intermediate FIR representation (Faust Imperative Representation), which can be translated to several output languages. An LLVM backend has been previously developed to allows applications to compile a DSP source into executable code in memory, bypassing the external compiler requirement.

In some specific situations, embedding the LLVM chain is not possible : for instance Apple does not allow to deploy dynamic compilers on iOS. Thus having an interpreter backend allows to get around this problem and still make Faust code run on those platforms.

Interpreter backend

The interpreter backend translates the FIR intermediate language into instructions for a virtual machine. A pure C++ interpreter for this instruction set has been implemented.

Running and performances

The interpreter backend translates the FIR intermediate language into bytecode for a virtual machine. It allows to run programs about 4 to 5 slower than native speed. Moreover this interpreter can be compiled in a special ‘trace’ mode to automatically detect various execution errors : invalid heap access, mathematical errors or warnings (division by zero, integer overloading….) which helps us to check the compiler semantic and code generation quality.

Deployment for developers

Given a Faust source code (as a file or a string), calling the createInterpreterDSPFactoryXXX function runs the compilation chain (Faust + interpreter) and generates the “prototype” of the class, as a interpreter-dsp-factory pointer.

class interpreter_dsp_factory : public dsp_factory {

    public: 

        /* Return Factory name */
        std::string getName();

        /* Return Factory SHA key */
        std::string getSHAKey();

        /* Return Factory expanded DSP code */
        std::string getDSPCode();

        /* Creates a new dsp instance */
        dsp* createDSPInstance();
};

Note that the library keeps an internal cache of all allocated factories so that the compilation of the same DSP code, that is same source code and same set of ‘normalized’ (= sorted in a canonical order) compilations options, will return the same (reference counted) factory pointer. You will have to explicitly use deleteInterpreterDSPFactory to properly decrement the reference counter when the factory is no more needed. You can get a unique SHA1 key of the created factory using its getSHAKey method.

Next, the createDSPInstance function, corresponding to the new className of C++, instantiates a interpreter-dsp pointer to be used through its interface, connected to the audio chain and controller interfaces. When finished, simply use delete to destroy the dsp instance.

class interpreter_dsp : public dsp {

    public:

        void metadata(Meta* m);

        int getNumInputs();
        int getNumOutputs();

        void init(int samplingRate);
        void instanceInit(int samplingRate);
        dsp* clone();

        void buildUserInterface(UI* inter);
        int getSampleRate();

        void compute(int count, FAUSTFLOAT** input, FAUSTFLOAT** output);

};

Since interpreter_dsp is a subclass of the dsp base class, an object of this type can be used with all already available audio and UI classes, in essence reusing all architecture files already developed for the static C++ class compilation scheme (like OSCUI, httpdUI interfaces etc.), see Developing a new architecture file.

Saving/restoring the factory

After the DSP factory has been compiled, your application or plugin may want to save/restore it in order to save Faust to interpreter bytecode compilation at next use. To get the internal factory compiled code, several functions are available:

  • writeInterpreterDSPFactoryToMachine allows to get the interpreter bytecode as a string, writeInterpreterDSPFactoryToMachineFile allows to save the interpreter bytecode in a file,

To re-create a DSP factory from a previously saved code, several functions are available:

  • readInterpreterDSPFactoryFromMachine allows to create a DSP factory from a string containing the interpreter bytecode, readInterpreterDSPFactoryFromMachineFile allows to create a DSP factory from a file containing the interpreter bytecode.

The complete API is available and documented in the installed faust/dsp/interpreter-dsp.h header.


2016-04-07: Faust and the Web Audio API (3)

The Faust compiler can now directly be used in a Web page. Thanks to the Emscripten compiler, the Faust compiler itself can be compiled to asm.js JavaScript. This has been done by compiling the libfaust C++ library to the libfaust.js JavaScript library, that exports a unique entry point.

Compiling DSP to JavaScript (asm.js)

The libfaust.js exported function createAsmCDSPFactoryFromString(…) allows to create a DSP factory from a given DSP program as a source string and a set of compilations parameters, uses the Faust compiler asm.js backend, and produces the complete asm.js module and additional pure JavaScript methods as a string.

Then calling JavaScript ‘eval’ function on this string compiles it in the browser. The dynamically created asm.js module and additional pure JavaScript methods can then be used.

This internal code in then wrapped with additional JavaScript code. A DSP “factory” will be created from the DSP source code with the following ‘synchronous’ code (if using the ‘libfaust.js’ library):

var factory = faust.createDSPFactory(code, arguments);

or possibly (if using the ‘libfaustworker.js’ library in the ‘asynchronous’ model):

faust.createDSPFactory(code, arguments, callback);

where ‘code’ is the DSP source as a string, and ‘arguments’ is an array of parameters to be given to the Faust compiler (like ‘-vec’, ‘-vs 512’…), and ‘callback’ is a function taking the created ‘factory’ as argument.

When no more used, you’ll have to explicitly use the following code the deallocate the factory:

faust.deleteDSPFactory(factory);

Your application may want to save the already compiled factory as asm.js/JavaScript code to speed-up possible restore at later time:

var machine_code = faust.writeDSPFactoryToMachine(factory);

And restore the factory with the following code:

var factory = faust.readDSPFactoryFromMachine(machine_code);

Using DSP instances

A fully working DSP “instance” as a Web Audio node is then created with the code:

var dsp = faust.createDSPInstance(factory, audio_context, buffer_size);

When no more used, you’ll have to explicitly use the following code to deallocate the instance:

faust.deleteDSPInstance(dsp);

This instance can be used like the statically compiled one, as previously described in this page.

Polyphonic instruments

Polyphonic instruments can be produced. For a given ‘factory’ the following code will create a 16 voices polyphonic instance:

var dsp = faust.createPolyDSPInstance(factory, audio_context, buffer_size, 16);

This instance can be used like the statically compiled one, as previously described in this page.

Using Faust JavaScript library

The Emscripten compiled Faust library can be used in two ways. Either using the ‘libfaust.js’ library:

<script src="libfaust.js"></script>
<script src="webaudio-asm-wrapper.js"></script>

or if using worker mode with the following code which loads the ‘libfaustworker.js’ library:

<script src="webaudio/webaudio-asm-worker-wrapper.js"></script>

2016-02-05: Faust Award 2016

Faust Award 2016: deadline June 1, 2016

The Faust Open-Source Software Competition is intended to promote innovative high-quality free audio software developed with the Faust programming language, as well as development tools build around the Faust compiler itself. The Faust Open-Source Software award will be attributed to the best submission by an international committee of leading experts in the field. The competition is sponsored by Grame, centre national de création musicale. The winning software will receive a 2000€ price to encourage its authors. The results will be announced July 15, 2016.

To participate, the software must be provided with source code and licensed with a Free/Open Source license. A substantial part of the software must be written in Faust and the Faust source code must be provided. As part of the review process, the software will be built from the sources. All source code, license, video demonstration, installation instructions, and any other documentation must be available on a public web page. License compatibility with other open source software is encouraged. Dependencies on non-open source third-party software are discouraged, with the exception of operating systems and freely available commercial packages.

Authors are required to prepare a video demonstrating the software. This video must be done carefully, and should convincingly present the qualities of the software. The submission must also contain any useful documentation, including examples of how the provided software might be used, existing prototypes that use the software, download statistics or other public usage information. The criteria for judging submissions includes broad applicability and potential impact, novelty, technical depth, reusability, etc.

Junior Competition

In parallel to the Faust Open-Source Software Competition we introduce this year a junior competition, the Faust Student Software Competition, with a 200€ prize for the winner. The Faust Student Software Competition is intended to promote interesting audio processing and synthesis applications written in Faust in a single file in less than 1000 words. The word count is done after removing the comments from the code:

cat foo.dsp | stripcmt | wc -w.

The use of the standard Faust libraries is strongly encouraged. They don’t take part in the word count.

Important dates

  • Start of the competition: February 8, 2016
  • Software Submission Deadline: June 1, 2016
  • Results of the competition: July 1, 2016

Submission Guidelines

Authors interested in participating in the Faust Open Source Software Competition or the Faust Student Software Competition should send a submission email to faustaward@grame.fr with a PDF file attached containing the following information:

  • Title of submission,
  • Category of submission (Faust Open Source Software Competition or Faust Student Software Competition),
  • Name, email and affiliation of the main author,
  • Names, emails and affiliations of other authors,
  • A permanent link for the open source software (e.g., Sourceforge, GitHub, Google Code, etc.),
  • A permanent link for the video demonstration (e.g., YouTube, Vimeo, etc.),
  • A link to a compressed archive file that contains the software (source code, documentation, build/install instructions, and licenses). Comprehensive and clear build/install instructions will be a crucial component of any submission. The committee will make a reasonable effort to build the software for the top contributions, but if they are unable to make the software run, it will be excluded from the competition.

International Committee

  • Jean-Louis Giavitto (IRCAM, Paris, France),
  • Albert Gräf (Johannes Gutenberg U., Mainz, Germany),
  • Pierre Jouvelot (Ecole des Mines, Paris, France),
  • Victor Lazzarini (Maynooth U., Maynooth, Ireland),
  • Romain Michon (CCRMA, Stanford , USA)
  • Yann Orlarey (Grame, Lyon, France),
  • Dave Phillips (Musician/Journalist, Findlay, USA)
  • Laurent Pottier (U. Jean Monnet, Saint Etienne, France),
  • Julius Smith (CCRMA, Stanford , USA)

Previous Winners

  • 2015: Guitarix, by Hermann Meyer and Andreas Degert

2016-01-14: Controlling with MIDI

Faust programs can be controlled using MIDI messages. Thanks to the metadata mechanism, all UI elements (sliders, button, bargraph…) can send and receive MIDI data.

Adding MIDI messages description in the dsp source code

MIDI control messages are described as metadata in UI elements. They are decoded by a new MidiUI class that will parse incoming MIDI messages and update the appropriate control parameters, or send MIDI when the UI elements (sliders, buttons….) are moved.

Description of the possible standard MIDI messages

  • [midi:ctrl num] in a slider or bargraph will map the UI element value to (0,127) range. When used with a button or checkbox, 1 will be mapped to 127, 0 will be mapped to 0,
  • [midi:keyon pitch] in a slider or bargraph will register the UI element’s state-variable to be driven by MIDI note-on velocity (an integer between 0 and 127) of the specified key between 0 and 127. When used with a button or checkbox, 1 will be mapped to 127, 0 will be mapped to 0,
  • [midi:keyoff pitch] in a slider or bargraph will register the UI element’s state-variable to be driven by MIDI note-off velocity (an integer between 0 and 127) of the specified key between 0 and 127. When used with a button or checkbox, 1 will be mapped to 127, 0 will be mapped to 0,
  • [midi:key pitch] in a slider or bargraph will register the UI element’s state-variable to be driven by MIDI note-on velocity (an integer between 0 and 127) of the specified key between 0 and 127. When used with a button or checkbox, 1 will be mapped to 127, 0 will be mapped to 0. Note-on and note-off events will be handled,
  • [midi:keypress pitch] in a slider or bargraph will map the UI element value to keypress value in the (0,127) range. When used with a button or checkbox, 1 will be mapped to 127, 0 will be mapped to 0,
  • [midi:pgm num] in a slider or bargraph will map the UI element value to the progchange value, so “progchange” message with the same “num” value will be sent. When used with a button or checkbox, 1 will send the “progchange” message with “num” value, 0 will send nothing,
  • [midi:chanpress num] in a slider or bargraph will map the UI element value to the chanpress value, so “chanpress” message with the same “num” value will be sent. When used with a button or checkbox, 1 will send the “chanpress” message with “num” value, 0 will send nothing,
  • [midi:pitchwheel] in a slider or bargraph will map the UI element value to (0,16383) range. When used with a button or checkbox, 1 will be mapped to 16383, 0 will be mapped to 0.

MIDI synchronization

MIDI clock based synchronization can be used to slave a given Faust program. The following three messages need to be used:

  • [midi:start] in a button or checkbox will trigger a value of 1 when a start MIDI message is received
  • [midi:stop] in a button or checkbox will trigger a value of 0 when a stop MIDI message is received
  • [midi:clock] in a button or checkbox will deliver a sequence of successive 1 and 0 values each time a clock MIDI message is received, seen by seen by Faust code as a square command signal, to be used to compute higher level information. .

A typical Faust program will then use the MIDI clock stream to possibly compute the BPM information, or for any synchronization need it may have. Here is a simple example of a sinusoide generated which a frequency controlled by the MIDI clock stream, and starting/stopping when receiving the MIDI start/stop messages:

import("stdfaust.lib");

// square signal (1/0), changing state at each received clock
clocker   = checkbox("MIDI clock[midi:clock]");    

// ON/OFF button controlled with MIDI start/stop messages
play      = checkbox("ON/OFF [midi:start] [midi:stop]");    

// detect front
front(x)  = (x-x') != 0.0;      

// count number of peaks during one second
freq(x)   = (x-x@ma.SR) : + ~ _;   

process   = os.osc(8*freq(front(clocker))) * play;

Activating the MIDI interface (for developers)

For multi-platform support, the MidiUI class uses the RTMidi framework. Add the following line into your code to get it compiled:

#include "faust/midi/RtMidi.cpp"

As with other UI objects, MidiUI is to be given as parameter to the dsp buildUserInterface method:

MidiUI midiinterface(name);
DSP->buildUserInterface(&midiinterface);
....
midiinterface.run();

To be used with JACK MIDI, use the jackaudio_midi class (instead of the standard jackaudio JACK API using class):

jackaudio_midi audio;
audio.init(name, DSP);
...

// JACK MIDI aware object used by the MidiUI MIDI messages handling class
MidiUI midiinterface(&audio);  
DSP->buildUserInterface(&midiinterface);
....
midiinterface.run();

Activating the MIDI interface (for users)

Several architecture files and associated scripts have been updated to handle MIDI aware dsp code:

  • use faust2caqt -midi foo.dsp to create a MIDI aware CoreAudio/QT application on OSX
  • use faust2jaqt -midi foo.dsp to create a MIDI aware JACK/QT application on Linux and OSX
  • use faust2ios -midi foo.dsp to create a MIDI aware iOS application
  • use faust2alsa -midi foo.dsp to create a MIDI aware ALSA/GTK application on Linux
  • use faust2alqt -midi foo.dsp to create a MIDI aware ALSA/QT application on Linux.

Note that the buildUserInterface method for polyphonic instruments (defined using the mydsp_poly class) called with a MidiUI object, will automatically connect to the MIDI system, to be ready to handle incoming keyOn/keyOff MIDI messages and so on. See Creating polyphonic instruments page for more informations.


2016-01-13: Creating polyphonic instruments

Polyphonic instruments can be created by “combining” several voices using a specific architecture file, with the single voice described by a Faust DSP program. The architecture file takes care of dynamic voice allocation and control MIDI messages decoding and mapping.

Description of the polyphonic instrument

First you’ll have to describe the voice in Faust, then use the mydsp_poly class to combine several voices.

Programming the instrument voice

By convention Faust architecture files with polyphonic capabilities expect to find a user interface parameters with the following freq, gain and gate names. The metadata declare nvoices “8”; kind of line with a desired value of voices can be added in the source code.

In case of MIDI control, the freq (which should be a frequency) will be automatically mapped to MIDI note numbers, gain (which should be a value between 0 and 1) to velocity and freq to keyon/keyoff events. Thus, gate can be used as a trigger signal for any envelope generator, etc.

Look at the A Simple Organ post for a complete example.

Allocating the polyphonic instrument

Use the faust/dsp/poly-dsp.h file to wrap the dsp voice into the polyphonic architecture. This file defines the mydsp_poly class (a sub-class of base class dsp) that maintains and array of dsp objects, manage dynamic voice allocation, control MIDI messages decoding and mapping, and mixing of all running voices (stopping a running voice, when its output level decreases below a given threshold).

As a sub-class of dsp, the mydsp_poly class redefines the buildUserInterface method. By convention all allocated voices are grouped in a global “tabgroup”, so that a user interface builder may display them separately. The first tab contains a Voices group that can be used to change parameters on all voices at the same time. A Panic button can be used to stop running voices.

This dsp object can be used as usual and connected with the wanted audio driver and possibly other UI control objects like OSCUI, httpdUI, etc. Having this UI hierarchical view allows for instance complete OSC control of each single voice and its control parameters.

Allocation of a polyphonic instrument takes the DSP to be used for one voice, the desired number of voices, the dynamic voice allocation control state, and the ‘group’ state which controls if the Voices group as well as separated voices are displayed or not:

DSP = new mydsp_poly(dsp, nvoices, true, false);

With the following the code, note that a polyphonic instrument may be used outside of a MIDI control context, so that all voices will be always running:

DSP = new mydsp_poly(dsp, nvoices, false, true);

Controlling the polyphonic instrument

Note that mydsp_poly class is also ready for MIDI control and can react to keyon/keyon and pitchwheel messages. You can also add other MIDI control parameters directly in the dsp source code. See Controlling with MIDI post for more informations.

Creating the polyphonic instrument

Several architecture files and associated scripts have been updated to handle polyphonic instruments.

As an example on OSX, the script faustcaqt foo.dsp can be used to create a polyphonic CoreAudio/QT application. The desired number of voices is either declared in a nvoices metadata or changed with the -nvoices num additional parameter (-nvoices parameter takes precedence over the metadata value). MIDI control is activated using the -midi parameter.

The number of allocated voice can possibly be changed at runtime using the -nvoices parameter to change the default value (so using ./foo -nvoices 16 for instance).

Several other scripts (faust2jaqt, faust2ios…) have been adapted using the same conventions.

Adding an output effect

Polyphonic instruments can be used with a global output effect. Putting that effect in the main Faust code is not a good idea since it would be instantiated for each voice which would be very inefficient.

The -effect effect.dsp paramter has to be used in the script. The number of outputs of the instrument must the same as the number of inputs of the effect.

Polyphonic ready faust2xx scripts will then compile the polyphonic instrument and the effect, combine them in sequence, and create a ready to use dsp. As an example on OSX, faustcaqt -nvoices 8 -effect freeverb.dsp -midi synth.dsp script can be used to combine the instrument and the output effect, and make it MIDI controllable.

Polyphonic instrument as plugin

The previously described polyphonic architecture has been written to develop standalone applications and it still rather basic. Note that much more sophisticated polyphonic aware plugins have already been developed:

  • Yan Michalevsky’s VSTi support is part of the regular Faust distribution. Look at the vsp.cpp architecture file, to be used with the faust2vsti script.
  • Albert Graef LV2 and VSTi separately developed but which are also part of the standard Faust distribution.

2016-01-12: Using the dynamic compilation chain

The dynamic compilation chain allows developers to embed the Faust compiler technology directly in their application or plugins. Thanks to the awesome LLVM technology combined with libfaust, the new library version of the Faust compiler, Faust DSP programs can now directly be compiled and executed on the fly at full speed.

Dynamic compilation chain

Faust2 development branch uses an intermediate FIR representation (Faust Imperative Representation), which can be translated to several output languages. The FIR language describes the computation performed on the samples in a generic manner. It contains primitives to read and write variables and arrays, do arithmetic operations, and define the necessary control structures (for and while loops, if structure etc.). The language of signals (internal to the Faust compiler) is now compiled in FIR intermediate language.

To generate various output languages, several backends have been developed: for C, C++, Java, JavaScript, asm.js, and LLVM IR. The native LLVM based compilation chain is particularly interesting: it provides direct compilation of a DSP source into executable code in memory, bypassing the external compiler requirement.

LLVM

LLVM (formerly Low Level Virtual Machine) is a compiler infrastructure, designed for compile-time, link-time, run-time optimization of programs written in arbitrary programming languages. Executable code is produced dynamically using a “Just In Time” compiler from a specific code representation, called LLVM IR. Clang, the “LLVM native” C/C++/Objective- C compiler is a front-end for LLVM Compiler. It can, for instance, convert a C or C++ source file into LLVM IR code. Domain-specific languages like Faust can easily target the LLVM IR. This has been done by developing a special LLVM IR backend in the Faust compiler.

Compiling in memory

The complete chain goes from the Faust DSP source code, compiled in LLVM IR using the LLVM backend, to finally produce the executable code using the LLVM JIT. All steps take place in memory, getting rid of the classical file based approaches. Pointers to executable functions can be retrieved from the resulting LLVM module and the code directly called with the appropriate parameters.

In the Faust2 development branch, the Faust compiler has been packaged as an embeddable library called libfaust, published with an associated API that imitates the concept of oriented-object languages, like C++. Given a Faust source code (as a file or a string), calling the createDSPFactoryXXX function runs the compilation chain (Faust + LLVM JIT) and generates the “prototype” of the class, as a llvm_dsp_factory pointer.

class llvm_dsp_factory {

 public: 
    
    /* Return Factory name */
    std::string getName();
    
    /* Return Factory LLVM target */
    std::string getTarget();
    
    /* Return Factory SHA key */
    std::string getSHAKey();

    /* Return Factory expanded DSP code */
    std::string getDSPCode();
};

Note that the library keeps an internal cache of all allocated factories so that the compilation of the same DSP code, that is same source code and same set of ‘normalized’ (= sorted in a canonical order) compilations options, will return the same (reference counted) factory pointer. You will have to explicitly use deleteDSPFactory to properly decrement the reference counter when the factory is no more needed. You can get a unique SHA1 key of the created factory using its getSHAKey method.

Next, the createDSPInstance function, corresponding to the new className of C++, instantiates a llvm_dsp pointer to be used through its interface, connected to the audio chain and controller interfaces. When finished, use deleteDSPInstance to destroy the dsp instance.

class llvm_dsp : public dsp {
    
 public:
    
    void metadata(Meta* m);
    
    int getNumInputs();
    int getNumOutputs();
    
    void init(int samplingFreq);
    void buildUserInterface(UI* ui_interface);
    void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs);
    
    llvm_dsp* copy();
};

Since llvm_dsp is a subclass of the dsp base class, an object of this type can be used with all already available audio and UI classes, in essence reusing all architecture files already developed for the static C++ class compilation scheme (like OSCUI, httpdUI interfaces etc.), see Developing a new architecture file.

Saving/restoring the factory

After the DSP factory has been compiled, your application or plugin may want to save/restore it in order to save Faust to LLVM IR compilation or even JIT compilation time at next use. To get the internal factory compiled code, several functions are available:

  • writeDSPFactoryToIR allows to get the LLVM IR (in textual format) as a string, writeDSPFactoryToIRFile allows to save the LLVM IR (in textual format) in a file,
  • writeDSPFactoryToBitcode allows to get the LLVM IR (in binary format) as a string, writeDSPFactoryToBitcodeFile allows to save the LLVM IR (in binary format) in a file,
  • writeDSPFactoryToMachine allows to get the executable machine code as a string, writeDSPFactoryToMachineFile allows to save the executable machine code in a file.

To re-create a DSP factory from a previously saved code, several functions are available:

  • readDSPFactoryFromIR allows to create a DSP factory from a string containing the LLVM IR (in textual format), readDSPFactoryFromIRFile allows to create a DSP factory from a file containing the LLVM IR (in textual format),
  • readDSPFactoryFromBitcode allows to create a DSP factory from a string containing the LLVM IR (in binary format), readDSPFactoryFromBitcodeFile allows to create a DSP factory from a file containing the LLVM IR (in binary format),
  • readDSPFactoryFromMachine allows to create a DSP factory from a string containing the executable machine code, readDSPFactoryFromMachineFile allows to create a DSP factory from a file containing the executable machine code.

Additional functions

Some additional functions are available in the API:

  • expandDSPFromString/expandDSPFromFile creates a ‘self-contained’ DSP source string where all needed librairies have been included. All compilations options are ‘normalized’ and included as a comment in the expanded string,
  • generateAuxFilesFromString/generateAuxFilesFromFile: from a DSP source string or file, generates auxiliary files: SVG, XML, ps… depending of the ‘argv’ parameters.

Using the libfaust library

The libfaust library is part of the Faust2 development branch. You’ll have to compile and install it. Then look at the installed faust/dsp/llvm-dsp.h header for a complete description of the API. Note that faust/dsp/llvm-c-dsp.h is a pure C version of the same API.

Use case examples

The dynamic compilation chain has been used in several projects:


2016-01-11: Developing a new architecture file

Being a high-level specification language, the Faust code says nothing about the audio drivers, the GUI toolkit, or any other non-GUI interface to be used to control the dsp. It is the role of the architecture file to describe how to relate the dsp code to the external world. This approach allows a single Faust program to be easily deployed to a large variety of audio standards (Max/MSP externals, PD externals, VST plugins, CoreAudio applications, JACK applications, etc.).

The dsp class

The Faust compiler typically generates a self contained C++ sub class of the followig dsp class :

class dsp {

 protected:
    int fSamplingFreq;
    
 public:
    dsp() {}
    virtual ~dsp() {}

    virtual int getNumInputs() = 0;
    virtual int getNumOutputs() = 0;
    virtual void buildUserInterface(UI* ui_interface) = 0;
    virtual void init(int samplingRate) = 0;
    virtual void compute(int count, FAUSTFLOAT** inputs, FAUSTFLOAT** outputs) = 0;
};

The dsp object is central to the Faust architecture design:

  • getNumInputs, getNumOutputs provides information about the signal processor,
  • buildUserInterface creates the user interface using a given UI class object (see later),
  • init is called to initialize the dsp object with a given sampling rate, typically obtained from the audio architecture,
  • compute is called by the audio architecture to execute the actual audio processing. It takes as a count number of samples to process, inputs and outputs arrays of non-interleaved float/double samples, to be allocated and handled by the audio driver with the required dsp input and ouputs channels (as given by getNumInputs, getNumOutputs).

(note that FAUSTFLOAT label is typically defined to be the actual type of sample : either float or double using #define FAUSTFLOAT float in the code for instance).

We can look at what the Faust compiler generates for a given DSP source file. For the following Faust DSP example:

import("music.lib");

smooth(c)   = *(1-c) : +~*(c);
gain        = vslider("[1]", 0, -70, +4, 0.1) : db2linear : smooth(0.999);
process     = *(gain);

Here is the C++ code the Faust compiler will produce:

//----------------------------------------------------------
// name: "volume"
// version: "1.0"
// author: "Grame"
// license: "BSD"
// copyright: "(c)GRAME 2006"
//
// Code generated with Faust 0.9.73 (https://faust.grame.fr)
//----------------------------------------------------------

/* link with  */
#ifndef FAUSTFLOAT
#define FAUSTFLOAT float
#endif  

#ifndef FAUSTCLASS 
#define FAUSTCLASS mydsp
#endif

class mydsp : public dsp {
  private:
    FAUSTFLOAT fslider0;
    float fRec0[2];
  public:
    static void metadata(Meta* m)   { 
        m->declare("name", "volume");
        m->declare("version", "1.0");
        m->declare("author", "Grame");
        m->declare("license", "BSD");
        m->declare("copyright", "(c)GRAME 2006");
        m->declare("music.lib/name", "Music Library");
        m->declare("music.lib/author", "GRAME");
        m->declare("music.lib/copyright", "GRAME");
        m->declare("music.lib/version", "1.0");
        m->declare("music.lib/license", "LGPL with exception");
        m->declare("math.lib/name", "Math Library");
        m->declare("math.lib/author", "GRAME");
        m->declare("math.lib/copyright", "GRAME");
        m->declare("math.lib/version", "1.0");
        m->declare("math.lib/license", "LGPL with exception");
    }

    virtual int getNumInputs()  { return 1; }
    virtual int getNumOutputs()     { return 1; }
    static void classInit(int samplingFreq) {
    }
    virtual void instanceInit(int samplingFreq) {
        fSamplingFreq = samplingFreq;
        fslider0 = 0.0f;
        for (int i=0; i<2; i++) fRec0[i] = 0;
    }
    virtual void init(int samplingFreq) {
        classInit(samplingFreq);
        instanceInit(samplingFreq);
    }
    virtual void buildUserInterface(UI* interface) {
        interface->openVerticalBox("0x00");
        interface->declare(&fslider0, "1", "");
        interface->addVerticalSlider("0x00", &fslider0, 0.0f, -7e+01f, 4.0f, 0.1f);
        interface->closeBox();
    }
    virtual void compute (int count, FAUSTFLOAT** input, FAUSTFLOAT** output) {
        float fSlow0 = (0.001f * powf(10,(0.05f * float(fslider0))));
        FAUSTFLOAT* input0 = input[0];
        FAUSTFLOAT* output0 = output[0];
        for (int i=0; i<count; i++) {
            fRec0[0] = ((0.999f * fRec0[1]) + fSlow0);
            output0[i] = (FAUSTFLOAT)((float)input0[i] * fRec0[0]);
            // post processing
            fRec0[1] = fRec0[0];
        }
    }
};

Note that by default mydsp is used as the name of the created class. You may need to use the -cn name Faust compiler parameter to possibly generate another class name, especially if you need to compile several Faust generated C++ classes in a same context and avoid name clashes.

The audio class

Faust audio architecture is a glue between the host audio system and a Faust module. It is responsible to allocate and release audio channels and to call the Faust dsp::compute method to handle incoming audio buffers and/or to produce audio output buffers. It is also responsible to present the audio as non-interleaved float/double data, normalized between -1 and 1.

A Faust audio architecture derives the following audio class:


typedef void (* shutdown_callback)(const char* message, void* arg);

class audio {

 public:
    audio() {}
    virtual ~audio() {}

    virtual bool init(const char* name, dsp*)               = 0;
    virtual bool start()                                    = 0;
    virtual void stop()                                     = 0;
    virtual void shutdown(shutdown_callback cb, void* arg)  {}

    virtual int get_buffer_size() = 0;
    virtual int get_sample_rate() = 0;

    virtual int get_num_inputs() { return -1; }
    virtual int get_num_outputs() { return -1; }
    virtual float get_cpu_load() { return 0.f; }
};

The API is simple enough to give a great flexibility to audio architectures implementations. The init method should initialize the audio underlying driver. The start method begins the actual audio processing, until stop method is called. A concrete implementation of audio class will typically get buffer size and sample rate driver parameters in its contructor. So get_buffer_size and get_sample_rate methods can be used to retrieve those values, or the one actually choosen by the driver.

The UI class

A Faust UI architecture is a glue between a host control layer and a Faust module. It is responsible to associate a Faust control parameter to a user interface element and to update the parameter value according to the user actions. This association is triggered by the dsp::buildUserInterface call, where the dsp asks a UI object to build the module controllers.

Since the interface is basically graphic oriented, the main concepts are widget based: an UI architecture is semantically oriented to handle active widgets, passive widgets and widgets layout.

A Faust UI architecture derives the following UI class:

class UI
{

 public:
    UI() {}
    virtual ~UI() {}

    // -- widget's layouts
    virtual void openTabBox(const char* label) = 0;
    virtual void openHorizontalBox(const char* label) = 0;
    virtual void openVerticalBox(const char* label) = 0;
    virtual void closeBox() = 0;

    // -- active widgets
    virtual void addButton(const char* label, FAUSTFLOAT* zone) = 0;
    virtual void addCheckButton(const char* label, FAUSTFLOAT* zone) = 0;
    virtual void addVerticalSlider(const char* label, FAUSTFLOAT* zone, 
        FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) = 0;
    virtual void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, 
        FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) = 0;
    virtual void addNumEntry(const char* label, FAUSTFLOAT* zone, 
        FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) = 0;

    // -- passive widgets
    virtual void addHorizontalBargraph(const char* label, FAUSTFLOAT* zone, 
        FAUSTFLOAT min, FAUSTFLOAT max) = 0;
    virtual void addVerticalBargraph(const char* label, FAUSTFLOAT* zone, 
        FAUSTFLOAT min, FAUSTFLOAT max) = 0;

    // -- metadata declarations
    virtual void declare(FAUSTFLOAT*, const char*, const char*) {}
};

Controlling the dsp

The FAUSTFLOAT* zone element is the primary connection point between the control interface and the dsp code. The compiled dsp Faust code will give access to all internal control value addresses used by the dsp code by calling the approriate addButton, addVerticalSlider, addNumEntry etc. methods (depending of what is described in the original Faust DSP source code).

The control/UI code keeps those addresses, and will typically change their pointed values each time a control value in the dsp code has to be changed. On the dsp side, all control values are “sampled” once at the beginning of the dsp::compute method, so that to keep the same value during the entire audio buffer. Since writing/reading the FAUSTFLOAT* zone element is atomic, there is no need of complex synchronization mechanism between the writer (controller) and the reader (the Faust dsp object). Look as how the fslider0 field of the previously mydsp displayed C++ class is used in the mydsp::compute method, and how its value is read and kept in a local variable, before entering the actual sample computation loop.

Active widgets

Active widgets are graphical elements that control a parameter value. They are initialized with the widget name and a pointer to the linked value. The widget currently considered are Button, CheckButton, VerticalSlider, HorizontalSlider and NumEntry. A GUI architecture must implement a method addxxx(const char* name, FAUSTFLOAT* zone, …) for each active widget. Additional parameters are available to Slider and NumEntry: the init value, the min and max values and the step.

Passive widgets

Passive widgets are graphical elements that reflect values. Similarly to active widgets, they are initialized with the widget name and a pointer to the linked value. The widget currently considered are HorizontalBarGraph and VerticalBarGraph. A UI architecture must implement a method addxxx(const char* name, FAUSTFLOAT* zone, …) for each passive widget. Additional parameters are available, depending on the passive widget type.

Widgets layout

Generally, a GUI is hierarchically organized into boxes and/or tab boxes. A UI architecture must support the following methods to setup this hierarchy:

  • openTabBox(const char* label)
  • openHorizontalBox(const char* label)
  • openVerticalBox(const char* label)
  • closeBox(const char* label)

Note that all the widgets are added to the current box.

Metadata

The FAUST language allows widget labels to contain metadata enclosed in square brackets. These metadata are handled at GUI level by a declare method taking as argument, a pointer to the widget associated value, the metadata key and value: **declare(FAUSTFLOAT, const char, const char*)**. They are used to add specific informations to be decoded by specialized UI interfaces (like OSCUI, MidiUI…).

Non grapical interface controllers

Those UI elements have firstly been defined to have a “graphical meaning”, but you can perfectly decide to control the dsp with a pure non-graphical controller. OSC (see faust/gui/OSCUI.h file) and HTTP (see faust/gui/httpdUI.h file) controllers are good examples of that approach.

Developing your own architecture file

Developing your own architecture file typically means thinking on what part of your system is going to handle the dsp control state (by changing the value of each UI element), and what part is going to activate the actual dsp computation (by calling the dsp::compute method). Handling the dsp state can be done by a regular User Interface or a network based controler for instance. Dsp computation is usually trigerred by the real-time audio chain in a standalone application or plugin, but could be also be done in a pure deferred time context.

Implementing a subclass of audio base class is usually done when producing standalone applications. In the context of a plugin, subclassing a given base “audio node” class part of the host audio chain is usually sufficient. Then developing a subclass of UI base class could also be needed.

For audio you can look at the faust/audio/portaudio-dsp.h file that implements the portaudio class using the PortAudio API as as simple example. Other files in /faust/audio/ allows to use JACK, NetJack, CoreAudio, RTAudio, Alsa, OpenSL ES, etc API.

On the UI side, note that a lot of helper classes (like GUI, MapUI, PathUI, etc.) have already been developed, and may be helpful in your project:

  • PathUI class builds complete hierarchical path for UI items,
  • MapUI class creates a map of complete hierarchical path and zones for each UI items,
  • JSONUI class creates a JSON description of the dsp (including name, number of inputs/outputs and complete UI description),
  • GUI class provides additional mechanisms to synchronize widgets and zones. Widgets should both reflect the value of a zone and allow to change this value.
  • FUI class used to save and recall the state of the user interface. This class provides essentially two new methods saveState() and recallState() used to save on file and recall from file the state of the user interface. The file is human readable and editable.

Using your own architecture file

As soon as you architecture file is ready, you can test it using the following Faust command for instance:

  • faust -a your_architecture_file.cpp foo.dsp -o foo.cpp to create the new foo.cpp file to be compiled with a regular C++ compiler, and linked with the required libraries to produce the final executable or plugin.

Note that you can possibly use the -i parameter to textually include all Faust related dependancies in the output C++ file. You may want to automatize all build steps like invoking the Faust compiler, then the C++ compiler, and possibly additional steps. See scripts located in the tools folder as possible examples.


2015-11-15: New Faust online course

We’re happy to announce Romain Michon’s new Faust online course based on the “Audio Plug-Ins Designed with Faust workshop” that took place at CCRMA (Stanford University) on July 6-10 2015.

It aims at giving a broad introduction to digital signal processing and to the Faust programming language. By the end of this course, students should have a full collection of plug-ins usable in various DAWs and computer music environments. While previous experience in programming is helpful but not required to take this course, we expect students to have basic notions of algebra, calculus and to have some experience using computers to make music.


2015-11-13: fluctuat nec mergitur

Tossed but not sunk. Ten months after January 2015 shouting at Charlie Hebdo and Hyper Casher, Paris has been again attacked.

We are at war against Islamic fundamentalism, a particularly cowardly enemy who kills disarmed people in newspapers, planes, supermarkets, beaches, museums, concert halls,… We are at war against religious obscurantism in all its stupidity and all its inhumanity. Our thoughts go to the victims and their family.


2015-10-01: A Simple Organ

In this example we will see how to write a simple organ base on a sine oscillator described here. The polyphony and the MIDI control will be handled by the architecture file. We will only have to describe a single voice and adopt special conventions on widget’s names for the architecture file to know how to map incoming MIDI messages.

Organ Voice

Let start with the organ timbre, here obtained by combining three sine oscillators. The fundamental frequency will be controlled by the MIDI key:

timbre(freq) = osc(freq) + 0.5*osc(2.0*freq) + 0.25*osc(3.0*freq);

We need also an envelop signal that starts when a key is pressed. This envelop will be controlled by two signals : a gain corresponding to the MIDI velocity and an gate at 1 while a key is pressed. Smooth is a simple filter used to smooth the envelop signal:

envelop(gate, gain) = gate * gain : smooth(0.9995)
                    with { smooth(c) = * (1-c) : + ~ * (c) ; } ;

By combining timbre and envelop we have our organ voice :

voice(gate, gain, freq) = envelop(gate, gain) * timbre(freq);

Midi interface

By convention Faust architecture files with polyphonic MIDI capabilities expect to find a freq, a gain and a gate user interface parameter:

midigate    = button ("gate");                              // MIDI keyon-keyoff
midifreq    = hslider("freq[unit:Hz]", 440, 20, 20000, 1);  // MIDI keyon key
midigain    = hslider("gain", 0.5, 0, 10, 0.01);            // MIDI keyon velocity

Putting all together

All it remains is to connect our organ voice to the MIDI control and add a general volume:

process = voice(midigate, midigain, midifreq) * hslider("volume", 0, 0, 1, 0.01);

You can try the code on the online compiler by dragging this url or pasting the following lines

// Simple Organ
import("stdfaust.lib");

midigate    = button ("gate");                              // MIDI keyon-keyoff
midifreq    = hslider("freq[unit:Hz]", 440, 20, 20000, 1);  // MIDI keyon key
midigain    = hslider("gain", 0.5, 0, 10, 0.01);            // MIDI keyon velocity

process = voice(midigate, midigain, midifreq) * hslider("volume", 0, 0, 1, 0.01);

// Implementation

phasor(f)   = f/ma.SR : (+,1.0:fmod) ~ _ ;
osc(f)      = phasor(f) * 6.28318530718 : sin;

timbre(freq)= osc(freq) + 0.5*osc(2.0*freq) + 0.25*osc(3.0*freq);

envelop(gate, gain) = gate * gain : smooth(0.9995)
                with { smooth(c) = * (1-c) : + ~ * (c) ; } ;

voice(gate, gain, freq) = envelop(gate, gain) * timbre(freq);

2015-09-30: A Sine Oscillator

In this example we will see how to write a sine oscillator. The main component will be a “phase” generator.

Phase generator

A phase generator produces a periodic signal that goes from 0 to 1 at each period. For example the expression:

0.1 : (+,1.0:fmod) ~ _

corresponding to the following block-diagram :

produces the periodic signal :

{0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 0.0}...

In this expression 0.1 is the increment between successive samples, and fmod is the floating point remainder operation used to wrap the signal between 0 and 1.

By controlling the increment we can control the frequency of the generated signal. Let say that the sampling rate is 48000 samples per second. By using an increment of 1/48000 we will produce a signal at 1 Hz, and by using an increment of f/48000 we will produce at frequency f Hz.

We can therefore define our phase generator as:

phasor(f)   = f/48000 : (+,1.0:fmod) ~ _ ;

Sine Oscillator

Once we have a phase generator it is easy to define a sine oscillator by multiplying the phase signal by 2*PI and taking the sine:

osc(f)      = phasor(f) * 6.28318530718 : sin;

We can complete our program with sliders to control the frequency and the level of the oscillator

process     = osc(hslider("freq", 440, 20, 20000, 1)) * hslider("level", 0, 0, 1, 0.1);

Final program

Instead of hardcoding the sampling rate, we can use the SR primitive defined in the math.lib library (as a foreign constant to be setup with the actual sample rate by the architecture file) in the definition of phasor. This lead us to the following program.

import("stdfaust.lib");

phasor(f)   = f/ma.SR : (+,1.0:fmod) ~ _ ;
osc(f)      = phasor(f) * 6.28318530718 : sin;
process     = osc(hslider("freq", 440, 20, 20000, 1)) * hslider("level", 0, 0, 1, 0.01);

You can try it by pasting the above code into the online compiler and selecting the web/audio target in the exec code tab will result in the following user interface:


2015-09-11: The Faust Online Compiler is back!

The Faust Online Compiler is back in a simplified and faster version! It allows you to edit and compile your Faust code directly from a web browser. Try it at here.


2015-06-06: faust2md

The tool faust2md provides an ultra simple documentation system for Faust. It extracts the comments from a Faust file and creates a documentation file based on the lightweight markup language markdown.

The basic usage is faust2md [-t 4] [-c] [-f] foo.dsp > foo.md. The option -t n can be used to change the default tab setting. The option -c can be used to include the faust code itself into the generated file. The option -f adds a YAML front matter at the begin of the documentation file.

The structure of the comments to annotate the source code is the following :

//------------ foo(x,y) ----------------
//  markdown formatted text....
//  markdown formatted text....
//---------------------------------------

Everything else is considered Faust code. The resulting translation is:

# foo(x,y)
markdown formatted text....
markdown formatted text....

Practical example

The convention for the comments was chosen to be as close as possible from the current practice in documenting Faust libraries. Here is the actual documentation of the zita_rev_fdn in effect.lib:

//------------------------------- zita_rev_fdn -------------------------------
// Internal 8x8 late-reverberation FDN used in the FOSS Linux reverb zita-rev1
// by Fons Adriaensen <fons@linuxaudio.org>.  This is an FDN reverb with
// allpass comb filters in each feedback delay in addition to the
// damping filters.
//
// USAGE:
//   bus(8) : zita_rev_fdn(f1,f2,t60dc,t60m,fsmax) : bus(8)
//
// WHERE
//   f1    = crossover frequency (Hz) separating dc and midrange frequencies
//   f2    = frequency (Hz) above f1 where T60 = t60m/2 (see below)
//   t60dc = desired decay time (t60) at frequency 0 (sec)
//   t60m  = desired decay time (t60) at midrange frequencies (sec)
//   fsmax = maximum sampling rate to be used (Hz)
//
// REFERENCES:
//   http://www.kokkinizita.net/linuxaudio/zita-rev1-doc/quickguide.html
//   https://ccrma.stanford.edu/~jos/pasp/Zita_Rev1.html
//
// DEPENDENCIES:
//   filter.lib (allpass_comb, lowpass, smooth)
//   math.lib (hadamard, take, etc.)

And here is my editing to add some markdown formatting :

//------------------------------- zita_rev_fdn -----------------------------
// Internal 8x8 late-reverberation FDN used in the FOSS Linux reverb zita-rev1
// by Fons Adriaensen <fons@linuxaudio.org>.  This is an FDN reverb with
// allpass comb filters in each feedback delay in addition to the
// damping filters.
//
// ### USAGE:
//   `bus(8) : zita_rev_fdn(f1,f2,t60dc,t60m,fsmax) : bus(8)`
//
// #### WHERE
// + f1    = crossover frequency (Hz) separating dc and midrange frequencies
// + f2    = frequency (Hz) above f1 where T60 = t60m/2 (see below)
// + t60dc = desired decay time (t60) at frequency 0 (sec)
// + t60m  = desired decay time (t60) at midrange frequencies (sec)
// + fsmax = maximum sampling rate to be used (Hz)
//
// ### REFERENCES:
//   <http://www.kokkinizita.net/linuxaudio/zita-rev1-doc/quickguide.html>
//   <https://ccrma.stanford.edu/~jos/pasp/Zita_Rev1.html>
//
// ### DEPENDENCIES:
// + filter.lib (allpass_comb, lowpass, smooth)
// + math.lib (hadamard, take, etc.)
//--------------------------------------------------------------------------

The translation produced by faust2md is the following :

---
file: t2.txt
date: 2015-08-06
---

# zita_rev_fdn
Internal 8x8 late-reverberation FDN used in the FOSS Linux reverb zita-rev1
by Fons Adriaensen <fons@linuxaudio.org>.  This is an FDN reverb with
allpass comb filters in each feedback delay in addition to the
damping filters.

### USAGE:
  `bus(8) : zita_rev_fdn(f1,f2,t60dc,t60m,fsmax) : bus(8)`

#### WHERE
+ f1    = crossover frequency (Hz) separating dc and midrange frequencies
+ f2    = frequency (Hz) above f1 where T60 = t60m/2 (see below)
+ t60dc = desired decay time (t60) at frequency 0 (sec)
+ t60m  = desired decay time (t60) at midrange frequencies (sec)
+ fsmax = maximum sampling rate to be used (Hz)

### REFERENCES:
  <http://www.kokkinizita.net/linuxaudio/zita-rev1-doc/quickguide.html>
  <https://ccrma.stanford.edu/~jos/pasp/Zita_Rev1.html>

### DEPENDENCIES:
+ filter.lib (allpass_comb, lowpass, smooth)
+ math.lib (hadamard, take, etc.)

2015-07-29: Your first Faust example

Here is a very simple example of Faust program. It transforms a pair of input signals (a stereo signal) into a mono signal by adding the two input signals

process = +;

The Faust compiler can generate a graphic block-diagram representation of our program (using faust -svg example.dsp)

as well as a C++ implementation (using faust example.dsp -o example.cpp))

class mydsp : public dsp {
  private:
  public:
    ...
    virtual void compute (int count, FAUSTFLOAT** input, FAUSTFLOAT** output) {

        FAUSTFLOAT* input0 = input[0];
        FAUSTFLOAT* input1 = input[1];
        FAUSTFLOAT* output0 = output[0];

        for (int i=0; i<count; i++) {
            output0[i] = (FAUSTFLOAT)((float)input0[i] + (float)input1[i]);
        }
    }
};

2015-07-28: New Website!

Welcome to Faust’s new website. It is a static website build using Jekyll. The source code of the website is on Github faustwebsite.

Periodically the server do a git pull, then rebuild the website using jekyll build and copy the generated site using rsync. Use jekyll serve to run the server locally (http://localhost:4000/).


2015-04-11: Faust Award 2015 to Guitarix

The Faust Open Source Software Competition aims at promoting innovative high-quality free audio software developed with Faust programming language. The Faust Award 2015 was awarded on April 11 in Mainz to Guitarix, a virtual guitar amplifier by Hermann Meyer and Andreas Degert, by an international committee composed of:

  • Albert Graef (Johannes Gutenberg U., Mainz, Germany),
  • Pierre Jouvelot (Ecole des Mines, Paris, France),
  • Victor Lazzarini (Maynooth U., Maynooth, Ireland),
  • Yann Orlarey (Grame, Lyon, France),
  • Laurent Pottier (U. Jean Monnet, Saint Etienne, France),
  • Julius Smith (Stanford U., Palo Alto, USA)

Here are some appreciations made by the committee concerning the Guitarix project:

  • “Guitarix is an impressive piece of software with an impressive sound quality !”
  • “The maturity, both at the artistic, user-interface and technological levels, of the Guitarix project makes it a top contender for the 2015 Faust Open Source Software Competition.”
  • “Guitarix software platform impresses with its intimate knowledge and use of the Faust environment features.”
  • “It is an impressive project that uses Faust for production-grade software, and it is not only a fine piece of work, but also the best demonstration of how useful Faust can be for developers.”
  • “I can say that I have a high opinion of the guitarix work.”

The committee was also very impressed by the quality of three other projects :

  • Flauta, a Waveguide based flute model by T. Westkamper, C.Barría, D. Tirado, P. Magron and P. de la Cuadra,
  • Voice of Faust, a voice synthesizer/effects machine by Bart Brouns,
  • PMix, a graphical patcher, preset interpolator and JIT compiler for Faust by Oliver Larkin.

Many thanks to all the participants, to the members of the committee, and to Albert Gräf and the Linux Audio Conference 2015 organization team.


2015-01-07: First Faust Open Source Software Competition

GRAME is happy to announce the first Faust Open Source Software Competition !

Overview

Faust Open-Source Software Competition is intended to promote innovative high-quality free audio software developed with the Faust programming language. The Faust Open-Source Software award will be attributed to the best submission by an international committee of leading experts in the field. The competition is sponsored by Grame, centre national de création musicale. The winning software will receive a 2000€ price to encourage its authors. The results will be announced during the Linux Audio Conference 2015 in Mainz.

To participate, the software must be provided with source code and licensed with a Free/Open Source license. A substantial part of the software must be written in Faust and the Faust source code must be provided. As part of the review process, the software will be built from the sources. All source code, license, video demonstration, installation instructions, and any other documentation must be available on a public web page. License compatibility with other open source software is encouraged. Dependencies on non-open source third-party software are discouraged, with the exception of operating systems and freely available commercial packages.

Authors are encouraged to prepare a video demonstrating the software as well as any useful documentation, including examples of how the provided software might be used, existing prototypes that use the software, download statistics or other public usage information. The criteria for judging submissions includes broad applicability and potential impact, novelty, technical depth, reusability, etc.

Important dates

  • Software Submission Deadline: March 15, 2015
  • Results of the competition : April 10, 2015 (during the Linux Audio Conference 2015 in Mainz)

Submission Guidelines

Authors interested in participating to the Faust Open Source Software Competition should send a submission email to faustaward@grame.fr with a PDF file attached containing the following information:

Title of submission

  • Name, email and affiliation of the main author
  • Names, emails and affiliations of other authors
  • A permanent link for the open source software (e.g., Sourceforge, GitHub, Google Code, etc.).
  • A permanent link for the video demonstration (e.g., Youtube, Vimeo, etc.).
  • A link to a compressed archive file that contains the software (source code, documentation, build/install instructions, and licenses. Comprehensive and clear build/install instructions will be a crucial component of any submission. The committee will make reasonable effort to build the software for the top contributions, but if they are unable to make the software run, it will be excluded from the competition).

2014-10-14: Faust and the Web Audio API (2)

We are happy to publish a new and improved version of the Faust to Web Audio API development.

Compiling DSP to JavaScript (asm.js)

Using the asm.js based technology, Faust DSP programs can now be compiled in efficient code to be deployed on the Web. Asm.js is an highly optimizable, low-level subset of JavaScript, that can be automatically produced from C/C++ code using the LLVM based Emscripten compiler. Starting from the C++ class produced by the regular Faust compiler, the asm.js code is wrapped using additional C++ and JavaScript code to appear as a ScripProcessor (a pure JavaScript node in Web Audio API terminology) to be connected to other JavaScript or native audio nodes.

While faust1 version (= master branch on GIT) Emscripten SDK has to be installed before using the following scripts.

Whith faust2 development branch, a internal asm.js backend has been developed to directly generate the code starting from the DSP source. So you will be able to either generate the asm.js code using Emscripten (by adding the -emcc parameter in the following described commands), or using the internal asm.js backend.

The JavaScript code alone can be produced using the following script to produce a foo.js file containing the Emscripten runtime, some glue code and the “faust.foo” class.

faust2asmjs karplus.dsp

Using DSP Instances

When “faust.karplus” class is defined, instances can be created and used as regular Web Audio API nodes with the following code (assuming ‘dsp2’ is another Faust defined node):

var dsp = faust.karplus(audio_context, buffer_size);
dsp.start();
dsp.scriptProcessor.connect(dsp2.scriptProcessor);

The parameter ‘audio_context’ will be retrieved using the Web Audio API, and the given ‘buffer_size’ will be used to create the internal ScripProcessor JavaScript node running the actual asm.js generated DSP code.

The list of all input controls can be retrieved with the following code:

var control_list = dsp.controls();

The user interface can change the value of any control using the following code, where ‘path_to_control’ denotes a complete path to the control (retrieved using ‘controls’ function), and ‘value’ the value to be changed:

dsp.setValue(path_to_control, value);

The paramter value can ge read using the following code:

var value = dsp.getValue(path_to_control);

A user interface may have to be periodically updated when output controls (typically bargraphs) have changed. You can use the following code to setup a handler callback:

dsp.setHandler(update_handler);

Where ‘update_handler’ is a function with a prototype (path_to_control, value) that will be called once at each audio cycle with output control values.

The JSON description of the DSP can be retrieved and typically parsed by the user interface builder with the following code :

var json = dsp.json();

For DSP with inputs, the client glue code would typically have to open the audio_context audio input and connect it with the node :

var audio_input = audio_context.createMediaStreamSource(device);
audio_input.connect(dsp.scriptProcessor);

Note that the -comb parameter allows to generate several Faust DSP in a single JavaScript file (named comb.js), thus sharing a single Emscripten runtime when compiled in Emscripten mode:

faust2asmjs -comb karplus.dsp freeverb.dsp zita_rev1.dsp 

Another script can be used to generate a fully working HTML page with a SVG based user interface (thanks to Mike Solomon developments). This is a simple way for developers to produce a fully working HTML page that shows how to use the JavaScript API. The following code will generate a karplus.html page to be loaded in a Web Audio aware browser:

faust2webaudioasm karplus.dsp 

Polyphonic instruments

Polyphonic instruments can be produced. Starting from a monophonic DSP, an when using Emscripten, a polyphonic voice manager coded in C++ allocates voices, instantiates several DSP instances and is compiled in asm.js using the Emscripten chain. When using the internal asm.js backend, the polyphonic code is written in JavaScript. Web MIDI inputs are connected and used to trigger the sound generation. Only keyOn and keyOff events are handled right now. Use the following command to generate a polyphonic version :

faust2webaudioasm -poly piano.dsp 

The DSP has to be allocated and used with the following kind of code:

var dsp = faust.piano_poly(audio_context, buffer_size);
dsp.start();
dsp.keyOn(channel, pitch, velocity);
dsp.keyOff(channel, pitch);

The JavaScript code can possibly be controlled using the Web MIDI API.


2014-06-14: FaustLive is released!

GRAME is happy to announce the official release of FaustLive !

FaustLive is an advanced self-contained prototyping environment for the Faust programming language with an ultra-short edit-compile-run cycle. Thanks to its fully embedded compilation chain, FaustLive is simple to install and doesn’t require any external compiler, development toolchain or SDK to run. FaustLive is the ideal tool for fast prototyping. Faust programs can be compiled and run on the fly by simple drag and drop. They can even be edited and recompiled while running without sound interruption or JACK disconnection.

Dynamic compilation

On FaustLive’s windows you can drop your Faust code as a file, a string or a url. The code will be dynamically compiled and executed. You can then choose to edit your code. It will be opened in the default editor for .dsp files (FOLLOW THE README TO CONFIGURE FILE ASSOCIATION). The application will be automatically recompiled, every time you save your document. A crossfade is calculated between two relaying applications in a window to avoid brutal sound interruptions.

Audio drivers

Depending on your Operation System, you will have different drivers available…

  • on OSX : Coreaudio, JACK and NetJack
  • on Linux : JACK and NetJack
  • on Windows : Portaudio

Export your DSP

Exporting your DSP as plugins is easy, thanks to FaustWeb, compilation service. In FaustLive’s export menu, you can find every platform and architecture that Faust can target. As you choose your target, your code is sent to FaustWeb and you receive the requested binary in exchange.

Save snapshots

If you create a configuration you like, you can save it as a Snapshot. The state of FaustLive will be saved (running applications, JACK connections, interface parameters…). Later on, you will be able to whether:

  • recall the snapshot : closing any running application to restore the saved state
  • import the snapshot : adding the saved state to the current state.

Remote control interfaces (only on Linux and OSX)

In the Windows Option toolBar, you can open a UDP port for OSC control or a TCP port for HTTP control. Moreover, the HTLM interface can be accessed through a QrCode that you can create from «View QrCode » in the menu « Window ».

Download the binaries


2014-04-14: New Faust released

GRAME is happy to announce the release of FAUST 0.9.67 !

This release provides many bug fixes and improvements in several architectures (Audio Units, VTSi, etc.) and libraries, as well as two very exiting new tools.

faust2webaudioasm

This tool, based on developments by Myles Borins at CCRMA, and by Mike Solomon and Stephane Letz at GRAME, allows to make realtime audio applications in a web browser ! faust2webaudioasm uses emscripten to translate Faust programs to efficient Javascript code (asm.js) embedded in a single HTML page. Check some examples (best results with firefox 29):

The two following ones are polyphonic instruments that can be controlled with MIDI. Check them with Chrome (don’t forget to activate Web MIDI API).

faust2owl

faust2owl allows to develop effects for the OWL programmable effects pedal. See http://hoxtonowl.com/ for the pedal, and a short demo of a wah wah effect here.


2012-12-10: faustgen~ : LLVM powered Faust embedded compiler as an external for Max/MSP

GRAME - Centre National de Creation Musicale - is happy to announce faustgen~, the Faust compiler embedded as a Max/MSP external, available for OSX and Windows.

Thanks to the awesome LLVM technology combined with libfaust, the new library version of the Faust compiler, Faust DSP programs can now directly be compiled and executed on the fly at full speed. The Faust DSP source, compiled by libfaust using the LLVM backend, produces an intermediate representation (as LLVM IR), to be compiled and executed as native machine code directly in memory (using LLVM JIT technology).

The LLVM IR can itself be optimized (using “optimization passes” in LLVM terminology), and the JIT component can be configurated to produce the best possibly native machine code.

This compilation chain has been experimented in faustgen~, an external for Max/MSP. Faustgen~ allows to easily use Faust source code inside a Max/MSP patcher, edit it, change compilation options, and even produce the processor flow chart as an SVG diagram. Preliminary tests show that the resulting native code runs at speed comparable to what the previous static compilation model was achieving.

Here is a screen shot of a simple Max/MSP patch including a faustgen~ object containing the classical Freeverb Faust DSP code:

For Pure Data, Albert Graef pd-faust dynamic environment can be used. We hope similar implementations will be available in the future for Supercollider and Csound.