Modules
Every module of shuffle_engine, what it is for, what it depends on, and which
ports connect it to a backend. A module’s own page (core/<name>/README.md)
has its API, threading rules and decisions; this page is the map.
Some modules live in a satellite repository: the JUCE and Tracktion adapters
in shuffle_juce, ai_tasks, the audio.cpp adapter and the AI specs in
shuffle_ai, education and research in shuffle_edu. Their rows say so and
link there; satellites.md lists every satellite.
Status legend: planned (no spec yet) · spec (behavioural spec written
and reviewed) · implementing · done (core implemented, tests passing) · adapted (adapters for today’s backends exist).
Dependency graph
Section titled “Dependency graph”Cores only; arrows mean “depends on”. Adapters and UI depend on the cores they serve and are not drawn.
flowchart BT
base[base]
commands[commands] --> base & time
time[time] --> base
netaudio[netaudio] --> time
redundancy[redundancy] --> time
timecode[timecode] --> base & time & commands
midi[midi] --> base & time & commands
tuning[tuning] --> base
harmony[harmony] --> base
tempo[tempo] --> base
lyrics[lyrics] --> base
routing[routing] --> midi & commands & loudness & redundancy
setlist[setlist] --> time & commands & timecode & cues
cues[cues] --> base & time & commands
osc[osc] --> base
loudness[loudness] --> time & commands
resample[resample] --> base
dsp[dsp] --> base & resample
synth[synth] --> midi & dsp & commands
engine[engine] --> routing & setlist & cues & synth & loudness
showcontrol[showcontrol] --> midi & timecode & setlist & osc & cues
voiceover[voiceover] --> setlist & ai_tasks
ai_tasks["ai_tasks (shuffle_ai)"] --> midi & commands
events[events] --> setlist
sync[sync] --> engine & setlist & commands
looper[looper] --> engine & setlist & commands
video[video] --> setlist
documents[documents] --> base
lighting[lighting] --> showcontrol
remote[remote] --> setlist
hwcontrol[hwcontrol] --> midi
assistant[assistant] --> setlist & showcontrol
package[package] --> setlist
ui_model[ui_model] --> base
ui_theme[ui_theme] --> ui_model
ui_layout[ui_layout] --> ui_theme
ui_render[ui_render] --> base
The graph is a design target: each module’s DEPENDS file is the truth, and
tools/check_repo.py holds the code to it.
Core modules
Section titled “Core modules”| Module | Purpose | Depends on | Ports it declares or uses | Status |
|---|---|---|---|---|
| base | Shared vocabulary (MIDI bytes, results, lock-free queue) and the platform and I/O ports used by many domains | — | TaskQueue, TimerService, WorkerPool, Clock, FileStore, SettingsStore, Logger, FeatureGate, OutputStage, MidiOutputPort, MidiOutputDirectory, MidiInputSource, AudioOutputTopology |
done (OutputStageHost, DeviceEvents, TransportEvents, MidiInputDirectory, InstrumentChains also in) — README |
| commands | Every user action as a command: descriptors, validation, preview, apply/undo, plans, name resolution, state snapshots, generated JSON Schemas / tool lists / GBNF grammars, profiles for people, remotes, small and large models, safety and confirmation; GO protection, show mode, inhibit switch registry, access levels and clients, collaborative editing with per-author undo, duplicate filtering of network input | base, time | LanguageModel (used by the AI adapters, not by the core), CommandTarget, RecordingSink |
done (CMD-R1..R78) — spec, README, 185 tests |
| time | Units as types (samples, flicks, seconds, musical ticks, bars|beats|ticks), positions and durations, time and musical ranges, tempo maps with time and key signatures, map inserts and deletes, tempo-edit re-placing, arrangements and section anchors that follow the music, quantised boundaries and jump plans, launch grids, the musical count, absolute TAI time, media clock mapping, start at a shared instant | base | Clock |
done — spec, README, 99 tests |
| timecode | SMPTE time arithmetic at eleven rates; MTC and LTC generation as free-running streams to named endpoints; slot sharing, cue conflicts, live monitor model; LTC decoding and MTC receive with lock, freewheel, jumps and a smoothed position; chase rules for followers; command table | base, time, commands | OutputStage, MidiEndpointTopology, AudioOutputTopology, AudioInputTopology, Clock, FeatureGate |
done — spec, README, 243 tests |
| sync | Open tempo/beat/phase sync protocol: masterless sessions, deterministic merge, quantum phase alignment, NTP-style clock estimation or PTP time directly (sample-aligned on wired PTP networks), links over UDP, BLE, USB/serial, WebSocket relay, MIDI clock bridge, authenticated sessions, optional Ableton Link bridge. Implemented: the MIDI clock output (pulses from the tempo map with ramps, clock while stopped, Start, Continue, Stop and Song Position Pointer, latency through the device timing, timed or block delivery), its engine node and sync.* commands |
base, time, setlist, engine, commands | MidiOutputPort, Clock (used); TempoSync, DatagramSocket, SecureRandom (planned) |
partially implemented — spec, README, 15 / 43 requirements (the MIDI clock output, SY-R29 to SY-R43), 30 tests |
| netaudio | AES67 / RAVENNA / ST 2110-30 audio over IP, PTP follower, SDP, SAP and mDNS/RTSP discovery, jitter buffering, RTP-MIDI, NMOS later | time | DatagramSocket, NetworkInterfaces, StreamSocket, Clock |
done — spec, README, 334 tests; ASRC, IPv6, NMOS later |
| redundancy | Stream health, ASRC, crossfade failover, flush and priming, synchronous start, command distribution for redundant rigs and stage boxes | time | DatagramSocket, Clock, OutputStage |
done — spec, README, 134 tests; open issues RD-OI1..7 |
| resample | Shared real-time resampler (64-tap Kaiser-windowed sinc, ratio changeable every block, bit-exact at ratio 1, ~134 dB S/(N+D)) | base | — | done — README, 11 tests |
| midi | Note-range gating that never cuts held notes, MIDI panic, trigger matching, MIDI-learn arbitration, binding persistence, MIDI Show Control receive, byte-stream parsing, RPN/NRPN, controller chase, UMP and MIDI 1.0/2.0 translation, sample-accurate sequence playback | base, time, commands | MidiInputSource, MidiInputDirectory, MidiOutputPort, MidiOutputDirectory, InstrumentChains, TaskQueue |
done — spec, README, 142 / 142 requirements, 161 tests |
| tuning | Pitch detection for instruments and a tuner model (cents, string, stability) | base | — | planned |
| harmony | Chord detection from audio/MIDI, chord symbols, notation and diagrams | base | — | planned |
| tempo | Tempo maps, click and beat analysis, tempo estimation, rhythm maps | base | TempoMap |
planned |
| lyrics | Timed lyrics, segments and placeholders, LRC/SRT reading, online lookup | base | HttpClient, FileStore |
planned |
| routing | Named audio and MIDI endpoints mapped onto physical channels and ports, surviving a change of interface; crosspoint matrices, buses, audition, monitor mixes, insert slots, output limits, live inputs with drift compensation; MIDI routes with filters, remaps, merge and hanging-note safety, feedback detection; virtual ports and devices shared with other applications | base, time, commands, loudness, midi, resample, redundancy | AudioDeviceChannels, AudioDeviceSwitch, InsertProcessor, VirtualMidiPorts, VirtualAudioDevices (declared); SettingsStore, DeviceEvents, Clock, MIDI directories (used); provides AudioOutputTopology, AudioInputTopology, MidiEndpointTopology |
done — spec, README, 171 requirements |
| setlist | The show engine: several songs loaded, the next one armed, transitions (stop, continue, segue, repeat), switch protection and performance lock, incremental loading, a live session that stays up across songs, tempo follow or lead through TempoSync, following timecode, quantised start/stop, live re-arrangement; playhead, loop range, roll-in, per-block segment flags, metronome on a named output |
base, time, commands, timecode, cues | SongSessionFactory, SongSession, Transport, MixControl, TempoSync, LiveSession, ShowStore, ConfirmationHandler (declared); Clock, AudioOutputTopology, OutputStage (used); provides cues::MusicPosition (ShowMusic) |
done — spec, README, 76 requirements, 118 tests |
| cues | Theatre cue model: pre-wait/action/post-wait, continue rules, playhead and GO, group modes (timeline, playlist, first, random), retrigger and press/release rules, fades of any parameter with curves (logarithmic included) computed per audio block, ducks and stop-others, panic/pause/reset across domains, wall-clock triggers, load to time and start from a position, preview and auditions, control cues, cue health and lint, safe opening, key and timecode bindings, grids with scenes and follow actions, quantised launch on the musical count, bulk edit, find, performance reports; resolves to a deterministic schedule | base, time, commands | CueTarget, CueParameters, MusicPosition (declared; setlist provides it), CivilTime (declared); Clock (used) |
done — spec, README, 171 of 175 requirements done (4 delegated), 198 tests, show control |
| showcontrol | Action matrix of MIDI (MSC send included), OSC, UDP/TCP, timecode and internal actions, message templates, value curves with modes and their own timing, MIDI file playback, MIDI learn, persistence tolerant of old and corrupt files | midi, timecode, setlist, osc, cues (with base, time, commands) | TimelineEvents, HostResolver, TimecodeActions, CommandRunner (declared); OscEndpoint, MidiEndpointTopology, MidiOutputPort, DatagramSocket, StreamSocket, FeatureGate, FileStore, Clock (used) |
done, 145 / 145 requirements, 146 tests — README, spec |
| voiceover | Spoken cues: count-ins, section announcements, user messages, cue library, baking into the timeline | setlist, ai_tasks | SpeechSource (declared in ai_tasks), Recorder, TimelineEvents |
planned |
| events | Timeline events dispatched on the audio thread as the playhead crosses them | setlist | TimelineEvents |
planned |
| looper | Live loops at engine level: an always-on input history and retroactive capture of the last bars, beats or seconds; record, overdub, replace, multiply with one level of undo in bounded memory; reverse, half and double speed; quantised, sample-accurate actions; volumes, mute groups, scenes, fades; device class presets; its engine node and looper.* commands |
base, time, setlist, engine, commands | — | done — spec, README, 48 / 48 requirements, 49 tests |
| video | Video clips in sync with the transport, transforms, text clips, transcode cache | setlist | VideoDecoder, ImageSink, Transport |
planned |
| documents | Score and lyric pages shown in sync with the song | base | DocumentRenderer, ImageSink |
planned |
| lighting | DMX over Art-Net and USB interfaces, fixtures, scenes driven by cues | showcontrol | DatagramSocket, SerialPort |
planned |
| remote | Discovery of devices on the network and remote control/monitoring of a show | setlist | DatagramSocket, MessageServer |
planned |
| hwcontrol | Control of external hardware (multi-effects, loopers, digital mixers) through device profiles | midi | MidiOutputPort, SerialPort, MessageServer |
planned |
| assistant | Show assistant built on llm: personas and tools for preparing and running a show |
llm, setlist, showcontrol | — | planned |
| package | Export and import of a show with its media, conflict-free copy planning | setlist | FileStore |
planned |
| resilience | Not a library: the rules every module follows (declared fallbacks per dependency, health reporting) and the fault-injecting fakes and show-goes-on test suite | base | all ports report health | spec — spec |
| compose | Algorithmic composition: pitch systems and tunings, rhythm (Euclidean, polymeter, rhythm trees), stochastic and Markov methods, L-systems and automata, constraint harmony, species counterpoint, spectral tools, transformations; seedable and explainable | time, harmony | — | planned — shuffle_edu |
| spectral | FFT analysis, partial tracking, spectral envelopes, frequency/midicent conversions for analysis and composition | base | — | planned |
| spatial | Ambisonics encode/decode, binaural from SOFA (AES69) files, loudspeaker layouts, trajectories, ADM-OSC | time | OscEndpoint |
planned |
| inference | Generic model runtime: tensors, runtimes (ONNX Runtime, TF Lite, llama.cpp) with GPU and CPU fallback, manifests with licences and checksums, model store with consent and commercial-build exclusion, ensembles, windowed inference, offline jobs and a real-time mode with admission check | base | InferenceRuntime, ModelFetcher, NeuralProcessor |
spec, in shuffle_ai — spec, 68 requirements |
| neural | Neural music analysis on inference: spectrogram and CQT features, separation, beats/downbeats/metre (DBN), sections, chords (HMM), pipelines, results as tempo-map and arrangement proposals applied through commands |
inference, time, commands | AudioDecoder |
spec, in shuffle_ai — spec, 57 requirements |
| llm | Generic language models: chat templates, context and KV-cache management, sampling, grammar and JSON-schema constrained output, hosted backends (OpenAI-compatible, Anthropic) with secret store, agentic loop over the command catalogue, MCP client and server, token and cost accounting, personas and prompt templates | inference, commands | LanguageModel, SecretStore, HttpClient, ProcessLauncher, HttpListener |
spec, in shuffle_ai — spec, 127 requirements |
| ai_tasks | Finished AI audio tasks as ports: speech synthesis for spoken cues, speech recognition with timestamps and voice-activity detection, stem separation aligned with the mix, audio to MIDI notes; worker-thread calls with stop token, progress and fixing errors; model manifests (files, SHA-256, licence, commercial use, consent), licence policy and consent as settings; SHA-256; fakes and contract suites | base, time, commands, midi | SpeechSource, SpeechToText, StemSeparator, AudioToMidi (declared); SettingsStore (used) |
done, in shuffle_ai — spec, README, 20 requirements, 32 tests; on audio.cpp in adapters/audiocpp |
| mir | Classic music information retrieval from the literature: onsets, tempo, beats (Ellis, Davies & Plumbley, Degara, multi-feature), downbeats and click detection, chroma/HPCP, key (published profiles), chords, structure (Foote), streaming variants, evaluation harness with mir_eval/MIREX metrics | time, resample | — | spec, in shuffle_ai — spec, 93 requirements |
| notation | MusicXML, MEI, abc and SDIF reading and writing; harmony and counterpoint analysis with explanations | harmony, time | FileStore |
planned |
| dsp | Real-time DSP building blocks: smoothing, varispeed interpolators, filters (biquad, TPT SVF), band-limited oscillators and wavetables, seeded noise, LFOs, ADSR, delays, latency-aligned dry/wet, dynamics, EQ, FDN reverb, distortion with oversampling, FFT, partitioned convolution | base, resample | FourierTransform (optional; declared, with the core implementation as default) |
implemented — spec, README, 140 / 141 requirements (DS-R16 is an adapter requirement), 172 tests |
| synth | Voices, polyphony and stealing with fade reserve, mono/legato/portamento, pedals, MPE zones and per-note expression (receive and send), MIDI 2.0 per-note control, tuning tables and Scala files, sample-accurate rendering, modulation matrix, sampler, wavetable, presets | base, time, commands, midi, dsp | FileStore |
partially implemented — spec, README, 102 / 103 requirements (SN-R97: a change of sound source needs a new instrument), 118 tests |
| engine | Own audio graph: typed pins, buses, sends, delay-node feedback; validation; program compile and atomic swap with state carry-over and edge ramps; deterministic order; latency compensation with render lead and monitoring; sub-block splitting; single-threaded and work-stealing parallel scheduling, bit-identical; overload ladder and isolated plugin nodes; audio and MIDI item playback with stretch and tempo following; plugin boundary; aligned recording; offline render identical to real time; taps and the output stage host; implements the engine ports of setlist, cues, routing and base | base, time, commands, midi, dsp, loudness, routing, cues, setlist, synth | ProcessingThreads, TimeStretcher, PluginHost, MediaReader, AudioWriters, SongReader (declared); Clock, TaskQueue, WorkerPool, InsertProcessor (used); Transport, SongSessionFactory, SongSession, LiveSession, MixControl, CueTarget, CueParameters, OutputStageHost, InstrumentChains (implemented) |
partially implemented — spec, README, 129 / 156 requirements in full, 26 in part, 109 tests |
| edit | Non-destructive arrangement editing, every edit a command: tracks, items, takes and comping, fades and crossfades, gain, normalise, reverse, rate, stretch and warp, MIDI note editing, quantise and groove, markers and sections, time insert/delete coordinated with followers in other domains, playback form handed to the engine | time, commands, engine, formats, loudness | MediaJobs |
spec — spec, 89 requirements |
| automation | Parameter automation curves, recording modes, anchored to musical time | time, commands | — | planned |
| render | Offline bounce and export: stems, mixdown, formats, dithering, deterministic | engine, loudness | FileStore |
planned |
| loudness | BS.1770 / EBU R128 loudness, loudness range, true peak, PPM/VU/peak meters, stereo field, delay and polarity, file QC, normalisation targets | time, commands | — | done — spec, README, 73 / 73 requirements, 96 tests |
| osc | OSC 1.0/1.1 wire format: strict encoding and decoding, bundles and time tags, address patterns, scheduled dispatch, UDP and TCP framing, OscEndpoint |
base | DatagramSocket, StreamSocket, Clock |
done — spec, README, 78 tests |
| formats | Audio file formats from the public standards: WAV/BWF/RF64, AIFF, CAF, FLAC, Ogg Vorbis/Opus, MP3, MP4/M4A (AAC, ALAC, fragmented), ADTS, SMF; exact encoder delay and padding, sample-accurate seeking, metadata read/write with unknown items preserved, writers with dither and RF64 promotion, memory-mapped PCM; codecs through permissive libraries or platform codecs | base, time, timecode | AudioDecoder, AudioEncoder, PacketDecoder, PacketEncoder, CodecProvider, ByteSource, ByteSink, FileStore |
partially implemented — spec, README, 120 / 129 requirements in full, 9 in part, 390 tests; codecs in adapters/codecs |
| library | Audio metadata (ID3, Vorbis, MP4, BWF), playlists, gapless playback, search | base | FileStore |
planned |
| plugin | Plugins from shuffle cores: CLAP, VST3, AU, LV2 wrappers, parameters, state, host transport mapped to time |
time, dsp | plugin SDKs (permissive) | planned |
| ui_model | View models and all interaction logic, toolkit-free: time axis and zoom, shared playhead clock and follow, ruler, snapping, hit-testing per input kind, drag state machines producing one command plan per gesture, selection, keyboard and focus, layout, virtualised lists and trees, waveform level of detail, meters, mixer strips, piano roll, transport fields, overlays as data, multiple screens, accessibility tree with named roles | base, time, commands | DisplayInfo, SystemAppearance, FrameClock, SettingsStore |
interaction implemented in part — README, spec: 175 of 185 requirements, 9 in part, UM-R182 waits for ui_bridge |
| ui_theme | The look of every interface, computed: colour roles, three theme families (Deep Field, Nightjar, Monolith; Dark and Light each) and High Contrast with a WCAG contrast matrix, custom schemes and brand accents in OKLCH, categorical palette and domain token sets, type scale, spacing, densities, scaling and pixel snapping, stage readout sizing, paint recipes of component states and of the parts of sliders, faders, knobs, XY pads, meters, readouts, status pills, progress, scrollbars, tooltips and timeline marks, motion and the frame-clock animator, title-bar hit-testing, safe areas, forced colours, accessible names, ui.set_* commands, export as design tokens and CSS |
base, time, commands, ui_model | SystemAppearance, FrameClock, SettingsStore |
implemented in part — README, spec: 110 of 124 requirements in full, 13 in part (toolkit or layout half), UT-R114 waits for a toolkit adapter |
| ui_layout | The content of a panel, arranged: rows and columns with gaps, alignment, grow and shrink weights and minimum and maximum sizes, wrapping rows, simple grids (fixed, fit and flexible tracks or a column count by width), overlays, breakpoints from the spacing scale; one text-fitting rule for the whole framework (step down the type scale, wrap at UAX #14 opportunities, ellipsis at a word boundary, values ask for space, truncation reported); checks for overlapping and clipped text and overlapping hit targets over a grid of sizes | base, time, ui_model, ui_theme | TextMeasurer (declared; fake and contract suite) |
done — README, spec: 53 of 53 requirements; DirectWrite measurer shuffle_text_dwrite; example ui_layout/control_surface |
| ui_bridge | Bridge between the command catalogue and any UI: protocol with handshake and versions, topics (snapshot then JSON Merge Patch deltas), events, backpressure, embedded webview / WebSocket / WebAssembly transports, generated TypeScript client, real-time data frames, theme as CSS, accessibility, security | base, time, commands | BridgeChannel, TopicSource, StreamSource, WebUiHost (declared); Clock, TaskQueue |
implemented in part — README, spec: 94 of 112 requirements in full, 10 in part; protocol, calls, topics and deltas, events, flow control, streams, version 0, in-process transport, webview security decisions, theme topic, generated client; the WebSocket transport in shuffle_net_websocket (no TLS); not yet the WebAssembly binding, shared-memory streams, binary reads; JUCE WebUiHost in shuffle_juce_webui (shuffle_juce); guide |
| ui_render | What a native screen draws, as plain data: the draw list (closed op kinds with conservative bounds, arenas, groups with content keys and group copying, validation, text and binary forms), damage merged into at most 8 pixel rectangles with the buffer-age history, the resource table, the geometry and antialiasing every renderer shares (outlines, coverage), a CPU reference rasteriser, the reference scenes and the 214-widget control surface of the conformance and performance runs | base | Renderer2D (declared; fake and contract suite) |
implemented — README, spec UW-R128 to UW-R158, UW-R179 to UW-R183; Direct2D renderer shuffle_render_d2d; example ui_render/surface |
| ui_widgets | Native widgets as pure C++: a catalogue for music applications (buttons, toggles, segmented controls, faders, sliders, knobs, meters, readouts, XY pads, virtualised lists and tables, tabs, menus, non-modal dialogs, text fields, timeline, waveforms, status pills, toolbars) drawn from ui_model view models, ui_layout rectangles and ui_theme recipes into a plain-data draw list with damage regions; screens as data; accessibility, text fitting, scale and motion; the Renderer2D and PlatformWindow ports, a CPU reference rasteriser and renderer conformance scenes |
base (ui_render); base, time, commands, ui_model, ui_theme, ui_layout, ui_render (ui_widgets) | PlatformWindow, RequestSink (declared; fakes, test driver and contract suite); Renderer2D, TextMeasurer, FrameClock (used) |
implemented (experimental) — README, spec; Win32 window shuffle_window_win32; example ui_widgets/control_surface |
Adapter modules
Section titled “Adapter modules”Plain C++20 libraries where the backend is the operating system itself
(adapters/net/, adapters/platform/), a set of permissive libraries
(adapters/codecs/, adapters/miniaudio/, adapters/libremidi/) or the
plugin formats themselves (adapters/plugin_host/). The JUCE modules (one per
backend area) and the Tracktion modules live in
shuffle_juce, the audio.cpp
adapter in shuffle_ai; their
rows link there. Each adapter implements ports and passes their contract
tests.
| Module | Backend | Implements | Status |
|---|---|---|---|
shuffle_juce_platform |
JUCE 9 | TaskQueue, WorkerPool, Clock (local only), FileStore (atomic writes), SettingsStore (properties file saved on a worker); ControlTimer for the host’s control timer (no TimerService port yet); Logger waits for a port |
adapted, in shuffle_juce — README, example juce/platform |
shuffle_juce_midi |
JUCE 9 | MidiOutputPort (real-time sendNow; sendAt sends at once; no UMP), MidiOutputDirectory, MidiInputSource (MIDI 1.0 bytes, real-time or control subscriptions), MidiInputDirectory, DeviceEvents for MIDI rescans (without Tracktion) |
adapted, in shuffle_juce — README |
shuffle_juce_audio |
JUCE 9 | AudioDeviceChannels, AudioDeviceSwitch (asynchronous, through TaskQueue) and DeviceEvents on JUCE’s audio drivers (keys "<driver type>:<device name>", no MIDI opened); the device callback that runs the engine’s process entry with flush-to-zero (DS-R16), device inputs to the engine and routing, xruns to the overload monitor, output stages after the graph; ProcessingThreads on real-time JUCE threads joined to the device’s audio workgroup (without Tracktion) |
adapted, in shuffle_juce — README, example juce/play |
shuffle_juce_plugins |
JUCE 9 | PluginHost (VST3, AU, LV2; scan on a worker with a crash list, known plugins kept in the SettingsStore, asynchronous instantiation and state), PluginInstance (MIDI, parameters and transport per call, latency), InsertProcessor backed by a hosted plugin; no audio device needed |
adapted, in shuffle_juce — README, example juce/plugins |
shuffle_juce_net |
JUCE 9 | DatagramSocket, OscEndpoint, HttpClient |
planned, in shuffle_juce |
shuffle_te_devices |
Tracktion | OutputStage host (global output hook), AudioDeviceChannels and AudioDeviceSwitch (the topologies come from routing on them), DeviceEvents; MIDI devices through shuffle_juce_midi |
adapted, in shuffle_juce — README |
shuffle_te_engine |
Tracktion | SongSessionFactory, SongSession, Transport (rate 1; in-block discontinuities rendered from the next block), TimelineEvents per song, MixControl (song gain), LiveSession, audio CueTarget and its CueParameters, AudioWriters; not yet TempoMap as a port, Recorder, AudioFileProbe (no port yet) |
partially adapted, in shuffle_juce — README |
shuffle_te_plugins |
Tracktion | PluginHost |
planned, in shuffle_juce |
shuffle_ai_mcp |
any | exposes commands and snapshots over the Model Context Protocol | planned |
shuffle_proto_oscquery |
any | OSC + OSCQuery surface generated from commands | planned |
shuffle_pd |
libpd (BSD-3) | Pure Data patches running inside an application, as processors and control logic | planned |
shuffle_max_externals, shuffle_pd_externals |
Max SDK / min-api (MIT), Pd (BSD-3) | shuffle objects (time, compose, commands) inside Max and Pd | planned |
shuffle_faust |
Faust-generated C++ | DSP written in Faust as processors | planned |
shuffle_neural_onnx, shuffle_neural_torch |
ONNX Runtime (MIT), libtorch (BSD-3) | NeuralProcessor |
planned |
shuffle_proto_web |
any | HTTP + WebSocket surface generated from commands | planned |
shuffle_proto_companion |
any | Bitfocus Companion module generated from commands | planned |
shuffle_codecs |
libFLAC, libvorbis/libogg, libopus, dr_mp3 (permissive; no JUCE) | CodecProvider, PacketDecoder, PacketEncoder (OpenCodecs: FLAC, Vorbis, Opus read and write, Opus from any input rate, MP3 read; AAC and ALAC left to platform codecs); checkFlacMd5 |
adapted — README, 32 tests, example formats/transcode |
shuffle_miniaudio |
miniaudio (Unlicense / MIT-0; no JUCE) | AudioDeviceChannels, AudioDeviceSwitch (asynchronous, through TaskQueue, the previous device reopened on failure) and DeviceEvents (polled list, device notifications) on miniaudio’s backends (keys "<backend>:<device name>"); the device callback that runs the engine’s process entry with flush-to-zero (DS-R16), device inputs to the engine and routing, output stages after the graph, the device’s latencies with every block (EN-R158), no allocation; ProcessingThreads on OS real-time threads (MMCSS, QoS, SCHED_FIFO) |
adapted — README, 24 tests, example miniaudio/play |
shuffle_webaudio |
the browser’s Web Audio API (WebAssembly only; no library) | the engine’s process entry inside an AudioWorkletProcessor (WebAudioOutput: one Engine::process per render quantum, the context’s output timestamps filtered into the device’s media clock mapping and baseLatency + outputLatency as its output latency with every block, EN-R157, EN-R158), Clock (WebClock), TaskQueue and WorkerPool for a one-thread module (WebTasks); the worklet script and the page’s side in JavaScript; no SharedArrayBuffer, so no COOP/COEP |
adapted — README, 17 tests and a worklet test under Node.js; used by Score Sync Lite (shuffle_showcase) |
shuffle_libremidi |
libremidi (BSD-2-Clause; no JUCE) | MidiOutputDirectory, MidiInputDirectory (names, driver type, persistent unique id, protocol, groups), DeviceEvents (hotplug through TaskQueue), MidiOutputPort (real-time sendNow and sendUmp through a preallocated queue and a sender thread; true UMP output on Windows MIDI Services, CoreMIDI UMP and ALSA UMP), MidiInputSource (raw MIDI 1.0 bytes or whole UMP packets, Clock timestamps, real-time or control subscriptions); WinMM, CoreMIDI, ALSA, Android AMidi, Web MIDI for MIDI 1.0 |
adapted — README, 31 tests, example libremidi/ports |
shuffle_plugin_host |
the plugin formats themselves: CLAP and VST3 interface headers (MIT), lilv (ISC) for LV2, AudioToolbox for AU; no JUCE | PluginHost (NativePluginHost: one worker job scans every format with a crash-safe skip list in the FileStore, known plugins in the SettingsStore, code loaded on a worker and instances created on the control thread, state on the control thread, names resolved with ambiguity reported), PluginInstance (CLAP, VST3, LV2, AU: sample-accurate parameters, MIDI in and out, transport, latency, tail, own bypass, state; parameter values readable without a lock), InsertProcessor (PluginInsert, a placeholder when the plugin cannot run) |
adapted — README, 30 tests (36 with LV2), example plugin_host/list; editors planned |
shuffle_text_dwrite |
DirectWrite (Windows SDK; no JUCE) | TextMeasurer (DWriteTextMeasurer: ui_theme’s families with fallbacks to installed faces, natural advances, tabular figures measured as the widest digit, optional DirectWrite line-break analysis) |
adapted — README, 4 tests, example ui_layout/control_surface |
shuffle_render_d2d |
Direct2D 1.1, Direct3D 11, DXGI, DirectWrite (Windows SDK; no JUCE) | Renderer2D (D2dRenderer: window targets on a host HWND with a flip-model swap chain, buffer-age partial redraw, dirty-rectangle presentation and frame pacing; offscreen targets with read-back; device-loss recovery from the resource table; WARP fallback; shapes as the core’s shaded coverage, text in the fonts of shuffle_text_dwrite) |
adapted — README, 6 tests, example ui_render/surface |
shuffle_platform |
C++20 standard library + OS (Win32, CoreFoundation/CoreGraphics, POSIX, gsettings; no JUCE) | TaskQueue (ControlLoop: run on the caller’s thread or one of its own, timers with handles, quit, no nested loops), WorkerPool (ThreadWorkerPool), Clock (SteadyClock, local only), FileStore (OsFileStore: atomic writes and replaces, path safety), SettingsStore (JsonSettingsStore: one JSON file saved on a worker, coalesced), SystemAppearance and DisplayInfo (Windows, macOS; declared unavailable elsewhere); ControlTimer for the host’s control timer; FrameClock left to the UI backend |
adapted — README, 60 tests, example platform/settings |
shuffle_net_sockets |
OS sockets (Winsock 2, BSD sockets; no JUCE) | DatagramSocket (unicast, multicast, broadcast, DSCP, kernel receive timestamps), StreamSocket, NetworkInterfaces (timestamping capability, change polling), Clock (SteadyClock) |
adapted — README, 22 tests, example net/osc_udp |
shuffle_ai_audiocpp |
audio.cpp (Apache-2.0) on ggml (MIT); no JUCE; desktop only, off by default | SpeechSource, SpeechToText (voice-activity detection through a VAD model), StemSeparator, AudioToMidi; AudioCppModels: catalogue of local model folders, files checked by SHA-256, licence policy and consent, load on demand, unload, memory limit; rate and channel conversion to the model’s; no network |
adapted, in shuffle_ai — README, example ai/spoken_cue |
shuffle_ai_llm |
llama.cpp / ONNX, hosted APIs | LanguageModel, with grammar-constrained decoding for local models |
planned |
UI modules
Section titled “UI modules”The UI is split in two halves (see architecture.md):
core/ui_model: everything a widget computes, as pure C++ with tests.ui/juce/shuffle_ui_*: everything a widget draws, plus forwarding of input events. Replacing the toolkit means rewriting only this half.
Each UI module gets a spec like any other domain.
What goes into core/ui_model
Section titled “What goes into core/ui_model”| Area | Pure logic (tested, toolkit-free) |
|---|---|
| timeline view state | visible range per editor with invariants (end after start, repair of corrupt saved ranges), time/beat to pixel mapping, zoom around a point with a minimum span, pixel-quantised panning so grid, clips and waveforms move rigidly |
| follow modes | scroll vs page following of the playhead, dead zone, automatic switch to page mode for very short windows, centre pinning that avoids a saw-tooth playhead |
| playback clock for the UI | one smoothed, monotonic position per transport, predicted between engine updates, shared by every widget so they never beat against each other |
| snapping | grid levels, triplets, “smart” grid level chosen from the zoom, snap points of a dragged item (start, centre, end) |
| ruler ticks | which bars, beats and subdivisions to draw at a zoom level, with a cache keyed on the tempo map |
| waveform rendering plan | which peak columns to draw for a rectangle, a quantised cache key that keeps scrolling stable, when to switch to sample-accurate drawing |
| gestures | drag, resize and stretch state machines for timeline items; one gesture equals one undo transaction |
| lists | diffing a model list into rows, row recycling, chunked creation with cancellation, insert positions for drag and drop |
| layout | data-driven split and stack layouts with min/preferred/max sizes, card waterfall allocation, settings row metrics, word-wrap geometry for karaoke lyrics, chord grid and chord timeline layout |
| multi-screen | assignment of outputs (video, lyrics, documents, chords) to displays, one output per display |
| media transforms | position/scale of a video layer with snapping to edges, centre and thirds, aspect-locked resizing |
| theme | tokens by role (surfaces, ink, accent, semantic states, meters, playhead), schemes, extra token sets contributed by domains (song-part kinds, track kinds), live re-theming without rebuilding the layout |
UI modules (rendering)
Section titled “UI modules (rendering)”These are areas, not sixteen libraries to create up front. UI code starts in a few modules and an area becomes its own module only when its size or its dependencies make that worthwhile.
Superseded by
ui_widgets. The native widget toolkit is now specified as pure C++ cores,ui_widgetsandui_render(spec): widgets draw into a draw list that aRenderer2Dadapter paints (Direct2D first), so these areas become kinds and compositions of its catalogue instead of per-toolkit modules, and the toolkit half ofui_themebecomes the renderer and window adapters with their conformance runs (UW-R190). JUCE adapters of the two ports, for JUCE applications and plugin editors, belong in shuffle_juce. The table below remains as the map of areas to cover.
| Module | Widgets | Draws view models from | Status |
|---|---|---|---|
shuffle_ui_base |
buttons (icon, animated, toggle pills), search field, separators, colour picker, rename field, containers, drawers, headers, toolbars, frame clock that drives all animated widgets from one timer | ui_model | planned |
shuffle_ui_overlays |
confirm card on a dimmed backdrop (also a “repeat to confirm” pass-through mode), progress overlay, call-out pickers, bubble messages, insert-point highlight; never a modal loop | ui_model | planned |
shuffle_ui_theme |
mapping of theme tokens onto the toolkit, base look-and-feel, button roles and variants, meter drawing, the adapter contract tests (UT-R114) | ui_model, ui_theme | planned |
shuffle_ui_layout |
split/stack/tab layouts built from a description (the content of each panel arranged by core/ui_layout), docking and floating windows, collapsible rails, multi-screen and projector windows (placed on the target display before sizing, so it adopts that display’s scaling) |
ui_model | planned |
shuffle_ui_lists |
model-driven lists and trees, recycled rows, drag and drop containers and targets, grid-snapped drag images | ui_model | planned |
shuffle_ui_timeline |
timeline viewport (zoom, pan, pinch, wheel), ruler and beat grid, playhead and cursors with dirty-strip repaint, range-bound scrollbars, timeline item base with snapping | ui_model, tempo | planned |
shuffle_ui_waveform |
waveform columns from a peak source, overview strip, waveform with trim handles, render-progress badge | ui_model | planned |
shuffle_ui_lanes |
marker and section lanes (with live tap-in of sections while playing), tempo and time-signature lane, song-parts strip, cue/event strip | ui_model, tempo, setlist, showcontrol | planned |
shuffle_ui_arrangement |
track lanes, clip shells (select, move across lanes, stretch, context actions), audio/MIDI/chord clip views, track headers, automation curves | ui_model, setlist | planned |
shuffle_ui_midi |
piano roll drawn as painted rows, keyboard with fine zoom, note drag and stretch, velocity and controller lanes, step editor | ui_model | planned |
shuffle_ui_mixer |
level meters (peak hold, audio and MIDI), faders and pan, mute/solo/arm/monitor, sends, channel strips, strip lists, I/O matrix | ui_model, routing, setlist | planned |
shuffle_ui_transport |
transport buttons, position/tempo/time-signature fields, tap tempo, loop and punch, CPU indicator, timecode monitor, compact live overview bar | ui_model, timecode, tempo | planned |
shuffle_ui_rack |
parameter knob with MIDI-learn overlay (one shared control, not one per editor), parameter list, preset bar, processing-graph editor (nodes, pins, wires) | ui_model | planned |
shuffle_ui_stage |
setlist in tile/rich/compact variants, song and dashboard cards, empty states, lyrics projector, chord diagrams (fretboard and keyboard) and chord grid, cue matrix, tuner (strobe, headstock), loop wheel | setlist, showcontrol, lyrics, harmony, tuning, looper | planned |
shuffle_ui_media |
video view and compositor preview, filmstrip, video transform overlay, document page preview | ui_model, video, documents | planned |
shuffle_ui_settings |
settings row kit, steppers, colour swatches, shortcut editor, audio device and I/O pages | ui_model, routing | planned |
flowchart BT
base[ui_base] --> theme[ui_theme]
overlays[ui_overlays] --> base
layout[ui_layout] --> base
lists[ui_lists] --> base
timeline[ui_timeline] --> lists
waveform[ui_waveform] --> timeline
lanes[ui_lanes] --> timeline
midi[ui_midi] --> timeline
arrangement[ui_arrangement] --> waveform & lanes
mixer[ui_mixer] --> lists
transport[ui_transport] --> base
rack[ui_rack] --> lists
settings[ui_settings] --> lists & layout
stage[ui_stage] --> lists & layout
media[ui_media] --> timeline & layout
Rules for every UI module:
- widgets get colours from the theme they are given, never from a global;
- a widget listens to the model object it was built for, never to “whatever is focused now”, and stops listening before that object can go away;
- one frame clock drives every moving widget; repaint only the strip that changed;
- render caches use quantised keys so scrolling does not invalidate them;
- per-module colour schemes passed by value are the pattern to follow.
Stability at 0.1.0
Section titled “Stability at 0.1.0”Decision 0020:
a stable module breaks only in a minor version and keeps a cheap
forwarding alias for one minor version; an experimental module may change
in any minor version, with a changelog entry and no deprecation period.
Every adapter (adapters/*) and every satellite module is experimental.
| Module | Stability |
|---|---|
base |
stable |
time |
stable |
timecode |
stable |
commands |
stable |
midi |
stable |
dsp |
stable |
osc |
experimental |
resample |
experimental |
loudness |
experimental |
routing |
experimental |
setlist |
experimental |
cues |
experimental |
showcontrol |
experimental |
netaudio |
experimental |
redundancy |
experimental |
synth |
experimental |
formats |
experimental |
engine |
experimental |
sync |
experimental |
looper |
experimental |
ui_model |
experimental |
ui_theme |
experimental |
ui_layout |
experimental |
ui_render |
experimental |
ui_bridge |
experimental |
Per-module summary format
Section titled “Per-module summary format”Each core/<name>/README.md starts with this block, so every module page reads
the same way:
Purpose one sentenceLayer core | adapter (backend) | ui (toolkit)Depends on modulesPorts declared: ... / used: ...Threads what runs whereSpec specs/<name>.md, requirement prefixStatus planned | spec | implementing | done | adaptedStability stable | experimental (decision 0020)© 2026 Umberto Sorbo. The software is licensed under the Apache License, Version 2.0, and provided “as is”, without warranties or conditions of any kind; see the disclaimer.
SHUFFLE Framework and the SHUFFLE Framework logo are trademarks of Umberto Sorbo; the licence grants no rights to them (trademarks). Other names belong to their owners. Fonts: IBM Plex Sans and JetBrains Mono, SIL Open Font License 1.1.
Contact: shuffleframework@gmail.com · Instagram @shuffleframework. Security problems: write to the same address with “Security” in the subject, not in a public issue.