ENGINE=qdelay · src/engine/qdelay/qdelay_engine.{h,cpp} · class QdelayEngine
A second "flavor" of the tempo-synced dual delay, inspired by qdelay. It keeps the delay engine's entire control grammar — tempo-locked musical divisions, feedback, mix, PITCH transpose, ENV tone, the mod LFO, the Freeze/Reverse pad gestures and the three stereo topologies — and swaps only the character palette from Clean/Tape/Shimmer to Clean / Diffuse / Duck. The aim is the smeared, reverb-leaning dub end of the delay spectrum rather than the warble-and-shimmer end.
Because the binding constraint on the hardware is the control surface (a handful of knobs and two 3-way switches), qdelay does not expose the desktop plugin's ~40 parameters. It picks the highest-value, lowest-cost slice — feedback diffusion and ducking — and maps them onto the existing mode switch.
Implementation, the file map, and dev notes live in
docs/dev/qdelay-impl.md.
License: unlike the rest of this MIT project, the qdelay engine is GPLv3 —
src/dsp/diffuser.his a port of qdelay's GPLv3Diffusor, so the engine and anyENGINE=qdelaybinary are GPLv3. Seesrc/engine/qdelay/NOTICE.md.
delayThe division table, tempo sync, control smoothing, the crossfading two-head PITCH shifter, the Freeze (Play pad) and Reverse (Rev pad) gestures, and the Stereo / DoubleMono / Ping-pong topologies are identical to delay — refer there for those mechanics. Two delay lines (deck A → left, deck B → right) live in borrowed SDRAM (~6 s each). Per sample the path splits into read_color() then write_out() so ping-pong can cross the two taps' feedback and so the stereo diffuser can run on the feedback pair between the read and the write.
_Generated from docs/diagrams/controls/qdelay.json via make diagrams._
| Control | ParamId / config | Function |
|---|---|---|
| SIZE | Size | musical division (stepped; also sizes the Diffuse smear) |
| POS | Pos | feedback (capped ·0.95) |
| SOS | Mix | wet/dry mix |
| PITCH | Speed | transpose the heard wet (±1 octave, centre = unity) |
| ENV | Env | feedback tone — one-pole low-pass in the loop: up = open, down = darker repeats |
| MODFREQ | set_mod_speed | mod-LFO rate (~0.05 .. 12 Hz) — chorus/flange/vibrato with MOD_AMT |
| MOD_AMT | ModAmp | mod-LFO depth — modulates the delay time 0 .. ~12 ms |
| Play pad | on_play_pad | Freeze (per deck): loop the buffer at unity feedback |
| Rev pad | on_play_pad (reverse) | Reverse (per deck): read the buffer backwards over a delay-length window |
| Reel/Slice/Drift switch | ConfigId::Mode (per deck) | character: Clean / Diffuse / Duck |
| Route switch | ConfigId::Route | topology: Stereo / DoubleMono / Ping-pong |
Knob meanings are fixed across characters — the mode only changes the feedback-path treatment.
ConfigId::Mode, per deck; ring tint blue / teal / amber)src/dsp/diffuser.h, a JUCE-free port of qdelay's Diffusor/TARON MiniVerb). Each repeat is smeared a little more than the last, so the tail thickens into a dense, reverb-like dub wash. The diffuser is a single stereo instance over the two taps' feedback; each deck takes the diffused copy only if it is in Diffuse, so DoubleMono can run a Diffuse deck alongside a Clean/Duck deck. SIZE sets the smear depth (longer division = looser, more spread-out smear). Its buffers (~235 KB at 48 kHz) sub-allocate from the SDRAM arena, so SRAM is unaffected.ConfigId::Route)Identical to delay: DoubleMono (two independent mono delays), Stereo (linked to deck A's controls), Ping-pong (linked + cross-feedback, echoes bounce L↔R). In Diffuse/Duck the per-deck colored feedback is what crosses in ping-pong.
capabilities() = CapOwnDisplay | CapDualDeck; route() reports the topology for the route LED.host/test_qdelay.cpp (make -C host test-qdelay) and the standalone diffuser test host/test_diffuser.cpp (make -C host test-diffuser).make engine-qdelay # clean build + DFU flash
make -j8 ENGINE=qdelay # compile only