Skip to content

Modules, voices, and params

patchflow’s graph model has three structural concepts above the individual connection: modules, sections, and voices. Understanding them helps you lay patches out cleanly.

A module is any name that appears on either side of a connection. The first time patchflow sees Filter, it creates a block for it. If you never declare it, that block has no parameters or subtitle — it’s a stub block.

- Oscillator (Out) -> Filter (In)
Patch diagramPatch diagram with 2 modules and 1 connection. Modules: Oscillator, Filter. Signals: 1 audio.OscillatorFilterOutaudioInaudioaudio
Patch diagramPatch diagram with 2 modules and 1 connection. Modules: Oscillator, Filter. Signals: 1 audio.OscillatorFilterOutaudioInaudioaudio
Two stub blocks and a single audio cable.

A declaration lets you attach a subtitle, parameters, or just pin down the exact capitalization. It’s a header line ending with :, followed by zero or more parameter lines starting with *.

Filter [Ladder]:
* Cutoff: 2 kHz
* Resonance: 0.7
* Drive: moderate
- Oscillator (Out) -> Filter (In)
- Envelope (Out) >> Filter (Cutoff)
Patch diagramPatch diagram with 3 modules and 2 connections. Modules: Filter, Oscillator, Envelope. Signals: 1 audio, 1 cv.FilterLadderOscillatorEnvelopeCutoff: 2 kHzResonance: 0.7Drive: moderateInaudioCutoffcvOutaudioOutcvaudiocv
Patch diagramPatch diagram with 3 modules and 2 connections. Modules: Filter, Oscillator, Envelope. Signals: 1 audio, 1 cv.FilterLadderOscillatorEnvelopeCutoff: 2 kHzResonance: 0.7Drive: moderateInaudioCutoffcvOutaudioOutcvaudiocv
The subtitle sits under the module name; each param becomes a plate on the panel.

Ports aren’t declared — they’re inferred from the connection endpoints. A port used as a source is treated as an output; used as a target, an input. If the same port appears on both sides of connections across a patch, the layout step treats it as an output and the parser emits an AMBIGUOUS_PORT_DIRECTION warning so you can investigate.

Some modules house multiple functional channels — think MATHS, Maths-like slope generators, or a multi-channel mixer. Declare the parent module, and address sections with Module.Section:

MATHS:
* CH 1: Cycle ON, Rise fast
* CH 2: Attenuverter ~2 o'clock
* CH 4: Cycle OFF
- MATHS.CH 1 (OUT) >> MATHS.CH 2 (In)
- MATHS.CH 4 (EOC) g> MATHS.CH 1 (Trig)
Patch diagramPatch diagram with 3 modules and 2 connections. Modules: CH 1, CH 2, CH 4. Signals: 1 cv, 1 gate.CH 1CH 2CH 4Cycle ON, Rise fastAttenuverter ~2 o'clockCycle OFFTriggateOUTcvIncvEOCgatecvgate
Patch diagramPatch diagram with 3 modules and 2 connections. Modules: CH 1, CH 2, CH 4. Signals: 1 cv, 1 gate.CH 1CH 2CH 4Cycle ON, Rise fastAttenuverter ~2 o'clockCycle OFFTriggateOUTcvIncvEOCgatecvgate
MATHS becomes three sibling panels — one per channel — each carrying its own parameter.

Each section is laid out as its own panel alongside its siblings. If every param on the declared parent matches a section name, the parser migrates the params into their sections and removes the parent block entirely (unless the parent is also directly wired). There is no outer “MATHS” bevel wrapping the sections — they sit side-by-side as independent panels, which is why the layout stays readable even when a composite module has many channels.

Voice markers tag blocks with a voice name for post-processing. Add a header of the form VOICE <name>: and every block declared after it carries that name on its voice field.

VOICE 1:
- Osc1 (Out) -> Mixer (In1)
- Env1 (Out) >> VCA1 (CV)
VOICE 2:
- Osc2 (Out) -> Mixer (In2)
- Env2 (Out) >> VCA2 (CV)
- Mixer (Out) -> Filter (In)
- Filter (Out) -> Output (In)
Patch diagramPatch diagram with 9 modules and 6 connections. Signals: 4 audio, 2 cv.Osc1MixerEnv1VCA1Osc2Env2VCA2FilterOutputOutaudioIn1audioIn2audioOutaudioOutcvCVcvOutaudioOutcvCVcvInaudioOutaudioInaudioaudiocv
Patch diagramPatch diagram with 9 modules and 6 connections. Signals: 4 audio, 2 cv.Osc1MixerEnv1VCA1Osc2Env2VCA2FilterOutputOutaudioIn1audioIn2audioOutaudioOutcvCVcvOutaudioOutcvCVcvInaudioOutaudioInaudioaudiocv
Two voice strands feeding a shared mixer → filter → output chain.

Parameter lines start with * and have the form key: value. Both halves are free text — patchflow doesn’t validate them. They render as small plates stacked under the module’s title.

VCO:
* Wave: saw
* Octave: 2
* Fine: +3

Use whatever vocabulary is natural for the module — position descriptions (2 o'clock), numeric values (2 kHz), or notes (C3). Long values are truncated with an ellipsis so the plate never overflows the module.