Using LLMs with Faust

Large Language Models (LLMs) can help write, explain, debug, and document Faust programs. They are useful for turning a musical or signal-processing idea into a first draft, proposing variations, finding standard-library functions, and driving a short compile/listen/revise loop.

They should not replace the Faust compiler, the library documentation, or listening tests. Generated DSP code must still be compiled, inspected, measured, and auditioned.

Faust is a strong target for LLM-assisted programming because it is compact, textual, and structured around signal flow. A .dsp file is not just code generated by a model: it is an auditable artifact shared by the model, the Faust compiler, and the human reviewer. The composition operators describe routing, the compiler checks arity and feedback structure, and SVG block diagrams make nontrivial signal flow visible.

For DSP, this is often a better division of labor than asking an LLM to write a complete C++ implementation. The LLM can write a compact Faust specification; the Faust compiler then generates C++, WebAssembly, LLVM IR, Rust, Cmajor, JAX, or another target.

Typical Uses

LLMs are most useful when the task has a clear sound, interface, or diagnostic goal:

  • draft an oscillator, filter, effect, instrument, physical model, or analysis patch;
  • explain existing Faust code as signal flow;
  • translate a block-diagram idea into Faust composition operators;
  • propose standard-library functions for a task;
  • add controls, metadata, MIDI mappings, or polyphonic structure;
  • debug compiler errors and arity/routing problems;
  • generate small variations while preserving an existing interface;
  • document a DSP for users or maintainers.

The most productive loop is:

prompt -> generated Faust -> compile -> inspect JSON/SVG -> listen/measure
       -> targeted correction -> repeat

Prompting Faust Code

Prompts work better when they include Faust-specific constraints:

  • desired sound or processing task;
  • number of inputs and outputs;
  • control names, ranges, and defaults;
  • whether to use import("stdfaust.lib");;
  • MIDI, polyphony, metadata, or target platform requirements;
  • whether readability or optimization matters more.

Example:

Write a Faust stereo chorus effect.
Requirements:
- use import("stdfaust.lib");
- two audio inputs and two audio outputs;
- controls: rate [0.05..8] Hz, depth [0..1], feedback [0..0.95], mix [0..1];
- keep the code readable;
- return only the .dsp code.

For debugging, include the compiler diagnostic and the complete current program:

This Faust program fails to compile. Explain the error and return a corrected
version. Preserve the public controls and stereo I/O.

<paste compiler diagnostic>
<paste Faust code>

For refinement, ask for a minimal edit:

Modify only the filter section so the resonance is safer at high cutoff values.
Keep all UI paths and control ranges unchanged.

What to Check

LLMs often produce plausible-looking Faust code that still needs correction. Common issues include:

  • missing import("stdfaust.lib");;
  • invented library names or wrong function arity;
  • wrong number of inputs or outputs;
  • invalid use of : / , / <: / :> / ~;
  • wrong delay or feedback topology, especially around ~;
  • unsafe UI ranges or defaults;
  • code that compiles but clips, self-oscillates, denormalizes, or produces silence;
  • argument-order or unit mistakes in library calls that compile cleanly but implement the wrong DSP.

Always run the compiler. When possible, also inspect JSON metadata and SVG block diagrams:

faust -lang cpp mypatch.dsp -o /tmp/mypatch.cpp
faust -json mypatch.dsp -o /tmp/mypatch.json
faust -svg mypatch.dsp

Treat the compiler as an oracle for what it can prove cheaply: syntax, symbol existence, arity, routing, and many feedback-shape errors. It cannot prove musical taste, correct parameter scaling, intended units, stability for every parameter trajectory, or whether the best library primitive was chosen.

Using Library Documentation with LLMs

LLMs are much more reliable when they can consult the actual Faust library documentation instead of relying on memory. A practical retrieval workflow is:

  1. load the general LLM entry point for the libraries;
  2. search the generated library index for relevant functions;
  3. provide exact names, signatures, I/O shape, parameter meaning, examples, and license information;
  4. ask the model to use only those functions;
  5. compile the result and feed diagnostics back into the conversation.

The Faust libraries site documents its LLM-oriented exports in the Contributing / LLMs section and publishes a dedicated entry point:

https://faustlibraries.grame.fr/llms.txt

The libraries repository can also generate machine-readable JSON exports from the .lib sources. The generator starts from stdfaust.lib, follows library("...") and import("...") directives, and extracts documented symbols with fields such as summary, usage, parameters, notes, I/O counts when derivable, test code, references, source location, and per-symbol license metadata.

Useful commands in a Faust libraries checkout:

make doc-index
make doc-index-split
make doc-index-commercial

The split layout is usually best for LLM workflows because it loads a compact global index first, then retrieves one module or symbol on demand. The commercial-compatible export is useful for license-sensitive generation; it is a practical filter, not a legal opinion.

The local query tool can be used directly:

python3 scripts/faust_doc_api.py --pretty search_faust_lib reverb --limit 5
python3 scripts/faust_doc_api.py --pretty get_faust_symbol de.delay
python3 scripts/faust_doc_api.py --pretty list_faust_module delays --limit 20
python3 scripts/faust_doc_api.py --pretty get_faust_examples delay
python3 scripts/faust_doc_api.py --pretty explain_faust_symbol_for_goal \
  re.springreverb "build a metallic spring reverb"

For prompts, prefer concise retrieved context: exact signature, argument order, units, I/O shape, one-line purpose, usage example, and license status. A bare list of names is less useful because the compiler already rejects unknown symbols. The high-value information is discovery, semantics, and custom library documentation that the model has not seen in training.

Example:

Use only these retrieved Faust functions:
- fi.lowpass(...)
- de.delay(...)
- si.smoo

All functions above are acceptable for the target license policy.
Build a mono tape-delay effect with delay time, feedback, tone, and wet/dry mix.
Do not invent other library functions.

Claude Code Faust Plugin

Julius O. Smith's /faust skill is also packaged as an installable Claude Code plugin. In Claude Code:

/plugin marketplace add josmithiii/gists
/plugin install faust@josmithiii-gists

After installation, the Faust skill triggers automatically on Faust-related requests; it does not need to be invoked explicitly. It carries the same kind of terse Faust primer and idiomatic examples described above, so the model starts with useful context about syntax, arity, composition operators, recursion, and standard-library usage before generating or reviewing Faust code.

MCP and Interactive Sessions

The Model Context Protocol (MCP) lets an LLM call tools instead of only generating text. For Faust, MCP tools can:

  • check syntax;
  • compile a DSP;
  • start audio in a browser or Node/WebAudio runtime;
  • list UI parameters from generated JSON;
  • set and read parameter values;
  • return audio metrics;
  • search Faust library documentation.

A minimal interaction can look like:

compile_and_start(faust_code="process = os.osc(440) * 0.2;")
get_param_values()
set_param(path="/freq", value=220)
set_param(path="/gain", value=0.1)

This creates two feedback loops:

  • symbolic: source -> compiler -> errors, JSON, generated code, diagrams;
  • perceptual: audio -> listening, peak/RMS, spectrum, stability checks.

Browser-based MCP systems such as faustbrowser-mcp or faustcode delegate audio execution to a real browser runtime. A small server exposes MCP tools and bridges the LLM client to a browser UI using Web Audio, Web MIDI when available, controls, meters, and diagrams. This is well suited to prototyping, teaching, and sound design, but generated DSP still needs review before production use.

Practical Verification

For generated or modified Faust code, check:

  • compile with the target Faust version;
  • input/output arity;
  • UI names, ranges, and defaults;
  • silence, clipping, NaNs, and runaway feedback;
  • extreme parameter values;
  • MIDI and polyphony metadata, if used;
  • CPU cost for constrained targets;
  • block diagrams for nontrivial routing.

For nontrivial patches, ask the LLM to explain the signal graph in terms of Faust's five composition operators:

~   feedback
,   parallel composition
:   sequential composition
<:  split
:>  merge

Then compare the explanation with the generated block diagram. Mismatches often indicate that either the code or the explanation is wrong.

Prompt Patterns

Generate:

Write a Faust DSP for a mono-in/stereo-out shimmer reverb prototype.
Use import("stdfaust.lib"). Keep the code compact and compilable.
Controls: mix, decay, shimmer, tone. Return only Faust code.

Explain:

Explain this Faust program as a signal-flow graph. Identify inputs, outputs,
UI controls, and feedback paths.

Repair:

This code does not compile with Faust. Fix the smallest possible part.
Preserve all UI labels and ranges.

Review:

Review this Faust effect for unsafe feedback, clipping risk, parameter ranges,
and library calls that may have wrong units or argument order.

Use retrieved documentation:

Here are the exact library functions available:
<paste retrieved docs>

Use only these functions. Do not invent library names.

Commercial Projects using LLMs with Faust

Several public products and applications are starting to use the same general loop described above: natural-language prompt, generated or controlled DSP, automatic checking, browser or hardware preview, and export to a playable result. Examples include:

  • Chaos Audio AI FX Builder for the Stratus and Nimbus hardware platforms. Chaos Audio describes a system where the user writes a plain-English effect prompt, the service generates a new effect algorithm in Faust, iterates automatically to debug and refine it, and then deploys the result to the pedal. The builder also exposes the generated Faust code for users who want to inspect or edit the DSP.
  • pluginmaker.ai, a browser-based AI platform for generating VST/AU instruments and effects from text prompts. The workflow is aimed at musicians rather than DSP developers: describe the plugin, preview it in the browser, customize the sound and interface, then export a plugin for a DAW.
  • MAGDA and its open-source magda-core repository. MAGDA is a DAW built around automation, transformation, and fast musical iteration. It includes AI agents that understand the session, generate commands in an internal DSL, and can operate musical structures and devices. Faust appears as the DSP layer for its effects bank and experimental Faust device, making it another example of LLMs controlling a larger music environment while Faust remains the auditable audio-processing language.

These projects are useful reference points for Faust because they show how LLMs can move beyond isolated code snippets into complete product workflows. They also make the review rules in this page more important: generated DSP should be compiled, tested, inspected, and checked against licensing constraints before it is shipped to users.

Limitations

Faust reduces some LLM risks, but it does not remove review. Its compiler can prove important structural facts about wiring, arity, and feedback form; it does not prove that a reverb is beautiful, that a compressor has the intended feel, or that a physical model matches a target instrument.

Current LLMs also have less Faust training data than Python, JavaScript, or C++. They often know the basic operators but may be less fluent with idiomatic stdfaust.lib usage, recursion patterns, and long-tail library functions. More public, well-licensed, idiomatic Faust examples and prompt-to-Faust examples with tests directly improve this situation.

Treat LLM output as a draft: compile it, test it, inspect metadata and block diagrams, listen critically, and keep human review in the loop.