AquaSynth/docs/faust-toolchain-boundary.md
Aqua 53f1f1b03e Faust loader: platform-aware library lookup and explicit path override
Find libfaust.so on Linux, libfaust.dylib on macOS, libfaust.dll/faust.dll on
Windows; join PATH with Path.PathSeparator; accept FaustLibraryPath or
AQUASYNTH_FAUST_LIBRARY as an explicit library file. Platform default homes
replace the unconditional C:\Program Files\Faust.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-31 09:14:08 +00:00

102 lines
4.4 KiB
Markdown

# Faust Toolchain Boundary
AquaSynth owns the path from patch intent to loadable DSP product. Aquarium
Engine owns audio hosting. That split keeps the compiler brain near the patch
model and keeps the engine from becoming a synth compiler with a game loop
stapled to it.
Package ownership follows that boundary:
- `AquaSynth.Core` owns patch meaning: model records, `.aqua` parsing, analysis,
presets, and Faust source emission.
- `AquaSynth.Faust` depends on Core and owns toolchain/rendering: Faust CLI
validation, target-code generation, live patch compilation, native `libfaust`
loading, compile manifests, factory lifetime, and offline/sample rendering.
## Pipeline Map
1. AquaSynth parses `.aqua` script into an explicit `SynthPatch`.
2. AquaSynth emits stable, inspectable Faust source.
3. AquaSynth resolves a pinned Faust toolchain or caller-provided Faust path.
4. AquaSynth compiles the patch into a target artifact.
5. AquaSynth emits a manifest for parameters, buses, MIDI behavior, sample-rate
assumptions, cache keys, diagnostics, and artifact provenance.
6. Aquarium loads the artifact, binds parameters, schedules notes and buffers,
and calls the DSP from its realtime path.
Aquarium may request compilation, cache lookup, reload, or diagnostics. It
should not need to know how AquaSynth chooses Faust flags, target languages,
architecture files, generated source layout, or artifact identity.
## Ownership
AquaSynth owns:
- patch graph contracts
- Faust source emission
- Faust toolchain selection and version pinning
- compile cache keys
- generated source/native artifact layout
- parameter and bus manifests
- diagnostics and compile provenance
- dynamic patch compilation outside the realtime callback
- native Faust factory lifetime and offline/sample-buffer rendering for hosts
- live patch compiler sessions requested by engine hosts
Aquarium owns:
- device I/O
- buffer scheduling
- audio-thread rules
- note/event delivery
- plugin or engine integration
- artifact loading policy for its platform
- presentation and editor UX
## Runtime Rule
Compilation is never an audio-thread operation. Dynamic patches compile in a
background worker or build step, then Aquarium swaps in a finished DSP artifact
through a realtime-safe handoff.
Parameter changes are not recompiles. Recompile only when graph shape changes;
ordinary patch controls move through the compiled DSP parameter API.
## Target Lanes
- Authoring/tests may use Faust-generated C# because it is easy to render,
inspect, and compare inside the .NET test suite.
- Browser-hosted tools should use Faust-generated WebAssembly plus Faust JSON UI
metadata. AquaSynth owns those artifacts; the web app owns WebAudio loading,
scheduling, user gesture unlocking, and parameter binding.
- Shipping builds should prefer Faust-generated native targets when the platform
permits it.
- A bundled Faust compiler belongs in an AquaSynth toolchain package or
installer lane, not as an accidental dependency of the core DSL package.
- Consumer runtimes should normally bundle compiled DSP artifacts plus manifests,
not the compiler itself, unless live user patch authoring is a product feature.
Current API foothold: `AquaSynthPatchCompiler` is the host-facing live compiler
surface. It owns lazy `libfaust` loading through AquaSynth, compiles `.aqua`
scripts into native Faust factories, writes optional `.dsp` artifacts, and
returns `AquaSynthCompiledPatch` products with `AquaSynthNativeManifest`.
`AquaSynthRenderSession` is only a render-proof convenience wrapper for tests
and offline one-shot buffers.
Library lookup is platform-aware: `libfaust.so` on Linux, `libfaust.dylib` on
macOS, `libfaust.dll` (then `faust.dll`) on Windows, always at `<home>/lib` with
`<home>/share/faust` beside it. `AquaSynthNativeOptions.FaustLibraryPath` or
`AQUASYNTH_FAUST_LIBRARY` names the library file directly and overrides the home
search; `FaustHome` then supplies `share/faust` if the prefix is not the file's
grandparent. The loader prepends `lib` and `bin` to `PATH` using the platform
path separator.
## Invariants
- AquaSynth remains the authority for what a patch means.
- Faust remains the pure DSP target, not the host runtime.
- Aquarium remains the realtime host, not the compiler.
- Generated artifacts are reproducible from script, AquaSynth version, Faust
version, target, compile options, and architecture inputs.
- Licenses and provenance travel with toolchains, reference inputs, generated
artifacts, and packaged output.