-
Notifications
You must be signed in to change notification settings - Fork 68
Faust Processor
- Browse the suggested Documentation and Resources.
- Use the Online IDE to develop and test code.
- Read Julius Smith's Audio Signal Processing in FAUST.
- Browse the Libraries.
- Read the Syntax Manual.
- Join the communities.
Let's start by looking at FAUST DSP files, which end in .dsp
. For convenience, the standard library is always imported, so you don't need to import("stdfaust.lib");
Here's an example using a demo stereo reverb:
process = dm.zita_light;
DSP_PATH = "C:/path/to/faust_reverb.dsp" # Must be absolute path
INPUT_AUDIO_PATH = "C:/path/to/piano.wav"
DURATION = 10.
faust_processor = engine.make_faust_processor("faust")
faust_processor.set_dsp(DSP_PATH) # You can do this anytime.
# Using compile() isn't necessary, but it's an early warning check.
faust_processor.compile() # throws a catchable Python Runtime Error for bad Faust code
print(faust_processor.get_parameters_description())
# You can set parameters by index or by address.
faust_processor.set_parameter("/Zita_Light/Dry/Wet_Mix", 1.)
faust_processor.set_parameter(0, 1.)
# Unlike VSTs, these parameters aren't necessarily 0-1 values.
# For example, if you program your FAUST code to have a 15000 kHz filter cutoff
# you can set it naturally:
# faust_processor.set_parameter(7, 15000)
print('val: ', faust_processor.get_parameter("/Zita_Light/Dry/Wet_Mix"))
print('val: ', faust_processor.get_parameter(0))
graph = [
(engine.make_playback_processor("piano", load_audio_file(INPUT_AUDIO_PATH)), []),
(faust_processor, ["piano"])
]
engine.load_graph(graph)
engine.render(DURATION)
Here's an example that mixes two stereo inputs into one stereo output and applies a low-pass filter.
declare name "MyEffect";
import("stdfaust.lib");
myFilter = fi.lowpass(10, hslider("cutoff", 15000., 20, 20000, .01));
process = si.bus(4) :> sp.stereoize(myFilter);
INPUT_AUDIO_PATH1 = "piano.wav"
INPUT_AUDIO_PATH2 = "vocals.wav"
DURATION = 10.
faust_processor = engine.make_faust_processor("faust")
faust_processor.set_dsp("C:/path/to/dsp_4_channels.dsp") # Must be absolute path
print(faust_processor.get_parameters_description())
faust_processor.set_parameter("/MyEffect/cutoff", 7000.0) # Change the cutoff frequency.
# or set automation like this
faust_processor.set_automation("/MyEffect/cutoff", 15000+5000*make_sine(2, DURATION))
graph = [
(engine.make_playback_processor("piano", load_audio_file(INPUT_AUDIO_PATH1)), []),
(engine.make_playback_processor("vocals", load_audio_file(INPUT_AUDIO_PATH2)), []),
(faust_processor, ["piano", "vocals"])
]
engine.load_graph(graph)
engine.render(DURATION)
Polyphony is supported too. You simply need to provide DSP code that refers to correctly named parameters such as freq
or note
, gain
, and gate
. For more information, see the FAUST manual. In DawDreamer, you must set the number of voices on the processor to 1 or higher. The default (0) disables polyphony. Refer to tests/test_faust_poly*.py.
Faust code in DawDreamer can use the soundfile primitive. Normally soundfile
is meant to load .wav
files, but DawDreamer uses it to receive data from numpy arrays. Refer to tests/test_faust_soundfile.py which contains an example of loading 88 piano notes and playing them with polyphony.
soundfile_test.py
# 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 that soundfile("mySound",2)
has 2 as a hint that the audio is stereo. It's unrelated to the Python side where mySound's dictionary value has 3 numpy arrays.