Sc_faust - Faust compiler for SuperCollider

Download it via Releases · capital-G/sc_faust · GitHub

sc_faust is a “meta UGen” which brings the Faust compiler to the SuperCollider server. This allows to write Faust code within sclang, send it to the server for compilation and use it immediately within a Synth. Rinse and repeat.

I don’t think I need to tell you how awesome and vast Faust is - if you haven’t used it before, there is a great tutorial on their website: Quick Start - Faust Documentation

I have tested it with macOS and Linux (Fedora 42), but haven’t tested if it works with Windows.
Currently there is no Supernova support and also no “select-audio-buffer” support via Faust.

Quickstart

In order to setup the Faust compiler, we need to tell it where the provided faust .lib files are - this is done via the init method

// start the server
s.boot;

// send a message to the server to tell the server the path of our faustlibs
// this "inits" the compiler
FaustDef.init;

Before a Faust UGen can be used, it needs to be registered and compiled on the server.
Here is an example in which the input will be fed into a JPVerb and it’s t60 parameter will be exposed and controllable

// define a faust snippet 
(
FaustDef(\jp, "
import(\"stdfaust.lib\");
re = library(\"reverbs.lib\");

t60 = hslider(\"t60\", 3.0, 0, 10.0, 0.01);

process = re.jpverb(t60, 0.2, 1.0, 0.8, 0.3, 0.4, 0.9, 0.8, 0.7, 500, 10000);
").send;
)

Once the faust code has been compiled, it can be used via the Faust UGen.

(
Ndef(\jp, {
    var sig = SinOscFB.ar(SinOscFB.kr(0.03*[1.0, 1.01], 2.3).exprange(100, 10000), [1.3, 1.4]) * SinOscFB.kr([1.4, 1.3], 1.3);
    sig = sig * Env.perc(releaseTime: LFDNoise3.kr(0.5).exprange(0.01, 0.5)).kr(gate: Impulse.kr(2.0, [0, 1/2]));
    Faust.ar(
        numOutputs: 2,
        script: \jp,
        inputs: sig,
        params: [
            t60: \t60.kr(2.0, spec: [0.01, 10.0]
        ),
    ]) * \amp.kr(0.2);
}).play.gui;
)

Acknowledgement

Big thanks to GRAME, especially to @Stephane_Letz, for sponsoring the development of this extension! <3

Much thanks also to @madskjeldgaard who provided the idea and a good starting point with GitHub - madskjeldgaard/faustgen-supercollider: Livecode Faust in SuperCollider using an embedded Faust compiler. - yet, in fact, sc_faust does not share any source code with this implementation and was coded from scratch. Instead of using the VSTplugin based approach, it follows the DynGen approach, which is IMO more suitable for passing parameters to short running synths (within e.g. patterns).

14 Likes

Thanks @dscheiba for this first release. The Release v0.1.1 · capital-G/sc_faust · GitHub still have files with 0.1.0 version number ?

Ah, thats a typo - thanks for pointing this out, it is fixed now.

1 Like

Great work on this. Very cool!

Sam

1 Like

New bugfix release: Release v0.1.2 · capital-G/sc_faust · GitHub

Also added spec extraction of parameters via paramMap:

(
~brass = FaustDef(\brass, "
import(\"stdfaust.lib\");

process = pm.brass_ui <: _,_;
").send;
)

(
Ndef(\brass, {
    Faust.ar(2, ~brass, params: ~brass.paramMap) * 0.2;
}).play.gui;
)
2 Likes

Thanks @dscheiba for this implementation ! Nice work !!

I have a small question regarding dynamic behavior in sc_faust:
Why is it not possible to change the Faust script dynamically while the synth is running, as is possible for example in DynGen?
If I remember well, in FaustGen for Max this is possible, which would suggest that, at least theoretically, it should also be feasible in sc_faust ? :slight_smile:

Many thanks!

José