# RIVET architecture

## Scope

Phase 1 builds a native C++20 / Qt 6 desktop application and proves its audio
foundation. Rack devices, synthesis, arrangement, persistence and export belong
to later phases. The diagnostic sine is explicitly development functionality.

## Ownership and threads

- `app/`: application identity, startup, settings location and lifecycle.
- `ui/`: Qt widgets, settings edits and a 30 Hz status/meter timer.
- `audio/`: JACK client lifecycle, output connections and callback adapters.
  PipeWire's JACK compatibility implementation is the Fedora backend.
- `dsp/`: Qt-independent, allocation-free block processor. Initially produces
  silence, with an opt-in, quiet, ramped diagnostic sine for verification.
- `midi/`: fixed-size MIDI messages, validation and a single-producer /
  single-consumer event queue. JACK MIDI events retain their frame offsets.
- `utilities/`: logging from ordinary threads only.
- Future modules: `devices/`, `rack/`, `routing/`, `sequencer/`, `mixer/`,
  `automation/`, `project/` and `browser/`. Add these when their phase starts.

The GUI owns the engine and starts/stops it outside the callback. Deactivation
and client closure happen before its storage is destroyed. Shutdown callbacks
only publish atomic flags. GUI polling observes failure and closes the client.
No Qt call, allocation, filesystem access, blocking lock or logging occurs in
RIVET's process callback. Buffers are supplied by JACK; DSP state is allocated
before activation. Lock-free scalar atomics communicate controls and meters.
Callback work is bounded by the server block size and a capped MIDI event count.

JACK MIDI runs in the audio callback: input is validated and copied into a
bounded queue for the GUI diagnostic monitor. Queue overflow drops monitor
events and increments a counter. Phase 3 will consume events directly in DSP;
the monitor is not an instrument and does not claim MIDI produces sound.
Future sample decoding, project I/O and indexing use background workers and
publish immutable, prepared state outside the real-time callback.

## Audio configuration and safety

JACK owns the actual sample rate and quantum. RIVET displays negotiated values,
requests a buffer size while stopped, and honors PipeWire's `PIPEWIRE_RATE`
launch environment for a sample-rate hint. A hint is not a guarantee; RIVET
displays the actual result. Native JACK sample-rate changes are server configuration.
Left/right output ports and a MIDI source are selected by exact port name.
Connections are real JACK graph edges. Missing selected ports fail explicitly.
RIVET never starts a server or rewires other clients.

Startup is silent. A development-only test signal is disabled unless explicitly
requested, limited to a quiet level, and smoothed on/off. All generated samples
are checked for finiteness and bounded before output. Meters measure samples
actually sent to the output ports. Clipping detection is separate from peak
metering. No instruments or transport-shaped decorative controls are exposed.

## Build and validation

`VERSION` owns the Semantic Version. CMake validates it, extracts the numeric
project version, and generates a header containing the full version for the
application. Git is not a build dependency. `VERSIONING.md` defines compatibility
and annotated release tags; `CONTRIBUTING.md` defines the development workflow.

CMake links Qt Widgets for the application and JACK through pkg-config when its
development package is present. A build without JACK can run the window and
core tests, but explicitly reports audio unavailable; it cannot establish the
Phase 1 audio acceptance criterion. ALSA is a possible later alternate MIDI
backend; libsndfile and SQLite are not needed until file/browser phases.

CTest covers DSP silence, frequency, continuity, smoothing, invalid parameters,
output bounds and MIDI parsing/queue behavior. An offscreen Qt smoke mode
exercises startup and shutdown. A JACK integration executable connects RIVET
to a capture client, verifies real callback output without sending test sound
to speakers, injects MIDI and checks start/stop and invalid-port handling.
Real server checks are reported separately from deterministic unit tests.

## Extension boundaries

Phase 2 introduces device metadata and a validated acyclic routing graph. Build
execution plans outside the callback, allocate buffers before publication and
retire old plans outside the callback. Do not expose cables before they alter
real signal routing. The block processor is independent of JACK so later offline
rendering can use the same DSP, sample-rate and event scheduling contracts.

Time in future sequencer state uses musical ticks; a transport converts to
sample offsets for each block. Versioned project data must validate parameter
ranges, connection types and resource limits. Undo commands operate on editable
project state and publish prepared changes to the engine.

## Identity

Application: RIVET. Tagline: Build the sound. Wire the machine.
Internal reverse-domain identifier: `org.retrace.rivet` (project namespace,
not a claim of domain ownership). Original graphite/brass visual treatment;
no third-party workstation assets or presets.

## API references

- [JACK callback contract](https://jackaudio.org/api/group__ClientCallbacks.html)
- [PipeWire JACK configuration and rate hints](https://docs.pipewire.org/page_man_pipewire-jack_conf_5.html)
