AquaSynth/docs/audio-doctrine.md
2026-05-08 10:40:15 +01:00

5 KiB
Raw Blame History

Aquarium Synth Audio Doctrine

Mission

AquariumSynthCSharp is the authoring and compiler surface for Aquarium synth patches. It should let us sketch sound quickly, compile to Faust, inspect the graph, compare results, and hand stable contracts to the C#/Vortice side.

The point is not to rebuild a whole audio engine in C# because we got excited near a compiler. The point is to make patch intent portable, analyzable, and pleasantly dangerous.

Realtime Law

Realtime audio has one primitive moral fact: the callback deadline wins.

Runtime-facing code must avoid operations with unbounded or scheduler-dependent latency:

  • dynamic allocation or deallocation
  • filesystem, network, console, or logging I/O
  • locks, mutexes, blocking waits, sleeps, or context switches
  • host/API calls not explicitly documented as callback-safe
  • graph compilation, parsing, reflection, or cache misses

Authoring tools can do expensive work. Audio callbacks cannot. Build patches, compile Faust, allocate buffers, score references, and serialize contracts outside the audio thread. Feed the realtime side precompiled DSP, fixed buffers, plain parameters, and lock-free or double-buffered control updates.

Dataflow Shape

Patch scripts are a textual dataflow language. Their job is to describe a graph: voices, controls, modulators, envelopes, filters, and output routing.

Pure Data is useful discipline here:

  • A patch is a graph of objects and connections, not a bag of imperative steps.
  • Audio-rate work is block-based, and block size is part of the execution model.
  • Subpatches can change block size, overlap, resampling, and on/off DSP state; those ideas map to explicit compile/runtime boundaries, not hidden globals.
  • Control events and signal streams are different animals. They can meet, but the crossing should be named.

For this repo that means:

  • Keep SynthPatch explicit and serializable.
  • Keep parser sugar as sugar. Defaults, templates, SFXR atoms, and buses should all lower into visible patch graph data.
  • Keep block size, sample rate, channel count, and latency visible in APIs that consume or produce audio buffers.
  • Prefer deterministic lowering. Same script plus same options must produce the same patch and Faust source.

Faust Boundary

Faust describes pure DSP: inputs to outputs. Architecture files and host code connect that pure processor to drivers, UI, MIDI, sensors, plugins, and the outside world.

That separation is the model for this repo:

  • The DSL owns musical intent and graph construction.
  • The Faust emitter owns pure signal expression.
  • The engine owns scheduling, buffers, device I/O, threading, and presentation.
  • Host parameters should be smoothed where they cross into signal-rate behavior.

Generated Faust should be stable, boring, and inspectable. Cleverness belongs in the DSL compiler only when it lowers to a graph a tired engineer can still read after midnight.

Control And Modulation

The Serum-style promise is not "one primitive that puts an oscillator on everything." The promise is that any meaningful parameter can be a modulation target in an ergonomic, visible way.

Rules:

  • Every modulation target must have a stable semantic name.
  • Global controls and voice-local modulators should share target names.
  • Modulators need waveform, rate, depth, phase, and bias.
  • Buses are authoring conveniences; compiled patches should expose individual target lanes.
  • UI/control-rate movement should be smoothed before it becomes audible zipper noise.

Metrics

Analysis exists to catch regressions and support search, not to crown winners.

Useful metrics:

  • envelope distance for shape and timing
  • log-mel spectrogram distance for perceptual-ish spectral shape
  • peak/RMS ratios for loudness sanity
  • zero-crossing and centroid ratios for noise/brightness drift
  • script readability and terseness scores for DSL golf work

Do not confuse high metric agreement with musical success. The game context, the reference sound, and the user’s ear still outrank the spreadsheet. Annoying, but civilization has survived worse.

Source Distillations