Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Running a patch in the player

patch_player (built from the patches-player crate; binary name patch_player, sometimes still referred to as patches-player) is the standalone command-line player. It opens an audio device, loads a .patches file, runs it, and watches the file for changes.

The smallest run

patch_player examples/square_440.patches

A pulse-width-modulated square plays through the default output device. The terminal switches into the TUI — log pane, CPU pane, status bar. Ctrl-C exits cleanly.

If the patch fails to compile, the player renders diagnostics with source spans to stderr (still in TUI mode) and keeps the previous patch running. Fix the error and save; the new graph swaps in.

MIDI

When the player starts it auto-connects to every MIDI input port currently visible to the system. There is no UI for choosing a device — plug the controller in before launching, and it appears. Events from any connected port feed into the patch’s MIDI source modules (MidiToCv, PolyMidiToCv, MidiCC, etc.).

If no ports are available, the player logs a warning and keeps running; you can still drive sequenced patches that don’t need external input.

To connect a new device after launch, exit and re-run — MIDI ports are opened once at startup. Re-running is cheap; the patch reloads fresh.

Audio routing

Use --list-devices to see what CPAL exposes:

patch_player --list-devices

Then point at a specific device with --output-device:

patch_player --output-device "External Headphones" examples/square_440.patches

--input-device <name> opens a capture device for modules that process input audio (AudioIn and friends). Names are matched literally; if the host system reports a device as "Built-in Microphone (Builtin)", that whole string is the argument.

--oversampling <1|2|4|8> raises the internal sample rate before downsampling to the device rate — useful for alias-heavy patches (unfiltered saw, hard sync). Default is 1 (no oversampling).

Recording

patch_player --record session.wav examples/tracker_three_voices.patches

The output stream is forked into a 16-bit PCM stereo WAV at the device’s sample rate. The file finalises when the player exits (Ctrl-C is fine; it runs the recorder’s Drop impl on the way out). Crash the process and the WAV header will be incomplete.

Hot-reload

The player watches the patch file. Save it, and the engine builds the new graph and swaps it in without stopping the audio. Module instances whose name and type are unchanged keep their internal state across the swap — an oscillator’s phase, a delay’s buffer, an envelope’s position — so small edits sound like parameter tweaks rather than restarts.

This is the development REPL described in the introduction. See The edit-reload cycle for the rules on what survives a reload, what resets, and how to structure patches to make iteration smooth.

Other flags

patch_player with no arguments prints the full flag list. Common options:

FlagEffect
--no-tuiLegacy stdout frontend (no TUI).
--no-stdinWith --no-tui, also skip reading from stdin.
--module-path <path>Scan a directory or specific dylib for FFI module bundles. Repeatable.
--output-device <name>Open a specific audio output device by name.
--input-device <name>Open a specific audio input device by name.
--oversampling <N>Internal sample-rate multiplier N ∈ {1, 2, 4, 8}; default 1.
--record <path>Fork the output stream to a 16-bit PCM stereo WAV at the device rate.
--monitorEnable the per-instance CPU monitor tab.
--list-devicesEnumerate audio devices and exit.

--no-tui is most useful for headless smoke runs and CI — it just prints to stdout and reads from stdin, no terminal raw mode.

Exiting

Ctrl-C in the TUI. The player tears down the audio stream, finalises any WAV recording, and restores the terminal. If the terminal looks broken after an unclean exit, reset will fix it.