AquaSynth/state/memory.json
2026-05-14 05:03:50 +01:00

85 lines
6.1 KiB
JSON

{
"project": "AquariumSynthCSharp",
"mission": "Own Aquarium Synth patch authoring, analysis, preset mapping, and Faust generation in C# for the Aquarium/Vortice engine path.",
"current_boundary": {
"leave_in_rust": [
"Rust sample renderer",
"PatchPlayer runtime",
"realtime AudioUnit bridge",
"experimental Rust DSL compiler branch"
],
"own_here": [
"patch graph model",
"operator graph model",
"renderable delayed operator feedback",
"patch parameter contracts",
"reference patch contracts",
"test-only public-domain DX7 fixtures",
"test-only dexed-py reference renderer",
"ignored listening WAV parity artifacts",
"thresholded DX7 rendered parity test",
"reference rebuild catalog",
"DX7 SysEx structural parsing",
"DX7 algorithm topology metadata",
"DX7 effective operator-level approximation",
"DX7 measured carrier output amplitude curve",
"staged operator envelope DSL",
"DX7 envelope-to-ADSR approximation",
"standard ADSR envelope model",
"note frequency/gate model",
"Faust-managed playback/polyphony contract",
"patch script parser",
"SFXR atoms and parameter mapping",
"analysis/comparison metrics",
"Faust-generated C# candidate rendering",
"script scoring",
"preset catalogs",
"Faust emission and compiler wrapper"
]
},
"taste": [
"Patch scripts should be terse but lower into explicit, inspectable graph data.",
"Compiler abstractions should remove repeated musical structure, not hide DSP behavior.",
"Generated Faust should be boring enough to diff and debug.",
"Realtime-facing work must assume allocation, locks, file I/O, console I/O, and OS calls are hostile."
],
"doctrine_refs": [
"docs/audio-doctrine.md",
"docs/dx7-calibration-plan.md",
"docs/migration-checklist.md",
"docs/reference-synth-roadmap.md",
"state/spine.yaml"
],
"reference_strategy": {
"purpose": "Use external synths and DSP corpora as parity pressure for Aquarium's patch DSL and Faust emitter: the DSL must reproduce behavior in terse, readable Aquarium syntax, not clone foreign internals.",
"priority_order": [
"DX7/Dexed SysEx for FM operator topology",
"ZynAddSubFX instruments for additive, subtractive, PAD, formant, and layered patches",
"Faust examples/libraries for general DSP graph topology",
"Surge XT for modern hybrid synth modulation",
"Cardinal/VCV-style patches for modular cable/rate semantics"
],
"rule": "Add DSL abstractions only when reference rebuilds prove the missing invariant. Do not consume references that cannot be backed by parity tests; parsing alone is inventory, not evidence of expressivity."
},
"dx7_reference_path": {
"status": "DX7 SysEx parser extracts voice edit buffers, packed voices, packed 32-voice banks, six operators, envelopes, algorithm, feedback, oscillator sync, LFO, transpose, voice name, checksum validation, ReferencePatch features, algorithm topology from the reverse-engineered OPS algorithm ROM table, envelope-to-ADSR approximations, measured carrier output amplitude, staged operator envelopes, two Aquarium DSL rebuild attempts, first-class OperatorGraph support, public-domain SysEx fixture coverage, dexed-py reference rendering, Aquarium candidate rendering through Faust-generated C#, one thresholded rendered parity test for analog1.syx voice 13, a hard PRC SYNTH1 parity probe with listening WAV artifacts and log-mel <= 0.26, and renderable delayed operator feedback.",
"lesson": "Algorithm 32's additive six-carrier shape maps cleanly to six Aquarium voices. Algorithm 8 justified OperatorGraph: operators, modulation edges, carriers, and feedback belong to a graph authority, not Voice fields. The first rendered parity rung is behavioral and sine-like, not exact DX7 operator execution. A harder algorithm-8 target exposed that feedback must be delayed recursion in Faust, not a direct cyclic self-reference. Static DX7 output-level approximation helped import/rebuild math but was mathematically wrong for carrier amplitude. A single-carrier Dexed sweep shows carrier amplitude follows 2^((outputLevel - 99) / 8). Staged operator envelopes now let Aquarium express four-rate/four-level contours in readable DSL. PRC SYNTH1 still exposes weak modulation-index and output-compensation calibration.",
"next": "Follow docs/dx7-calibration-plan.md: calibrate single-carrier amplitude, two-op modulation index, feedback, envelope level curve, and algorithm output compensation before adding new DSL surface or continuing PRC-specific tuning."
},
"note_and_envelope_model": {
"rule": "Notes own frequency, gate duration, and host/MIDI source. Envelopes own ADSR level shape.",
"sfxr_mapping": "SFXR sustain is note gate duration. SFXR punch maps to lower ADSR sustain level plus voice gain compensation so the implicit attack peak stays at 1 and the held level sits below it.",
"faust_surface": "One-shot patches use generated ADSR over patch age and note gate duration. MIDI mono/poly patches emit Faust's standard freq/gain/gate controls and [midi:on][nvoices:n] metadata so Faust architectures own note allocation."
},
"runtime_parameters": {
"rule": "Patch parameters are runtime controls, not compile-time constants.",
"faust_surface": "Faust UI controls expose parameter zones that hosts can update with setParamValue/getParamValue-style APIs.",
"aquarium_requirement": "Aquarium DSL patches declare stable exposed parameters with path/default/min/max/step metadata so callers can vary sound without recompiling.",
"binding_rule": "Parameter binding uses field-site references such as `lpf=@/macro/brightness` and `/opgraphs/0/operators/2/level`; the field owns meaning and the parameter owns the runtime value. Avoid target-routing semantics unless a new graph authority is deliberately mapped."
},
"last_verified": {
"command": "dotnet test AquariumSynthCSharp.slnx --no-restore",
"result": "55 passed with AQUARIUM_DX7_PYTHON set to bundled Python",
"commit": "pending DX7 carrier output calibration"
}
}