# A modulator is a file

FaustWave has no "LFO feature". A modulator is an ordinary `.dsp` document with a bargraph tagged `[modout]`; while it runs, that output is a **modulation source** in the Patchbay, and every live parameter of every running instrument, Builder and FX slot is a **sink**. Wiring is a cable with an amount, like audio is a cable with a gain.

This has three consequences you will feel immediately:

- **You can read it.** Open `Mod LFO Breath.dsp` in the demo and the whole modulator is twenty lines of Faust. Change the shape, add a second output, tempo-sync it — it is your code.
- **It persists like a file.** The modulator is in `assets/`, its edges are in the project's routing table, the values it swings around are in the project. Reopen the project and the breathing is back.
- **It is a source like any other.** An envelope follower on the drum bus, a random walk, a macro knob — anything with `[modout]` can drive anything with a slider.

## The corpus templates

You rarely write one from scratch. `modulation.source.add { type }` creates a modulator document from a template and runs it:

| Template | What it is | Tempo sync |
|---|---|---|
| `lfo` | Four shapes (sine, triangle, saw, square) from one resettable phasor, `rate` in Hz | yes — the `sync` menu (1/1 … 1/16) |
| `sample-hold` | A new random value on every clock tick, deliberately unsmoothed | yes |
| `random` | Band-limited drift | no |
| `macro` | One knob, no life of its own — the stage performer's source | — |

```yaml
actions:
  - action_id: modulation.source.add
    input: { type: lfo }
    save_as: lfo
    label: "▶ Create an LFO document and run it"
  - action_id: modulation.source.list
    input: {}
    label: "▶ Every source that is running, with its ports and edge count"
```

Tempo sync works through two metadata tags a modulator (or any DSP) can carry: a slider tagged `[bpm]` receives the live transport tempo, a button tagged `[transportreset]` is pulsed on stop → play so the phase re-aligns with the downbeat. The demo's `Mod SH Bell` steps on every eighth because of exactly those two lines.

## Writing your own

```faust
declare name "Breath";
import("stdfaust.lib");
rate  = hslider("rate[unit:Hz][scale:log]", 0.135, 0.01, 20, 0.001);
depth = hslider("depth", 1, 0, 1, 0.001);
process = attach(0, os.osc(rate) * depth : hbargraph("out[modout]", -1, 1));
```

Three rules: the output range is what the bargraph declares (-1..1 or 0..1 — the amount maths below uses it); `attach(0, …)` keeps the DSP audio-silent while forcing the bargraph to compute; the modulator must **run** (`dsp.run`) — a source registers only while its patch runs, which is also why `routing.list` shows modulation sinks only for running instruments.

## Where you see it

The **Modulators** pane (shipped in Perform) lists every source with its live value and edges. The **Inspector** colours every modulatable widget: arm a source with `modulation.assign.set` (or the panel's assign toggle) and a drag on any widget creates the edge and sets its depth — the gesture; the next chapter is the arithmetic behind it.

- **FaustWave — Faust DSP** § *Live params, modulation and observability* — the `[modout]` tag from the instrument's side.
- **FaustWave — Patchbay & Routing** § *Cable kinds* — modulation is the third cable kind beside audio and MIDI.
