name: faust description: Create FAUST DSP plugins in Pulp using offline codegen, pre-generated C++ headers, and the FaustProcessor template wrapper. requires: scripts: - tools/cmake/PulpFaust.cmake
tools: []
FAUST DSL
Use this skill when a task involves writing, generating, or testing FAUST-based processors in Pulp.
Truthful Position
Pulp supports FAUST as an offline codegen DSL. The FAUST compiler is an optional external tool; pre-generated C++ is checked into the source tree so builds work without a FAUST installation.
Supported now:
.dspsource files with offline codegen to C++ headersFaustProcessor<T>template that bridges any FAUST-generateddspsubclass into Pulp'sProcessormodel- automatic parameter reflection from FAUST
buildUserInterface()intoStateStore - bus layout detection from
getNumInputs()/getNumOutputs() - metadata extraction (
name,author,version) intoPluginDescriptor - CMake integration via
PulpFaust.cmake(pulp_faust_generate,pulp_add_faust_test) - three working examples: gain, filter, tremolo
Not supported by this skill:
- FAUST MIDI mapping
- FAUST polyphony /
declare options "[midi:on][nvoices:N]" - runtime JIT compilation
@gfx/ FAUST GUI — FaustProcessor reportshas_editor() = false- soundfile support
Core Files
| File | Purpose |
|---|---|
core/dsl/include/pulp/dsl/faust_base.hpp |
Self-contained FAUST base classes (dsp, UI, Meta) |
core/dsl/include/pulp/dsl/faust_processor.hpp |
FaustProcessor<T> template and PulpFaustUI |
core/dsl/include/pulp/dsl/dsl_processor.hpp |
DslProcessor base class shared across DSL lanes |
tools/cmake/PulpFaust.cmake |
CMake module: pulp_faust_generate(), pulp_add_faust_test() |
examples/faust-gain/ |
Stereo gain — simplest FAUST example |
examples/faust-filter/ |
Parametric filter example |
examples/faust-tremolo/ |
Tremolo with rate/depth |
How It Works
FAUST offline codegen produces a C++ class derived from ::dsp. Pulp provides self-contained base classes in faust_base.hpp so the generated code compiles without the FAUST architecture headers. FaustProcessor<T> wraps the generated class:
- Constructor calls
buildUserInterface()to discover parameters andmetadata()for plugin info define_parameters()registers each FAUST zone as aStateStoreparameter with correct range/unit/groupprepare()callsdsp::init(sample_rate)process()syncsStateStorevalues into FAUST zone pointers, then callsdsp::compute()
Creating a FAUST Plugin
1. Write the .dsp source
// examples/faust-myplugin/myplugin.dsp
declare name "MyPlugin";
declare author "YourName";
declare version "1.0.0";
import("stdfaust.lib");
gain = hslider("Gain [unit:dB]", 0, -60, 24, 0.1) : ba.db2linear;
process = _, _ : *(gain), *(gain);
2. Generate C++ (requires faust on PATH)
faust -lang cpp -cn MyPluginDsp -o examples/faust-myplugin/generated_myplugin.hpp \
examples/faust-myplugin/myplugin.dsp
Or let CMake handle it (regenerates when .dsp changes):
include(PulpFaust)
pulp_faust_generate(
${CMAKE_CURRENT_SOURCE_DIR}/generated_myplugin.hpp
${CMAKE_CURRENT_SOURCE_DIR}/myplugin.dsp
MyPluginDsp
)
The generated header is committed to the repo so builds never require faust.
3. Write the processor wrapper
// examples/faust-myplugin/faust_myplugin.hpp
#pragma once
#include "generated_myplugin.hpp"
#include <pulp/dsl/faust_processor.hpp>
namespace pulp::examples {
using MyPluginProcessor = dsl::FaustProcessor<MyPluginDsp>;
inline std::unique_ptr<format::Processor> create_my_plugin() {
return std::make_unique<MyPluginProcessor>();
}
} // namespace pulp::examples
4. Add CMakeLists.txt
if(PULP_BUILD_TESTS)
add_executable(pulp-faust-myplugin-test test_faust_myplugin.cpp)
target_link_libraries(pulp-faust-myplugin-test PRIVATE pulp::dsl pulp::format Catch2::Catch2WithMain)
target_include_directories(pulp-faust-myplugin-test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
catch_discover_tests(pulp-faust-myplugin-test)
endif()
5. Write tests
Follow the pattern in examples/faust-gain/test_faust_gain.cpp:
- verify
descriptor()metadata matches FAUSTdeclarestatements - verify parameter count, names, ranges, and units
- verify audio processing at known parameter values (unity gain, boost, cut)
- verify state serialization round-trip
- verify DSL reflection (
dsl_name() == "faust",dsl_params(),bus_layout())
Build and Test
# Build everything (uses pre-generated C++ — no faust needed)
cmake --build build -j$(sysctl -n hw.ncpu)
# Run all FAUST tests
ctest --test-dir build -R "faust" --output-on-failure
# Run one example
ctest --test-dir build -R "FaustGain" --output-on-failure
# Regenerate all FAUST C++ (requires faust on PATH)
cmake --build build --target faust-regenerate
What To Check
When modifying the FAUST lane, verify:
- pre-generated C++ compiles without
faustinstalled - parameter names, ranges, and units round-trip correctly from
.dspmetadata - bus layout matches
getNumInputs()/getNumOutputs() - audio output is correct at known parameter values
DslProcessorreflection (dsl_name,dsl_params,bus_layout) is accurate- new examples are added to
examples/CMakeLists.txt
Boundaries
This skill covers the offline codegen FAUST lane only.
- The FAUST compiler is external, not vendored
- Generated C++ is committed so builds are self-contained
- No runtime JIT or FAUST interpreter embedding
- No FAUST GUI — Pulp provides its own UI layer