Skip to content

Architecture

Mauro Moreno edited this page Aug 30, 2026 · 2 revisions

Architecture

This chapter describes the software boundaries that keep the audio engine portable, deterministic, and reusable across hosts.

Layer model

Layer 2  hosts and UI    VST3 · CLAP · standalone · WebAssembly · ui/
                              │ events, parameters, audio buffers
Layer 1  engine          voices · allocation · smoothing · patch binding
                              │ normalized DSP settings
Layer 0  DSP             oscillators · filters · envelopes · LFOs · effects

Dependencies point downward only.

Layer Location Responsibility Exclusions
DSP src/dsp/ Sample processing and reusable signal primitives Filesystem, patches, host APIs, audio-thread allocation
Engine src/engine/ Voice lifecycle, modulation, smoothing, and stored-value mapping Windowing and host-specific protocols
Hosts hosts/, ABI bindings under src/ Audio/MIDI transport, plugin contracts, persistence, and platform integration Instrument-specific DSP decisions
Interface ui/ Panel state, user interaction, patch browser, and keyboard Direct knowledge of a specific plugin format

Audio processing lifecycle

  1. A host converts MIDI, parameter, and transport data into engine events.
  2. The engine applies parameter changes and allocates or releases note voices.
  3. Each note voice evaluates its envelopes and modulation sources.
  4. Every active unison layer renders oscillators and its own filter state.
  5. Voice outputs are panned and summed to the stereo bus.
  6. The engine processes EQ, effect, delay, and chorus in that order.
  7. The host receives the final stereo samples in its native callback format.

The audio path performs no dynamic allocation. Parameter discontinuities that would click are smoothed in the engine; categorical changes such as waveform or filter type are not interpolated.

Shared interface and bridge

The HTML interface is host-neutral. ui/bridge.js presents one control surface to the application and adapts messages to the available transport:

  • a WebView2 bridge in the VST3 and CLAP plugins;
  • the WebAssembly interface in the browser;
  • the corresponding host adapter for other embedded contexts.

This design allows the main panel, patch browser, and on-screen keyboard to reuse the same components and parameter model. A UI control sends a parameter identity and value; it does not perform DSP or interpret a plugin ABI.

Parameter boundary

Patch files store integer states. The engine binding layer converts these values to hertz, seconds, gains, enum states, and measured response tables. Centralizing that mapping prevents host and interface code from independently interpreting the same patch. See Parameter storage for the distinction between positional and display-keyed values.

Host state and bank state

An individual plugin instance owns its current patch state. Banks are instrument resources rather than part of the audio engine, and their persistence differs by host. Filesystem access is restricted to the outer layer; the DSP and engine can therefore run unchanged in WebAssembly or another future adapter.

Design invariants

  • DSP code must remain independent of operating-system and plugin APIs.
  • Host code must not duplicate parameter conversion or synthesis behavior.
  • The interface must communicate through the bridge instead of detecting hosts.
  • Audio callbacks must remain allocation-free and bounded.
  • New reusable controls belong in shared UI modules with focused behavior tests.
  • Audible compatibility changes require repeatable measurement evidence.

For the lower-level engineering rules, see the repository's docs/architecture.md.


← Patch and bank formats · Verification →

Clone this wiki locally