downspout is a clean repository for porting selected flues LV2 plugins into more widely usable native plugin formats, with VST3 as the first practical target.
The motivation is straightforward:
- the existing
fluesLV2 plugins already contain promising DSP and host-interaction work; - LV2 adoption is limited across mainstream DAWs;
- local development has been Linux-centric, which reduces real-world feedback from other producers.
The project should therefore focus on preserving proven behavior while re-hosting that behavior in a portable plugin framework.
The first ports will be based on:
~/github/flues/lv2/bassgen~/github/flues/lv2/p-mix
Original follow-on plugin idea:
counterpointer: transport-aware MIDI processor that learns the incoming MIDI pattern, likecadence, and emits a complementary monophonic counter-melody.
These two plugins were chosen deliberately because together they cover the main migration risks:
bassgenexercises MIDI generation, transport sync, state persistence, and control/UI messaging.p-mixexercises audio processing, transport-driven behavior, state, and host channel-layout decisions.
Those ports established the project pattern now used by the wider plugin set: portable core, deterministic tests, thin DPF wrapper, custom UI, and local VST3 install packaging.
Current direction is to use DPF as the plugin framework.
Reasoning:
- DPF supports VST3, LV2, CLAP, and standalone builds from one codebase.
- DPF exposes host time-position support, which is essential for both
bassgenandp-mix. - DPF supports plugin state and custom UI paths, which are both relevant to the selected targets.
Important constraint:
- DPF is the integration layer, not the architecture.
- Shared DSP and musical logic should live outside framework entry points so ports remain testable and maintainable.
As of 2026-04-18, the working requirements are:
- Preserve the musical and transport behavior of the source LV2 plugins before adding new features.
- Support host transport/time information robustly enough for bar-based and loop-aware behavior.
- Evolve transport-aware generators toward true meter-aware behavior where the musical goal requires it, especially for compound meters and grouped pulse feel.
- Support saved/restored plugin state.
- Support custom UI, but do not let UI decisions block DSP/core migration.
- Keep per-plugin metadata, parameters, defaults, and ranges traceable back to source implementations.
- Use a multi-plugin repository layout.
- Separate shared reusable code from plugin-specific wrappers.
- Separate framework-neutral logic from DPF-specific glue.
- Keep build files modular so incomplete plugins do not break the whole tree.
- Add automated tests for deterministic logic.
- Add explicit regression coverage for transport edge cases.
- Keep documentation short, technical, and current.
Each plugin port should follow this order:
- Audit the source LV2 plugin and identify host-neutral logic.
- Extract deterministic core logic into plain C++ classes with tests.
- Define parameter/state contracts for the new plugin.
- Add DPF wrapper code for DSP and transport access.
- Add UI wrapper code after the core behavior is stable.
- Compare behavior against the source plugin in a host.
This order matters. The mistake to avoid is porting LV2 structure directly into DPF without first isolating what is actually plugin logic versus host plumbing.
downspout/
├── AGENTS.md
├── CMakeLists.txt
├── README.md
├── cmake/
├── docs/
│ ├── plan.md
│ └── requirements.md
├── include/
│ └── downspout/
├── plugins/
│ ├── bassgen/
│ │ ├── CMakeLists.txt
│ │ ├── docs/
│ │ ├── include/
│ │ └── src/
│ └── p-mix/
│ ├── CMakeLists.txt
│ ├── docs/
│ ├── include/
│ └── src/
├── src/
│ └── common/
├── tests/
└── third_party/
DPF appears viable for this project, but a few implications need to guide implementation:
- plugin code should be written in C++, even when porting from mixed C/C++ LV2 code;
- framework-specific state and UI messaging must be kept thin and isolated;
- transport handling should be validated carefully because both target plugins depend on host timing;
- DPF can support multiple output formats later, but the first milestone should target one format cleanly rather than many formats poorly.
The initial scaffold and first-port work are complete enough that the project now has a stable implementation pattern: portable core, deterministic tests, thin DPF wrapper, custom UI, local install script, and release packaging.
Progress as of 2026-05-27:
- root planning and requirements documents exist;
- repository rules and scaffold exist;
bassgenhas a portable core library with deterministic tests;bassgennow builds as a VST3 bundle with UI via vendored DPF;p-mixnow builds as a first VST3 wrapper with UI via vendored DPF;e-mixnow has a portable core library, deterministic tests, and a first VST3 wrapper target with a redesigned UI via vendored DPF;m-mixnow has a portable MIDI-gate core, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;t-mixnow exists as an original eight-input stereo mixer with a portable summing core, constant-power pan, mute/solo behavior, pre-fader meters, deterministic tests, and a DPF/VST3 wrapper with a mixer-style UI; it now accepts sample-accurate, click-smoothed CC 20-27 producer-gain overlays while preserving manual faders as the saved mix balance;mixgennow exists as an original automatic producer fort-mix, with repeatable random, low-discrepancy quasi-random, and Euclidean eight-lane gain patterns, transport synchronization, live lane status, deterministic tests, and a focused DPF/VST3 UI;loopdelaynow exists as a stereo delay and capture looper intended aftert-mix, with free or BBT-derived time, feedback/ping-pong/overdub shaping, sample-accurate fixed CC 30/31 producer control, transient MIDI takeover, deterministic transport tests, and a task-oriented DPF/VST3 UI;lightverbnow exists as a low-CPU stereo reverb for the Transmission mix path, using a fixed-cost four-line feedback-delay network, exact dry and 100%-wet send operation, non-conflicting CC 32/33 producer control, deterministic safety/allocation tests, and a focused DPF/VST3 UI;- Producer Control Bus v1 now loosely coordinates Mixgen, T-Mix, Loopdelay, and Lightverb through CC 19 lifecycle, CC 20–33 payloads, per-chain channel filtering, optional ownership gates, transparent MIDI-through, configurable Mixgen FX macro routing, and an end-to-end portable contract test;
melgennow has a phrase-aware MIDI melody core, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;riftnow exists as an originaldownspouttransport-aware live/sample buffer effect with WAV loading, beat-mapped sample playback, a portable core, deterministic tests, and a VST3 wrapper target with UI via vendored DPF;drumgennow has a portable core library, a host-neutral MIDI engine, text serialization helpers, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;drumkitnow ports thefluesdrum synth through a portable core and a first VST3 instrument wrapper with UI via vendored DPF;cadencenow has a portable core library, a host-neutral learning/playback engine, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;arpgennow exists as an original transport-synced MIDI arpeggiator with meter-relative chord capture, scale-derived material, deterministic tests, and a DPF/VST3 wrapper with custom UI;counterpointernow has a portable core, deterministic tests, text state serialization, and a first DPF/VST3 wrapper with custom UI;sidecarnow exists as an original AI-ready MIDI phrase player with local phrase validation, deterministic fallback generation, text state serialization, transport-aware playback, deterministic tests, and a first DPF/VST3 wrapper with custom UI;gremlinnow has a portable core library, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;gremlin-drivernow has a portable MIDI modulation core, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;groundnow exists as an original long-form MIDI bass generator with a portable form-planning core, explicit Dub and Jazz styles, guarded bass-register output, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;floozynow portsflues/lv2/floozy-polyas a corrected 8-voice hybrid physical/modulation synth with a portable core, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;basiliconow exists as an original monophonic bass instrument with upright, electric, dub, acid, and industrial models, tempo-aware wobble modulation, acid squelch, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;canticlenow exists as an original 12-voice polyphonic tonal instrument for keys, reed, pad, pluck, and glass roles, with deterministic tests and a first VST3 wrapper target with UI via vendored DPF;mokanow exists as an original stereo modal hit-object instrument (xylophone, glockenspiel, woodblock, glass bowl, metal sheet, tube) with ten controls, eleven factory presets, selectable 1–12 voice polyphony defaulting to 4, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF. Notes ramp in over the mallet contact time so no note opens with an impulse, and the panel plots the live partial ladder and ring time from the same table maths the engine renders;lumanow exists as an original Launchpad-oriented MIDI performance generator with pad agents, LED feedback, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;paunchladnow exists as an original Launchpad-oriented dub performance effect with echo throws, sirens, spring splashes, dropouts, chops, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;lifeformnow exists as an original Launchpad-oriented Conway Game of Life MIDI generator with one generation per beat, LED feedback, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;prattnow ports the offlinepratt-synthrenderer to a real-time plugin built on Pratt polynomials (f_n(2) = n,f_mn = f_m f_n) and the stable all-pole filterH_n(s) = n / f_n(2 + s/w0): eleven General MIDI voice families whose spectra come fromH_natn = (note + 1) x base, and a Pratt filter effect whose two index controls cascade asH_m H_n = H_mn, usable on its own, on audio, or after the synth. The engine matches the Python renderer's harmonics within 0.12 dB, has deterministic core/engine/state/threading suites (the last also run under ThreadSanitizer), a worker thread that pre-builds wavetables off the audio thread, and a VST3 wrapper with UI; host validation is pending;retunenow exists as an original MIDI effect that retunes notes to a Scala.sclscale (cents and ratio lines, strict parser) by sending each held note on its own output channel (2-16) behind a per-note pitch bend, with oldest-note stealing; CC and program change are broadcast to the pool, poly aftertouch follows its note, and incoming pitch bend and channel aftertouch are dropped. It has a deterministic core suite (also run under ASan/UBSan), a VST3 wrapper with a scale map UI, and awaits host validation;markovnow exists as an original Markov-chain melody generator: a random walk over the twelve pitch classes through a 12 x 12 transition matrix that is drawn on screen and can be edited, filled from one of eight styles, or learned from a melodic line on the MIDI input (first-order counts for every pair, second-order counts for every triple). The scale masks the matrix, Chaos reshapes it, and each phrase restarts the walk from the tonic so any position renders the same notes. It has a deterministic core suite (also run under ASan/UBSan) including locate and block-size independence, Conductor CC support, and a VST3 wrapper with a Magneto-look matrix editor; host validation is pending;sproutnow exists as an original L-system MIDI generator: seven grammars (Plant, Koch, Dragon, Sierpinski, Cantor, Levy, Tree) are rewritten per generation, read as a turtle (F/G note, f rest, +/- degree, brackets branch) and played as a scale-quantised line with folding range, gate, seeded probability and branch-depth velocity. A Grow control adds one generation every N bars. It is stateless against the host transport, has a deterministic core suite (block-size independence, scale pins fromdocs/scales.md), and a VST3 wrapper with a pattern plot; host validation is pending;planknow reimplements Plinky's voice engine as a portable eight-string synthesizer: a polyBLEP oscillator pair morphing into seventeen synthesised band-limited wavetables, Plinky's resonant two-pole filter, two envelopes, dynamic parameter smoothing, tape delay, shimmer reverb and mid/side width, played as one string per Launchpad grid column, with LED feedback, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;xoxolonow exists as an original simple MIDI drum pattern editor with a fixed 11-lane drumkit map, 32-step maximum, text state serialization, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;tuney-vstnow ports Tuney 0.3.39's text-to-music core as a focused-typing instrument/MIDI generator with portable mapping, tuning, free-time scheduling, synthesis, versioned text state, deterministic tests, and a DPF UI;campionenow exists as an original multi-zone sampler instrument with per-note MIDI mapping, WAV file loading, REX2 slice import (via VelociLoops), Serum/clm wavetable auto-detection, audio recording with auto-pitch detection, pitch-shift gap fill, zero-crossing loop snap, crossfade looping, deterministic core, and a first VST3 wrapper target with UI via vendored DPF;magnetonow exists as an original physically informed combustion engine sound generator ported from Baldan et al., SIVE'15: four-stroke cycle functions, per-cylinder digital waveguides with valve-modulated feedback and piston-modulated length, intake runners, extractors, straight pipe, prime-length four-element muffler, tailpipe, overrun-only backfire, manual/CC/host-tempo engine speed, listening-position stereo mix, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;chippernow exists as an original stereo lo-fi processor with bitwise quantization, sample-rate reduction via sample-and-hold, clock jitter, dry/wet mix, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;ghostnow exists as an original audio-triggered ghost-note generator with BBT-quantised 16th-grid ghosts, drum (ch 10) and note modes, four Drift-CC feel controls, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;spliffnow exists as a Spiff-manner adaptive transient processor with a 3-band detector, cut/boost modes, sensitivity, sharpness, decay with LF/HF tilt, mix/trim/delta/bypass, Drift-CC control, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;helterskelternow exists as an automatic wah pedal with a resonant lowpass driven by the input envelope and/or a BBT-synced ADSR cycle, full ADSR, gate invert, Drift-CC control, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;treatmentnow exists as a physically modelled acoustic treatment panel: a mass-air-mass absorber whose resonance followsw0 = c*sqrt(rho0/(m*D))and whose absorption is maximal at the impedance optimumr = rho0*c, so the panel has a real sweet spot rather than "more is better". Parameters are real panel quantities in mm, kg/m2 and Rayl/m; a seeded Randomise trigger builds a new plausible panel while preserving Amount and Bypass; five Drift-CC lanes drive the geometry; read-only status parameters report the derived resonance, peak absorption and fill diffusion corner; both biquad stages are cuts only and the tests assert the cascade never boosts anywhere in the parameter space; deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;voxmodnow exists as a combined vocoder and ring modulator sharing one four-input bus: a filter-bank vocoder that analyses the carrier on inputs 1/2 and re-imposes its spectral envelope on the modulator from 3/4, running in parallel with a polyBLEP-band-limited ring modulator over the same modulator, blended by a singleMixparameter rather than a mode switch. Band edges are logarithmic so the bank does not starve the formants, and are constant-skirt so resynthesis gain does not tilt with band width.Ring Ratiois quantised to 16 musical steps so sideband moves are repeatable, andFormanttransposes the modulator side of the bank only, which relocates the envelope rather than transposing the whole signal.Syncroutes the ring-modulated signal back as the vocoder's carrier so inputs 3/4 alone are sufficient. Five Drift-CC lanes; read-only status parameters report the effective carrier frequency, carrier sibilance and band-gate reduction; deterministic tests, and a first VST3 wrapper target with a NanoVG UI via vendored DPF;keyframenow exists as an extrema-sampling time stretch after Nielsen's DAFx26-26 method: bandlimited B-spline derivative analysis, difference thresholding, subsample extrema location, a three-playhead sparse-domain overlap-add engine whose crossfade length follows keyframe spacing, independent time and pitch rates, reference hold, fixed reported latency with a matched dry delay, deterministic tests, and a first VST3 wrapper target with UI via vendored DPF;install.shexists as the intended build/install entrypoint for local VST deployment.
Current main gap:
- DPF is now vendored and all current wrapper targets build successfully.
install.shandscripts/package-release.shnow install and package realbassgen.vst3,p_mix.vst3,e_mix.vst3,m_mix.vst3,t_mix.vst3,mixgen.vst3,loopdelay.vst3,lightverb.vst3,melgen.vst3,rift.vst3,orchid.vst3,ambo.vst3,drumgen.vst3,drumkit.vst3,cadence.vst3,arpgen.vst3,counterpointer.vst3,sidecar.vst3,gremlin.vst3,gremlin_driver.vst3,ground.vst3,floozy.vst3,basilico.vst3,canticle.vst3,moka.vst3,luma.vst3,paunchlad.vst3,lifeform.vst3,plank.vst3,pratt.vst3,retune.vst3,sprout.vst3,markov.vst3, andxoxolo.vst3,syrinx.vst3,tuney_vst.vst3,harmonic_atlas.vst3,conductor.vst3,drift.vst3,mnemosyne.vst3,polymeter.vst3,oracle.vst3,mosaic.vst3,resonance_garden.vst3,orbit.vst3,guardian.vst3,campione.vst3,skream.vst3,chipper.vst3, andmagneto.vst3,ghost.vst3,spliff.vst3,helterskelter.vst3,treatment.vst3,voxmod.vst3, andkeyframe.vst3bundles.bassgennow has a richer Jazz model with ii-V-I-turnaround roles, dominant color, chord-tone targeting, approaches/enclosures, and a generalColorcontrol.- the main remaining gaps are host validation across the full plugin set, validating the expanded release payload, and deeper interaction testing of the generative-workstation suite in Transmission.
The first implementation of Harmonic Atlas, Conductor, Drift, Mnemosyne, Polymeter, Oracle, Mosaic, Resonance Garden, Orbit, and Guardian proved the portable cores and host wrappers, but rendered every parameter through the same anonymous slider grid. That made choice values, switches, MIDI routing, processor status, and musical relationships difficult to understand in practice.
The approved UI-readiness pass for these ten plugins is:
- Replace numeric enum and boolean sliders with named choices, switches, and action buttons. Display musical notes, pitch classes, MIDI channels, CC destinations, beat/bar units, percentages, milliseconds, and decibels in domain terms.
- Use explicit workflow sections and separate read-only processor feedback from editable controls. Provide default reset gestures, concise contextual help, and strong disabled-state treatment where a control is not currently relevant.
- Give Harmonic Atlas a current-chord/keyboard view; Conductor a section timeline; Mnemosyne a reservoir view; Oracle an analysis dashboard; Resonance Garden a resonator-energy view; Orbit a trajectory view; and Guardian conventional safety meters and diagnostic lamps.
- Give Drift and Polymeter consistent four-lane layouts with per-lane mode or pattern previews rather than splitting lanes across unrelated columns.
- Give Mosaic a complete four-slot sample workflow with visible load, replace, clear, filename, and error/empty status controls. File loading remains on the DPF state/control path and never occurs in audio processing.
- Rebuild the ten core tests and VST3 targets, validate the bundles, capture and inspect updated catalogue screenshots, and document a practical host test recipe before considering the suite UI-ready.
Per-plugin usability targets:
- Harmonic Atlas: named movement/voicing choices, musical pitch-class labels, clear routing, and a live root/keyboard view.
- Conductor: a visible section timeline, named form modes, coherent section weights, and separately grouped advanced MIDI commands.
- Drift: four complete lane cards with named sources, shape previews, musical timing, bounded ranges, and readable CC destinations.
- Mnemosyne: visible reservoir occupancy, named modes/transforms, capture guidance, and an explicit clear-memory workflow.
- Polymeter: one coherent view per lane with Euclidean pattern/playhead, note names, and primary rhythm controls kept together.
- Oracle: separate listening, response, and routing workflows with live analysis meters and musical response boundaries.
- Mosaic: four visible sample slots with load/replace/clear actions, filenames, pool status, and a slice/grain visualization.
- Resonance Garden: grouped resonance/tuning/output controls and a live eight-voice pitch/energy view.
- Orbit: named trajectories, musical timing, contextual seed control, and a live path/position view.
- Guardian: conventional limiter meters, protection switches, neutral diagnostics, reported look-ahead, and a real diagnostic-reset button.
The shared implementation remains local to plugins/generative-common; it is
not a replacement for established plugin UIs elsewhere in the repository.
The practical host checklist is maintained in
docs/generative-suite-test.md.
The next architectural addition was shared meter handling.
Reasoning:
- several wrappers already followed host bar timing successfully;
groundanddrumgenneeded a structural refactor away from fixed4/4bar math;bassgenis more adaptable, but its rhythmic language is still simple-meter oriented;- compound-meter work is necessary if
downspoutis going to support use cases such as generative Irish folk material.
See docs/meter.md for the concrete design target and plugin impact.
The next work should proceed in this order:
- Continue host validation of the current plugin set in Reaper and fix any DAW-facing issues that block basic use.
- Add folk-oriented style vocabulary where musically justified: reel, jig, slip jig, hornpipe, polka, drone/modal accompaniment.
- Add pickup/anacrusis handling and phrase-end behavior where the generator concept needs it.
- Validate the release-build workflow on the first public tag so installable bundles can be built reproducibly on GitHub, not just locally.
Reasoning:
- the current plugin set already follows the portable-core-plus-wrapper pattern, so the highest-value work has shifted to host behavior, routing validation, UI clarity, and release packaging.
- release builds need to become a first-class workflow before the repository is ready for broader use beyond local iteration.
- DAW validation exposed a broader architectural gap: transport sync existed, but true meter support did not exist consistently across the generator plugins.
- the shared meter abstraction now exists and is wired into the transport layer plus the
bassgen,ground, anddrumgengenerators.
- No attempt to port every
fluesplugin immediately. - No premature UI redesign.
- No hard dependency on a single DAW for validation.
- No copy-paste port that keeps LV2 assumptions embedded in the core logic.