Architecture overview
This page describes SushiDSP’s layering as built, verified against the tree under
include/SushiDSP/, src/, modules/ and apps/. It is not the design spec: where a claim
comes from intent rather than code, it says so and cites
docs/design/SUSHIDSP.md by section instead of restating the intent
as fact.
The four layers
apps/ host, host_asio, host_gui — own IAudioDevice, drive the rig graph
↓
modules/session/ rig_preset
↓
modules/catalog/ node_registry
↓
modules/nodes/ jcm800, tubescreamer, dd3, peavey5150, mesa_mark2c, diezel_vh4,
cabinet, room, routing, capture
↓
include+src: core/ IAudioNode, RigGraph, NodeDescriptor, BufferPool, IAudioDevice,
SpscRing — the portable graph plumbing
↓
include+src: math/ Biquad, Fft, Resampler, Oversampler, Wdf, dk/ — the DSP kernels
circuits/ FmvToneStack, GraphicEqualizer, models/, stages/ — reusable circuit blocks
device/, io/ and audio_format/ sit beside core/ at the same tier: device/ (
AsioAudioDevice, Sdl2AudioDevice) implements core/IAudioDevice.hpp; io/ (Ir.hpp,
IrLoader.hpp, WavFile.hpp, WavWriter.hpp) and audio_format/
(AsioSampleConverter.hpp, ChannelSelection.hpp) supply device- and cabinet-adjacent
utilities that products and hosts both use. None of the four sit above core/ or math/ in
the dependency order; a lower tier never includes a higher one.
log/ (Logger.hpp, Log.hpp, the sinks) is the library’s logger. It depends on the C++
standard library only, and every module and host may include it. The audio thread never calls
it; include/SushiDSP/README.md says what it does instead.
Core interfaces (include/SushiDSP/core/)
IAudioNode.hpp declares prepare()/process()/ports()/reset(), the one interface every
processing block in the tree implements — a product module, a routing node, or the graph
itself. RigGraph.hpp holds a std::vector of nodes and topologically sorts and replays them
per block; NodeDescriptor.hpp is the POD factory contract (id, name, parameters, ports,
make()) a product exposes so a host can instantiate it without knowing its concrete type.
IAudioDevice.hpp is the device seam device/AsioAudioDevice.hpp and
device/Sdl2AudioDevice.hpp implement. BufferPool.hpp, RtGraphSlot.hpp, RtSwapSlot.hpp
and SpscRing.hpp are the RT-safe plumbing underneath: block-sized buffer reuse, and the
control-thread-to-audio-thread handoff for a recompiled graph or a parameter change. This
matches the interfaces design spec §3 describes; the header contents above are what is
actually checked into include/SushiDSP/core/ today.
Math and circuit kernels (include/SushiDSP/math/, include/SushiDSP/circuits/)
math/ holds the portable numerical kernels — Biquad, Fft, Oversampler,
PartitionedConvolution, StreamingConvolution, Resampler/SincResampler, Wdf,
SmoothedParameter — and math/dk/ holds the DK-method nonlinear-circuit core:
DenseLu, DampedNewtonSolver, DkNetlist, DkCircuit<S, N, I, O>. circuits/ holds
FmvToneStack.hpp and GraphicEqualizer.hpp alongside circuits/models/ (the device laws:
SiliconDiode, Triode12AX7, PentodeEL34) and circuits/stages/. Everything in math/ and
circuits/ depends on the C++ standard library only, never on core/ — a product module pulls
kernels down from here, never the reverse.
Products (modules/)
Each of jcm800, tubescreamer, dd3, peavey5150, mesa_mark2c and diezel_vh4 is a
library that composes math/circuits kernels behind one IAudioNode implementation and
exposes exactly one NodeDescriptor. cabinet is the impulse-response convolution the
amplifiers used to carry themselves, now a node of its own. routing supplies the rig graph’s own
SplitterNode/MixerNode/PanNode as ordinary products rather than RigGraph special
cases; capture and room are DS/D-phase modules the same way. node_registry is the one
module allowed to depend on every product at once — node_registry() and make_node() are
the id-to-instance catalog every host in apps/ builds a rig from today. Adding a product
adds one entry there; the host GUI still names products by id in
apps/host_gui/ui/PanelLibrary.cpp, ui/GearFilter.cpp and TopologyApplier.cpp, which
KNOWN_ISSUES.md records. A future plugin wrapper would
draw from the same catalog (see “What is spec-only, not yet built” below), but none exists in
the tree yet. rig_preset serializes
a rig (descriptor id plus parameter values) to and from JSON. This is the dependency rule
design spec §8 states for modules/; what is verified here is that modules/catalog/node_registry/
and modules/session/rig_preset/ exist in the tree and match that description, alongside the six
product modules and cabinet/routing/capture/room under modules/nodes/.
Hosts (apps/)
apps/host is a minimal SDL2-backed standalone host; apps/host_asio is the ASIO-backed
counterpart; apps/host_gui is the full rig-editing GUI, with its own audio import, resampling
and MP3-decode support classes alongside RigController and the UI tree under
apps/host_gui/ui/. All three sit above modules/ and core/: they own an IAudioDevice,
build a RigGraph from node_registry(), and drive process() per audio callback. A VST/CLAP
plugin wrapper is design intent only — design spec §3 (“Product contract”) and §8’s apps/plugin
layout entry describe it, but no apps/plugin directory exists in the tree yet.
What is spec-only, not yet built
The following are described in docs/design/SUSHIDSP.md as intent and were not found under
include/, src/, modules/ or apps/ during this review — read them from the spec, not as
current fact:
- The VST3/CLAP plugin wrapper and its
apps/plugindirectory (design spec §3, §8). - Any packaging step beyond what
sd build/sd testalready exercise (design spec §8, “Targets & dependency rules”). - Roadmap phases beyond what the changelog records as shipped (design spec §9); check
docs/reference/CHANGELOG.mdfor what has actually landed.

