A digital instrument built around a single idea: modulation is the instrument. Two symmetric parts, each driven by a performable modulation engine, feeding a selectable sound source.
It runs today on the desktop and inside VCV Rack. The hardware target is a standalone Daisy Patch Submodule prototype, brought up in milestone M6.
Build log, audio demos and photos: fireflow.ton-k.de
⚠️ Not yet running on hardware. The modulation engine currently exists only as a portable C++ core, verified with the desktop offline renderer (unit tests + audio/CV render) and playable through the VCV Rack host. Selected CPU workloads have been measured on a real Daisy Seed; the firmware shell that turns the engine into a playable device is milestone M6, and it has not been built.
The modulation system is the primary interface, and the sound engine is whatever you point it at — not a sound engine you happen to be able to modulate.
Each part currently points at one of five: a polyphonic synth voice, a granular texture deck that granulates live input or a loaded sample, WAVE, a digital-glassy PPG-style wavetable voice, BODY, a resonator that morphs along a physical axis from plucked string through prepared piano to struck bell, or BBD, a voiceless bucket-brigade delay that processes whatever reaches it — audio input or the other deck — instead of playing notes. The deck is deliberately not a second melodic instrument — it is the room the synth part plays in; WAVE covers the bell, vocal-formant, hollow-resonant, and bright-digital corner; BODY is the struck and bowed one, and it can be excited by its own echo, by the other deck, or by the audio input; BBD is the one deck with nothing to trigger — it has no notes, so its five modulation lanes drive the delay's clock, feedback and mix instead of pitch and timbre, and its own voice row retunes ATTACK/DECAY/RESONANCE/SUB/ FILT into the delay's freeze, tail, feedback tilt, input level and loss-pole brightness. All five sit behind the same five modulation lanes and the same voice row, so no knob goes dead when you flip the engine.
That voice-row SOURCE control is contextual — TIMB on Synth, FRAME on WAVE, MATL on BODY, ORG on Sampler, and DRIVE on BBD — while Detune A/B remains an independent per-part setting.
On the texture deck, STEP walks a SliceMap of transients marked while the
buffer is recorded or loaded: each phrase fire spawns one grain on a real
attack in the material. MOTION moves that walk from ordered playback at zero
toward free traversal. DENS controls runtime grain overlap; COLOR
becomes FEEL in STEP, deriving accents from the material, and spreads the
cloud's pitch in FLOW. Material without enough transients falls back to the
even tempo grid automatically, so drones and pads stay playable. FLOW still
moves continuously across the same lanes regardless of engine.
Melodic STEP lanes keep two persistent full-pattern snapshots, A and B. FORM chooses how those phrases are composed — TWO MOTIFS, ONE + VAR, HIERARCHICAL, CALL / RESPONSE, or OSTINATO — while SONG independently arranges them as AAAB, ABAB, ABBB, BUILD, ROTATE, MIRROR, or OFF. Structural changes land on phrase boundaries; OFF keeps A evolving while B remains stored. On the Rack panel the PLAY row is STEP · FORM · SONG · NEW. NEW rebuilds the A/B pair and, on a Sampler, also spawns a grain immediately.
Those STEP notes are not all the same note. Each deck already ranks the slots of its groove, and DENSE decides how far down that ranking it fires — so the first slot to sound is the anchor and the ones DENSE reveals sit under it. That ranking is the accent: it scales how hard a note is struck and how long it rings (the ring-time half only once DEC is up), which gives a dense pattern a contour instead of a machine pulse. No knob was added for it.
Each of the two parts is a SuperModulator — one performable macro surface (RATE, SHAPE, DENSITY, SMOOTH, RANGE, MOD) sitting on top of five independent modulation lanes, one per target. Every lane has its own phase, its own random stream and its own probability dice, running at a fixed musical ratio of the master rate. Shared character, independent motion: the melody can rise while the filter falls. (A single output driving all targets would just move everything in unison — a tremolo, not an instrument.)
Each lane can run as a smooth LFO (FLOW), a stepped sequence (STEP), or grow, loop, or erode over time (ENTROPY). A center section -- MORPH / COUPLE / DRIFT / SPOT / SETTLE -- makes the interaction between the two parts playable. One shared Oliverb-based ambient reverb turns the room into an instrument (Doppler SIZE and a DECAY that blooms past 100 %), while each deck has its own SEND dry/send mix into that shared room (the centre ROOM group holds the reverb itself). CV + gate outputs extend the modulation to the rest of the rack.
The full design intent lives in
docs/superpowers/specs/; this README is a
self-contained summary of it.
One portable engine core, three hosts. No hardware type ever crosses into
engine/, so the exact same code runs in the desktop renderer, the VCV Rack
module, and (later) on the hardware prototype.
Instrument (engine/instrument.h) is the complete public API: init(sample_rate),
normalized 0..1 parameter setters, and process(in, out, size).
The engine is fully testable offline. You need a host C++ toolchain
(clang or gcc), CMake, and Ninja. doctest and nlohmann/json are
vendored under third_party/, so no test dependencies are fetched.
# optional: source a local env.sh to put your toolchain on PATH and set CC/CXX
source env.sh
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildRun the unit tests:
ctest --test-dir build --output-on-failureConfigure with -DCMAKE_BUILD_TYPE=Release. Two of the six tests (spky_tests
and ctrl_identity) compare rendered audio against stored SHA-256 references,
and those were generated from an optimised build — a Debug configuration renders
slightly different floats and fails them with SYNTH reference moved.
Render a scenario to audio + a modulation trace. A scenario is a JSON timeline
of parameter changes (see host/render/scenarios/):
./build/render.exe host/render/scenarios/demo_step_melody.json out.wav mods.csvThis writes:
out.wav— the rendered audio.mods.csv— every lane's output plus pitch CV / gate per part, decimated for plotting. Ideal for seeing what FLOW / STEP / MELODY actually do.
demo_step_melody is a good starting point: a fixed 16-step melody that loops
identically, then varies (GROW) or regenerates into new motivic phrases (RENEW)
as MELODY is dialled off center — and cycles the phrase principle.
For a hands-on feel of the concept there's a VCV Rack plugin (host/vcv/)
that runs the same engine live — turn the knobs and hear the modulation engine
long before the M6 firmware. It's now a beta: real, playable Rack modules and
a permanent part of the workflow, not yet a finished instrument.
The plugin ships two modules over the one engine core. FireFlow is the
full surface: every engine setter on its own knob. FireFlow HW Draft is a
design study of the 60 HP hardware panel M6 is heading for, on the same engine.
Details in host/vcv/README.md.
You can also just listen first: the build log carries recordings from most milestones, next to the story of how they came about.
Download the latest release
— .vcvplugin builds for Windows, Apple Silicon and Linux, currently 2.22.0
(both modules: Synth, Sampler, WAVE, BODY, BBD and FEED, the independent
FORM/SONG phrase arranger, the STEP mod grid lock, the PACE modulation
time-stretch, the redrawn 60 HP hardware plate with its excursion lamps, the
STEP accent, PULL's chord gravity, and the MOD layer — hold MOD and every
wreathed knob edits its own modulation depth). Unpack into Rack's user plugin
directory and restart Rack.
Building it yourself needs its own toolchain (a native MinGW/GCC compiler, not
the desktop clang path); the build, install and I/O details live in
host/vcv/README.md.
| Milestone | Scope | Status |
|---|---|---|
| M1 | Portable engine foundation: SuperModulator, five lanes, Instrument API, desktop render host + tests |
✅ done |
| M1.6 | FX: per-part FLUX (tape echo) + GRIT (drive/reduce), shared ambient reverb, FX params as modulation targets | done (engine + host) |
| M2 | Polyphonic synth voice (replaces the M1 test tone) | done (engine + host) |
| M3 | Capture sequencer (freeze the PITCH lane into a loop) | built, then removed 2026-07-14 as orthogonal to the melody rework; nothing replaced it |
| M4 | Center section — MORPH / COUPLE / DRIFT / SPOT / SETTLE | done (engine + host) |
| M4.5 | Ambient reverb v2 — Oliverb port: Doppler SIZE, DECAY > 100 % bloom, TONE; shimmer & LGPL removed | done (engine + host) |
| M4.6 | Dynamics — one-knob comp per part + master limiter w/ master drive (captioned PUSH on the panel) | done (engine + host) |
| M4.8 | Reverb dry/wet — equal-power MIX at the master join + clear-on-sleep CPU bypass | done (engine + host) |
| M4.9 | Reverb DIFFUSION knob (replaces DEPTH) — room density 0–0.9, weak line-mod coupling | done (engine + host) |
| M4.10 | Chord layer — COLOR knob, diatonic stacks, voice-leading, live FLOW surface | done (engine + hosts; hardware placement deferred) |
| M5 | Sampler -- the texture deck: granular cloud, live recording + overdub, WAV load/save, Morphagene-style DENS/SCAN/NEW/LEN/ORG controls, clocked slice-groove, FEEL accents, and FLOW cloud dispersion | done (engine + hosts; released through 2.11.0) |
| M5h | Per-deck SEND mix: independent dry/send mix per deck into one shared Oliverb reverb | done (engine + VCV panel; released in 2.11.0) |
| CPU | Three measured rounds on real hardware: instrument_worst's worst block went from ~156 % of the audio-block budget to 94 %, and back up to 102 % when M5j's tape tap landed (measured at 5.4 % of the block). Since then an optimization ladder (DTCM placement, an ITCM audio hotset, -O3) brought the selected gate instrument_worst_bbd_dtcm to 96.43 % of the block on a Daisy Seed, and the whole signal path has been re-measured against it. The engine's own worst case still does not fit: on a Patch Submodule instrument_worst reads 102.27 % average / 108.62 % maximum, and whether that is a reachable operating point is an open question. Two more caveats live in docs/roadmap.md: every workload is more expensive on the submodule than on the Seed (reserve 2.17 points, so no Seed figure may be quoted for a submodule claim), and the intended ITCM placement does not currently link at the optimization level that ships. A debug probe is no longer needed — the bench also reports over USB-CDC. Method and every number in bench/ and docs/bench/ |
done (ongoing as a tool) |
| M5i | WAVE: four-voice PPG-style wavetable part engine | done (engine + renderer + VCV; 65,024-byte mapped-QSPI bank; hardware-gated; released in 2.13.0) |
| + FORM/SONG | Persistent A/B phrase snapshots: five FORM phrase engines plus AAAB, ABAB, ABBB, BUILD, ROTATE, MIRROR, and OFF SONG arrangements; boundary-safe changes and legacy patch migration | done (engine + renderer + VCV; released in 2.13.1) |
| M5j | BODY: one-voice-per-deck resonator part engine, morphing string -> metal -> bell, with a sympathetic excitation bus | done (engine + renderer + VCV; hardware-gated: body_2x4 295078 cycles, 30.7 % of the block, inside the spec's 29-32 % prediction and cheaper than SYNTH) |
| BBD | A bucket-brigade delay model, where the clock rate is the delay time — so RATE bends stored pitch only transiently, while it moves: held steady, a bucket-brigade line's pitch is unity at any clock rate. It first replaced FLUX's tape echo everywhere and now lives on as the fifth part engine only; FLUX itself is a plain tape echo again. FXT_FLUX_TIME is a genuine chorus/vibrato modulation lane, and STAGES has moved onto the BBD deck's own pitch lane, captioned BEND on the panel |
done (engine + renderer + VCV; released in 2.17.0/2.17.1, measured on hardware — inst_bbd_engine_worst 96.91 % of the block at -O3) |
| Modulation reachability | Four rounds that made the modulation surface mean what it says: PACE, one global time-stretch from ×1/32 to ×4, because TEMPO was inert in the free world and TIDE never reached the melodic lane; the FLOW melody engine, so the free mode's melodic lane walks an 8-slot phrase instead of a continuous LFO; the same phrase in STEP, which makes FORM and SONG audible at every SHAPE position instead of only above 0.75; and SMOOTH as a fraction of the lane interval rather than absolute seconds, so the knob means the same thing at every rate | done (engine + hosts; released in 2.21.2) |
| 60 HP plate | The hardware panel, drawn and playable in Rack as the second module: seven engine-grounded groups, eight CV inputs under the knobs they drive, and a dark anodised plate with framed fields and numbered legends | done as a design study (released in 2.21.2/2.21.3; still labelled DRAFT, no hardware ordered) |
| STEP accent | STEP notes get a contour from the groove rank the deck already computes: the anchor slot is loudest and longest, the slots DENSE reveals sit under it, on velocity and — once DEC is up — on ring time. No new control, no new randomness, FLOW unaffected; SYNTH, WAVE and BODY only | done (engine; released in 2.21.4) |
| LED feedback | What the panel shows while it runs: a lamp tracks the modulation excursion, never the knob position — one per texture lane, plus a phrase lamp per deck, a ceiling lamp for the limiter's audible onset, and the two modifier lamps. Nineteen lamps on the hardware plate, up from ten | done (engine + VCV FireflowHW; released in 2.21.5; four brightness constants still wait on real hardware) |
| FEED | Sixth part engine: a ring of six two-operator FM pairs per deck, free-running, where BOND morphs each modulator's input from its own feedback into its neighbour's output — the motion is the coupling, not an LFO on top | done (engine + hosts; released in 2.21.6; measured on a Patch Submodule, seventeen by-ear constants still first-try) |
| M5l | PULL: chord gravity between the two decks — a bipolar centre knob draws one deck's melody onto the other's sounding chord | done (engine + both VCV panels; released in 2.21.8; no listening pass yet) |
| MOD layer | Hold MOD and every wreathed knob shows and edits its own modulation depth instead of its sound value. The depth knobs are bipolar: right of noon the lane's continuous output, left of noon the same lane sampled and held on its own slots, noon off | done (engine + VCV FireflowHW; released in 2.21.7 and 2.21.10) |
| AIR | Noise/formant texture engine (working title): filtered noise through a resonant bank — wind, breath, vowel colours without sample material | planned (no spec yet) |
| M5k | ZAP: monophonic percussion part engine | planned (spec ready; not implemented) |
| M6 | Hardware prototype: bring-up on a Daisy Patch Submodule — panel, controls, LEDs, CV/gate I/O, preset persistence | planned after AIR and M5k (panel design done, see above; bring-up needs a new spec — the existing shell spec assumes Spotykach's panel) |
Per-milestone detail and current status live in docs/roadmap.md.
The instrument's own hardware is a standalone Daisy Patch Submodule
prototype — panel, controls, LEDs, CV/gate I/O and preset persistence — planned
as milestone M6, after the two remaining engine milestones. No firmware of it
is built yet. Its panel is designed, though, and you can turn it: the plugin's
second module, FireFlow HW Draft, is that 60 HP surface on the same engine,
generated from host/vcv/res/gen_hw_panel.py and guarded against the spec's own
coordinates. What still has no spec is the bring-up itself — the existing
firmware-shell spec was written against a different device and no longer
describes the target.
CPU headroom on the target MCU is not guesswork, though. Selected workloads are
measured on real Daisy hardware (a Daisy Seed, which carries the same STM32H750
at 480 MHz as the Patch Submodule) — method and every number in
bench/ and docs/bench/.
The original Spotykach firmware this project started from is still in the tree
and still builds; its setup, compile and DFU-flash instructions live in
docs/upstream-firmware.md.
MIT — see LICENSE (Copyright © 2026 Synthux Academy, Bastian Tonk).
FireFlow began as a fork of
Synthux-Academy/Spotykach, the
official firmware for the Spotykach hardware, and reuses parts of it; it is now
an independent project with its own hardware target. It was called spotymod
until 2026-08-04 — releases up to and including 2.18.x carry that name.
Bundled and submodule dependencies are documented in
THIRD_PARTY.md. Original firmware credits are in
CREDITS.md.
Built with AI pair-programming — the HAL 9000 co-author in the git history is Claude (Anthropic). 🔴


