Faust Processor
The FaustProcessor enables real-time compilation and execution of Faust DSP code. Faust is a functional programming language for sound synthesis and audio processing.
New to Faust?
Resources:
Online IDE - Develop and test code
Libraries - Browse the standard library
Basic Usage
Creating a Faust Processor
import dawdreamer as daw
engine = daw.RenderEngine(44100, 512)
faust_processor = engine.make_faust_processor("faust")
Loading DSP from File
DSP_PATH = "/absolute/path/to/faust_reverb.dsp"
faust_processor.set_dsp(DSP_PATH) # Must be absolute path
# Compile early to catch errors
faust_processor.compile() # Raises RuntimeError for invalid Faust code
faust_reverb.dsp:
process = dm.zita_light;
Note
The standard library (stdfaust.lib) is always imported automatically. You don’t need to import("stdfaust.lib"); in your code.
Loading DSP from String
faust_processor.set_dsp_string(
"""
declare name "MySine";
freq = hslider("freq", 440, 0, 20000, 0);
gain = hslider("vol[unit:dB]", 0, -120, 20, 0) : ba.db2linear;
process = freq : os.osc : _*gain <: si.bus(2);
"""
)
Parameters
Listing Parameters
Get a description of all available parameters:
print(faust_processor.get_parameters_description())
Setting Parameters
Parameters can be set by address (string) or by index (integer):
# By address
faust_processor.set_parameter("/Zita_Light/Dry/Wet_Mix", 1.0)
# By index
faust_processor.set_parameter(0, 1.0)
Note
Unlike VST plugins, Faust parameters aren’t necessarily normalized to 0-1. For example, a filter cutoff might accept values from 20 to 20000 Hz naturally:
faust_processor.set_parameter("/MyFilter/cutoff", 15000)
Getting Parameter Values
val = faust_processor.get_parameter("/Zita_Light/Dry/Wet_Mix")
print('Value:', val)
Example: Stereo Reverb
import dawdreamer as daw
from scipy.io import wavfile
import librosa
DSP_PATH = "/absolute/path/to/faust_reverb.dsp"
INPUT_AUDIO_PATH = "/path/to/piano.wav"
DURATION = 10.
SAMPLE_RATE = 44100
engine = daw.RenderEngine(SAMPLE_RATE, 512)
faust_processor = engine.make_faust_processor("faust")
faust_processor.set_dsp(DSP_PATH)
# Compile early to catch errors
faust_processor.compile()
print(faust_processor.get_parameters_description())
# Set parameters
faust_processor.set_parameter("/Zita_Light/Dry/Wet_Mix", 1.)
# Load input audio
audio, _ = librosa.load(INPUT_AUDIO_PATH, sr=SAMPLE_RATE, mono=False)
playback = engine.make_playback_processor("piano", audio)
# Build graph
graph = [
(playback, []),
(faust_processor, ["piano"])
]
engine.load_graph(graph)
engine.render(DURATION)
output_audio = engine.get_audio()
wavfile.write('reverb_output.wav', SAMPLE_RATE, output_audio.transpose())
Multi-Channel Processing
Here’s an example that mixes two stereo inputs into one stereo output with a low-pass filter:
dsp_4_channels.dsp:
declare name "MyEffect";
import("stdfaust.lib");
myFilter = fi.lowpass(10, hslider("cutoff", 15000., 20, 20000, .01));
process = si.bus(4) :> sp.stereoize(myFilter);
Python code:
import dawdreamer as daw
from scipy.io import wavfile
import librosa
import numpy as np
INPUT_AUDIO_PATH1 = "piano.wav"
INPUT_AUDIO_PATH2 = "vocals.wav"
DURATION = 10.
SAMPLE_RATE = 44100
def make_sine(freq, duration, sr=SAMPLE_RATE):
N = int(duration * sr)
return np.sin(np.pi * 2. * freq * np.arange(N) / sr)
engine = daw.RenderEngine(SAMPLE_RATE, 512)
faust_processor = engine.make_faust_processor("faust")
faust_processor.set_dsp("/absolute/path/to/dsp_4_channels.dsp")
print(faust_processor.get_parameters_description())
# Set static parameter
faust_processor.set_parameter("/MyEffect/cutoff", 7000.0)
# Or use automation
cutoff_automation = 15000 + 5000 * make_sine(2, DURATION)
faust_processor.set_automation("/MyEffect/cutoff", cutoff_automation)
# Load audio
audio1, _ = librosa.load(INPUT_AUDIO_PATH1, sr=SAMPLE_RATE, mono=False)
audio2, _ = librosa.load(INPUT_AUDIO_PATH2, sr=SAMPLE_RATE, mono=False)
playback1 = engine.make_playback_processor("piano", audio1)
playback2 = engine.make_playback_processor("vocals", audio2)
graph = [
(playback1, []),
(playback2, []),
(faust_processor, ["piano", "vocals"]) # 4-channel input
]
engine.load_graph(graph)
engine.render(DURATION)
output = engine.get_audio()
wavfile.write('mixed_output.wav', SAMPLE_RATE, output.transpose())
Polyphony
Faust processors support polyphonic synthesis. You must provide DSP code that refers to standard parameters:
freqornote: MIDI note frequencygain: Note velocity/amplitudegate: Note on/off trigger
For more information, see the Faust MIDI manual.
Enabling Polyphony
Set the number of voices to 1 or higher (default is 0, which disables polyphony):
faust_processor.set_num_voices(8) # 8-voice polyphony
Example
poly_synth.dsp:
import("stdfaust.lib");
freq = nentry("freq", 440, 20, 20000, 1);
gain = nentry("gain", 0.5, 0, 1, 0.01);
gate = button("gate");
envelope = gain * en.adsr(0.01, 0.1, 0.8, 0.3, gate);
process = os.sawtooth(freq) * envelope <: _, _;
Python code:
faust_processor.set_dsp("/path/to/poly_synth.dsp")
faust_processor.set_num_voices(8)
# Add MIDI notes (note, velocity, start_time, duration)
faust_processor.add_midi_note(60, 100, 0.0, 1.0) # C4
faust_processor.add_midi_note(64, 80, 0.5, 1.0) # E4
faust_processor.add_midi_note(67, 90, 1.0, 1.0) # G4
engine.load_graph([(faust_processor, [])])
engine.render(3.0)
See tests/test_faust_poly*.py for more examples.
Soundfiles
Faust code in DawDreamer can use the soundfile primitive. Normally, soundfile loads .wav files, but DawDreamer uses it to receive data from NumPy arrays.
This is useful for sample-based instruments or convolution reverbs.
Example
Python code:
# Suppose audio1, audio2, and audio3 are np.array shaped (channels, samples)
soundfiles = {
'mySound': [audio1, audio2, audio3]
}
faust_processor.set_soundfiles(soundfiles)
soundfile_test.dsp:
soundChoice = nentry("soundChoice", 0, 0, 2, 1); // choose between 0, 1, 2
process = soundChoice, _ ~ +(1) : soundfile("mySound", 2) : !, !, _, _;
Note
The second argument to soundfile("mySound", 2) is a hint that the audio is stereo. It’s unrelated to the Python side where mySound’s dictionary value has 3 NumPy arrays.
Advanced Example: 88-Key Piano
See tests/test_faust_soundfile.py for a complete example of loading 88 piano samples and playing them with polyphony.
Parameter Automation
Faust processors support both audio-rate and PPQN-rate parameter automation using parameter addresses.
See also
See Parameter Automation in the User Guide for complete documentation on automation modes and recording.
Quick example:
import numpy as np
# Audio-rate automation using parameter address
duration = 4.0
sample_rate = 44100
num_samples = int(duration * sample_rate)
# Sweep frequency from 200 Hz to 2000 Hz
frequency_sweep = np.linspace(200, 2000, num_samples)
faust_processor.set_automation("/MySynth/freq", frequency_sweep)
# PPQN-rate automation (musically-synced)
ppqn = 960
beats = 4
num_pulses = beats * ppqn
freq_automation = np.linspace(200, 2000, num_pulses)
faust_processor.set_automation("/MySynth/freq", freq_automation, ppqn=ppqn)
engine.set_bpm(120.)
engine.render(beats, beats=True)
Tips and Best Practices
- Development Workflow
Develop and test Faust code in the Online IDE
Save to a
.dspfile or copy to a Python stringLoad into DawDreamer and test
- Debugging
Use
compile()early to catch syntax errorsCheck
get_parameters_description()to verify parameter namesTest with simple DSP first (e.g.,
process = _;for passthrough)
- Performance
Faust compiles to optimized C++ at runtime
More complex DSP = longer compile time and higher CPU usage
Consider caching compiled processors for batch operations
- Parameter Naming
Use descriptive names with units:
hslider("freq[unit:Hz]", ...)Group parameters:
hgroup("Oscillator", ...)Makes automation and UI more intuitive
- Channel Handling
Use
si.bus(N)to handle N channelsUse
<:to split signals,:>to mix themExample:
process = _ <: _, _;duplicates mono to stereo
Common Issues
- “Parameter not found”
Check parameter address with
get_parameters_description()Verify spelling and path (e.g.,
/MyEffect/cutoffvs/cutoff)
- “Compilation failed”
Test code in Faust Online IDE first
Check for syntax errors or missing libraries
Ensure absolute path for
.dspfiles
- Audio is silent
Check parameter values (especially gain/volume)
Verify DSP logic (test with simple sine wave first)
Check for
gateparameter in polyphonic instruments
- Clicking or artifacts
Decrease buffer size for higher fidelity parameter automation
Check for parameter discontinuities
Use smoothing in Faust code:
si.smoo
Further Reading
Render Engine and BPM - BPM and timing
User Guide - Graph construction
Examples - Real-world examples