AquaSynth/state/spine.yaml

592 lines
42 KiB
YAML
Raw Normal View History

2026-05-12 22:53:22 +01:00
project: AquariumSynthCSharp
spine_version: 1
2026-05-14 19:41:11 +01:00
updated: 2026-05-14T19:45:00+01:00
2026-05-12 22:53:22 +01:00
prime_directive: >
Build coherent synth machinery. References exist to reveal missing structure,
not to justify piling parameters onto the current patch DSL.
current_objective: >
Turn AquariumSynthCSharp into a reference-driven patch authoring and Faust
generation library. Use external synths and DSP corpora as pressure tests so
Aquarium's DSL grows only when a real target proves the abstraction belongs.
current_mechanism:
parser: src/AquariumSynth.Dsl/PatchScript.cs
model: src/AquariumSynth.Dsl/Model.cs
faust_emitter: src/AquariumSynth.Dsl/FaustExport.cs
2026-05-13 17:18:42 +01:00
faust_renderer: src/AquariumSynth.Dsl/FaustExport.cs
2026-05-13 01:25:05 +01:00
operator_graph_model: src/AquariumSynth.Dsl/Model.cs
2026-05-12 22:53:22 +01:00
analysis: src/AquariumSynth.Dsl/AudioAnalysis.cs
built_ins: src/AquariumSynth.Dsl/BuiltInScripts.cs
2026-05-14 14:51:49 +01:00
patch_library: patches
2026-05-13 00:45:00 +01:00
dx7_references: src/AquariumSynth.Dsl/Dx7SysEx.cs
dx7_reference_fixtures: tests/AquariumSynth.Dsl.Tests/Fixtures/Dx7/PublicDomain
dx7_reference_renderer_tests: tests/AquariumSynth.Dsl.Tests/Dx7ReferenceParityTests.cs
2026-05-14 19:41:11 +01:00
zyn_reference_reader: src/AquariumSynth.Dsl/ZynInstrument.cs
zyn_project_fixtures: tests/AquariumSynth.Dsl.Tests/Fixtures/ZynAddSubFX/ProjectAuthored
2026-05-13 00:54:59 +01:00
reference_rebuilds: src/AquariumSynth.Dsl/ReferenceRebuilds.cs
2026-05-12 22:53:22 +01:00
tests: tests/AquariumSynth.Dsl.Tests/PatchScriptTests.cs
doctrine: docs/audio-doctrine.md
2026-05-14 05:03:50 +01:00
dx7_calibration_plan: docs/dx7-calibration-plan.md
2026-05-14 20:09:52 +01:00
zyn_pressure_survey: docs/zynaddsubfx-pressure-survey.md
2026-05-12 22:53:22 +01:00
roadmap: docs/reference-synth-roadmap.md
2026-05-13 00:28:31 +01:00
parameter_contracts: src/AquariumSynth.Dsl/Model.cs
2026-05-12 22:53:22 +01:00
live_invariants:
- Aquarium owns its patch graph; external synths are references, not runtime dependencies.
- Patch scripts lower into explicit graph records before Faust emission.
2026-05-13 01:25:05 +01:00
- Operator graphs own FM topology: operators, modulation edges, carriers, and feedback. Do not hide this authority inside Voice fields.
2026-05-13 11:47:39 +01:00
- Readable operator graph authoring uses `operator`, `route`, and `carrier` declarations; compact `ops=`/`edges=` is only scaffolding/interchange.
2026-05-13 12:31:43 +01:00
- Notes own frequency, gate duration, and host/MIDI source; envelopes own ADSR level shape. Do not put note duration or SFXR punch back into the general envelope model.
2026-05-13 16:10:08 +01:00
- Faust-managed MIDI polyphony is preferred: emit one voice graph with standard `freq`, `gain`, and `gate` controls plus `[midi:on][nvoices:n]` instead of inflating Aquarium graphs for local allocation.
2026-05-12 22:53:22 +01:00
- Generated Faust should remain inspectable and deterministic.
2026-05-13 17:18:42 +01:00
- Aquarium Faust output may be rendered through Faust-generated C# for candidate audio comparison; reference parity still needs a real external render or captured licensed fixture.
- Reference-patch correctness and synth parity tests live in AquariumSynthCSharp, not Aquarium.
2026-05-12 22:57:56 +01:00
- Exposed patch parameters are runtime controls, not compile-time constants.
2026-05-13 00:38:23 +01:00
- Parameter binding uses field-site references like `lpf=@/macro/brightness`; do not add target-routing semantics unless a later map proves a new authority is needed.
2026-05-13 16:50:43 +01:00
- Operator graph parameter binding also uses exact field-site paths under `/opgraphs/...`; do not add graph-wide macro routing.
2026-05-13 18:30:22 +01:00
- Operator feedback must render through Faust as delayed recursion, not as a direct cyclic self-reference.
2026-05-13 19:10:07 +01:00
- DX7 operator output level approximation belongs in reference import/rebuild helpers, not the generic DSL model.
2026-05-14 05:03:50 +01:00
- DX7 carrier output amplitude follows the measured `2^((outputLevel - 99) / 8)` curve; do not restore the old internal-level proxy.
- DX7 isolated two-operator modulation uses Aquarium route index `6.275` for full-level modulators; do not apply that blindly to cascaded stacks.
2026-05-14 15:49:21 +01:00
- DX7 feedback lowers through `Dx7SysEx.OperatorFeedbackAmount`; feedback value 5 remains 0.19 for PRC, while feedback value 7 is much hotter at 2.2 to restore community-patch buzz. Do not restore PRC-local `feedback * constant` folklore.
2026-05-14 05:27:42 +01:00
- DX7 ratio-mode detune lowers through `Dx7SysEx.OperatorFrequencyRatio`; do not silently drop detune from operator graph scripts.
- DX7 voice transpose lowers through `Dx7SysEx.NoteFrequencyHz`; transpose 24 is neutral, 12 is one octave down. Do not hardcode `freq=261.6256` for imported voices.
2026-05-14 15:39:42 +01:00
- DX7 fixed-frequency operators lower through `Dx7SysEx.FixedOperatorFrequencyHz` as absolute Hz divided by the graph base frequency; do not treat fixed mode as a note ratio.
- DX7 ROM `COM` output compensation is not a carrier-balance authority in Aquarium lowering; `OperatorOutputCompensation` returns unity and graph gain owns loudness recovery.
- DX7 operator key-scaling and rate-scaling lower against the effective played MIDI note after voice transpose; do not hardcode MIDI 60 inside imported operator level or envelope timing.
2026-05-14 14:20:37 +01:00
- DX7 route lowering is topology-aware: isolated direct branches use `OperatorModulationRouteIndex` (`6.275`); summed edges and direct edges feeding summed modulation use `SummedOperatorModulationRouteIndex` (`6.0`).
- `SummedOperatorModulationRouteIndex` is backed by the hard PRC target, a project-authored algorithm-8 stack probe, and split cascade/summed-pair probes; do not restore the older under-bright `1.6` scale.
2026-05-14 05:03:50 +01:00
- DX7 calibration must proceed through isolated rungs in `docs/dx7-calibration-plan.md`; do not keep tuning hard PRC-specific constants as a substitute for a level/index model.
2026-05-13 19:28:07 +01:00
- Staged operator envelopes own multi-target operator level contours through `env=rl rates=... levels=...`; do not force DX7-style contours back into the general ADSR voice envelope model.
2026-05-14 13:31:15 +01:00
- Staged operator envelopes may use per-segment curves through `curves=lin,exp,...`; this belongs to the rate/level contour authority, not to the standard ADSR envelope.
2026-05-13 19:28:07 +01:00
- DX7 rate/level envelopes may lower to staged operator envelopes or labeled ADSR approximations, but exact DX7 EG timing/gain calibration remains missing pressure.
2026-05-14 13:31:15 +01:00
- DX7 envelope trace evidence now lives in `Dx7SysEx.TraceEnvelope`, `Dx7SysEx.TraceInterpolatedEnvelope`, and `artifacts/parity/dx7-envelope-trace/egstep.csv`; Dexed-style audio uses block-interpolated applied gain, not the raw EG state alone.
- Do not add an `env=dx7` runtime surface until it matches Dexed plugin audio with the block-interpolated gain model, not only the raw trace helper.
2026-05-14 13:40:56 +01:00
- DX7 applied envelope lowering now lives in `Dx7SysEx.ApproximateAppliedRateLevelEnvelope`; it normalizes traced applied gain so operator output level remains a separate authority.
2026-05-14 18:48:46 +01:00
- Current DX7 analog1 algorithm-2 lowering caps non-carrier applied-envelope Level1 at 0.92 to avoid modulator peak blowout; treat this as pressure on exact DX7 EG/output modeling, not as permission to add broad peak clamps.
2026-05-14 19:06:47 +01:00
- `MELLOWSOLO` is a pressure artifact, not passing parity; its render window is 1.25s so the candidate release tail is not cut at the artifact boundary.
2026-05-14 18:48:46 +01:00
- Do not reduce summed route scale merely because an edge has three sources; a Mooger fan-in route experiment worsened evidence and was cut.
2026-05-14 19:06:47 +01:00
- Do not replace applied-envelope release with a naive traced threshold duration; it shortened releases too aggressively and broke broader DX7 parity.
2026-05-12 22:57:56 +01:00
- Recompile only for graph shape changes; vary declared parameters through the hosted DSP control API.
2026-05-12 22:53:22 +01:00
- Reference fixtures must preserve provenance, license status, source hash, and feature pressure.
- Public-domain reference fixtures and dexed-py helpers are test/development material only; the NuGet package must ship only AquariumSynth.Dsl.
2026-05-14 19:41:11 +01:00
- ZynAddSubFX import starts as feature extraction, not translation. Use project-authored `.xiz` fixtures until external preset-bank license/provenance is explicit.
2026-05-14 20:25:59 +01:00
- Named `layer` declarations own Zyn-style kit/layer identity: engine tag, optional key range metadata, default gain, and effect-send labels. They lower to ordinary voices for now; do not smuggle PAD/free-envelope/effect behavior into them.
2026-05-14 14:51:49 +01:00
- Structured `.aqua` stock lives under `patches/` as development source material. Every library patch must parse/export, and the patch library must stay out of the NuGet package unless intentionally promoted.
2026-05-14 05:50:18 +01:00
- Project-authored Dexed patches may be generated inside tests for calibration; do not ship them in the NuGet package or treat them as runtime dependencies.
2026-05-14 15:10:30 +01:00
- Harsh calibration probes belong in tests and ignored artifacts, not in the patch library unless they are musically useful stock.
2026-05-13 19:41:25 +01:00
- Listening WAV artifacts belong under ignored `artifacts/`; keep them out of NuGet and commits unless explicitly promoted as fixtures.
2026-05-13 17:09:03 +01:00
- Do not consume external synth targets that cannot be backed by parity tests. Parsing is inventory; reproducing behavior through terse, readable Aquarium DSL is the proof.
2026-05-12 22:53:22 +01:00
- Audio metrics are evidence, not final judgment.
- Do not add a generic graph escape hatch until specific references force it.
- Do not hide missing graph structure behind unrelated voice fields.
reference_targets:
dx7_dexed:
priority: 1
purpose: "Structured FM/operator graph pressure test."
source: "https://github.com/asb2m10/dexed"
status: "DX7 SysEx parser, public-domain SysEx fixture, dexed-py reference rendering, project-authored Dexed patch rendering, first thresholded rendered parity test for analog1.syx voice 13, hard PRC SYNTH1 probe with listening WAV artifacts, project-authored algorithm-8 summed-stack parity, renderable delayed operator feedback, DX7 effective operator-level approximation, measured carrier output amplitude, isolated route index, feedback table, ratio detune lowering, voice transpose lowering, fixed-frequency lowering, ROM COM compensation cut, operator key/rate scaling at the effective played note, staged operator envelopes, DX7 envelope tracing, algorithm topology extraction, envelope-to-ADSR approximation, two Aquarium DSL rebuild attempts, first-class operator graph support, and Aquarium candidate rendering through Faust-generated C# exist."
2026-05-12 22:53:22 +01:00
first_slice:
- "Add a harder public-domain DX7 parity target that audibly needs operator routing."
2026-05-12 22:53:22 +01:00
zynaddsubfx:
priority: 2
purpose: "Additive, subtractive, PAD, formant, kit, and layered-instrument pressure test."
source: "https://github.com/zynaddsubfx/zynaddsubfx"
2026-05-14 20:25:59 +01:00
status: "Initial ZynInstrumentReader reads plain or gzip-compressed .xiz XML from project-authored fixtures and classifies active ADD/SUB/PAD engines, enabled kit items, layering, envelopes, free envelopes, LFOs, filters, formants, and effects as ReferencePatch features. First Aquarium rebuilds exist for additive lead, PAD texture, and vocal/formant layer and now use named `layer` declarations. A non-vendored upstream bank survey parsed 1358/1358 .xiz files and identified named kit/layer routing as the next likely owner abstraction."
2026-05-12 22:53:22 +01:00
first_slice:
2026-05-14 20:25:59 +01:00
- "Use named layers as the owner before promoting additive harmonic bank, PAD spectral source, free envelope, or richer formant morphing syntax."
2026-05-14 19:55:36 +01:00
- "Do not add all of them at once."
2026-05-12 22:53:22 +01:00
faust:
priority: 3
purpose: "General DSP graph topology pressure test."
sources:
- "https://github.com/grame-cncm/faust"
- "https://faustlibraries.grame.fr/"
first_slice:
- "Add ExternalFaustReference catalog entries."
- "Compile selected official examples as external references."
- "Use failures to decide whether Aquarium needs a lower-level graph DSL."
surge_xt:
priority: 4
purpose: "Modern hybrid synth and modulation matrix pressure test."
source: "https://github.com/surge-synthesizer/surge"
first_slice:
- "Inspect factory patch format and license/provenance."
- "Build feature extractor before translation."
cardinal:
priority: 5
purpose: "Modular graph and cable/rate semantics pressure test."
source: "https://github.com/DISTRHO/Cardinal"
first_slice:
- "Defer until a lower-level graph layer exists."
next_agent_start_here:
recommended_first_task: >
2026-05-14 19:41:11 +01:00
Continue the ZynAddSubFX phase. The first parser/classifier slice exists in
`src/AquariumSynth.Dsl/ZynInstrument.cs` with project-authored fixtures
under `tests/AquariumSynth.Dsl.Tests/Fixtures/ZynAddSubFX/ProjectAuthored`.
2026-05-14 20:25:59 +01:00
Next pressure is to choose the next syntax that attaches to named layers:
additive harmonic bank, PAD spectral source, free envelope, or richer
formant morphing. Do one, prove it across more than one target, and leave
DX7 alone unless a regression test fails.
2026-05-12 22:53:22 +01:00
must_read:
- AGENTS.md
- docs/audio-doctrine.md
2026-05-14 05:03:50 +01:00
- docs/dx7-calibration-plan.md
2026-05-12 22:53:22 +01:00
- docs/reference-synth-roadmap.md
- state/spine.yaml
- state/memory.json
- state/evidence.jsonl
verification:
- "dotnet test AquariumSynthCSharp.slnx --no-restore"
2026-05-13 00:28:31 +01:00
completed_slices:
2026-05-14 20:25:59 +01:00
- date: 2026-05-14
summary: >
Added the first Zyn-driven language-golf abstraction: `layer`.
Layer declarations own name, engine tag, optional MIDI key range metadata,
default gain, and effect-send labels while lowering to ordinary Aquarium
voices. The three Zyn-style rebuilds now use named layers, proving the
abstraction generalizes across additive, PAD-texture, and vocal/formant
targets without adding fixture-specific shortcuts or hidden PAD/effect
behavior.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 88 passed"
2026-05-14 20:09:52 +01:00
- date: 2026-05-14
summary: >
Hardened the Zyn reader against the real upstream instrument bank and
added `ZynInstrumentSurvey`. The reader now tolerates leading whitespace
before XML declarations and counts actual `FILTER`/`FORMANT_FILTER`
blocks instead of internal formant/vowel nodes. A non-vendored scan of
`zynaddsubfx/instruments` commit `e9f64a9` parsed 1358/1358 `.xiz`
files. The top pressure target is `olivers-100/0032-Drum Kit.xiz`, with
16 enabled kit items, mixed ADD/SUB/PAD engines, 106 envelopes, 25 free
envelopes, 73 LFOs, 37 filters, and 3 formant filters. The survey points
to named kit/layer routing as the next owner abstraction before syntax
golf.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 86 passed"
2026-05-14 19:55:36 +01:00
- date: 2026-05-14
summary: >
Added first Zyn-style Aquarium rebuilds for the project-authored additive
lead, PAD texture, and vocal/formant layer fixtures. The rebuild catalog
now records matched and missing features for each target, while tests
parse/export the scripts and verify matched feature claims against source
fixture features where names overlap. The first concrete Zyn pressure is:
additive harmonic-bank syntax, PAD/spectral source generation, free
envelopes for normal voices, named kit/layer routing with per-layer effect
sends, and richer formant/vowel morphing.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 83 passed"
2026-05-14 19:41:11 +01:00
- date: 2026-05-14
summary: >
Started the ZynAddSubFX phase after closing the current DX7 community
batch. Added `ZynInstrumentReader` for `.xiz`-shaped XML, including
gzip-compressed XML support, and project-authored Zyn fixtures for an
additive lead, PAD texture, and vocal/formant layer. The classifier emits
neutral `ReferencePatch` features for active ADD/SUB/PAD engines, enabled
kit items, layering, envelopes, free envelopes, LFOs, filters, formants,
and effects. Upstream Zyn bank files were inspected but not vendored
because preset provenance was not explicit enough for this first slice.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 81 passed"
2026-05-14 19:06:47 +01:00
- date: 2026-05-14
summary: >
Reframed the latest community listening as envelope pressure rather than
harmonic pressure. `{ Mooger }` needs a more aggressive attack contour;
`RES SYNTH1` still has a phase-like attack-modulation issue even though
oscillator sync is enabled; `MELLOWSOLO` needed its pressure artifact to
capture the release tail. Extended only `MELLOWSOLO` from a 1.0s render
to 1.25s, improving pressure log-mel to 0.3472474 and score to 0.5722256.
Tested and cut a global traced-release-duration change because it broke
PRC, `Piano Bass`, `RES SYNTH1`, and `ANLGSYN 1`.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 76 passed"
2026-05-14 18:48:46 +01:00
- date: 2026-05-14
summary: >
Added scoped modulator peak headroom after listening found `ANLGSYN 1`
and `RES SYNTH1` blowing out into a drone at the modulator peak while
`Piano Bass` was spot on. The DX7 probe lowering now caps only
algorithm-2 non-carrier applied-envelope Level1 at 0.92. Latest focused
metrics: `RES SYNTH1` score 0.8140223, log-mel 0.12369786, envelope
0.06489321; `Piano Bass` unchanged at score 0.7910121, log-mel
0.13413505; `ANLGSYN 1` score 0.6980632, log-mel 0.19461302, sustained
high-band still above gate; `MELLOWSOLO` score 0.55206907, log-mel
0.42906323. Tested and cut a three-source summed-route headroom rule for
`{ Mooger }`; it worsened Mooger metrics and did not isolate the overtone
issue.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter Dx7... focused pass: 28 passed"
- date: 2026-05-14
summary: >
Lowered DX7 operator key-scaling and rate-scaling against the effective
played MIDI note after voice transpose. `Dx7SysEx.OperatorRateScaling`
now feeds the block-interpolated applied envelope trace, and the DX7
probe no longer computes operator levels at hardcoded MIDI 60. This
improves `RES SYNTH1` attack/log-mel and `Piano Bass` harmonic metrics;
`Piano Bass` graph gain rebalances to 0.72. Added a `MELLOWSOLO`
pressure artifact test because it remains the clearest harmonic mismatch
and should not be promoted as passing stock. A trial that made envelope
tracing depend on operator output level was cut because it worsened
`MELLOWSOLO` and `ANLGSYN 1`.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter Dx7... focused pass: 28 passed"
2026-05-14 18:17:37 +01:00
- date: 2026-05-14
summary: >
Removed DX7 ROM COM carrier compensation after listening found the
no-compensation community renders had closer harmonics and were mainly
too quiet. `OperatorOutputCompensation` now returns unity; graph gain owns
loudness recovery. Passing community graph gains are now `{ Mooger }`
0.75, `Piano Bass` 0.90, and `RES SYNTH1` 0.75. `RES SYNTH1` joined the
passing community gate with score 0.7277295, log-mel 0.1461968, envelope
0.10764466, RMS 0.941083. `DX1 LEAD B` and `MELLOWSOLO` sound closer by
ear under no-COM/gain-restored lowering but still fail numeric gates, so
they remain pressure targets.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 74 passed"
2026-05-14 17:43:40 +01:00
- date: 2026-05-14
summary: >
Fixed the remaining `ANLGSYN 1` drift after listening found the
conditional output-clip candidate still lost buzz halfway through the
note. `Dx7SysEx.ApproximateAppliedRateLevelEnvelope` now accepts a
sustain floor, and max-feedback source operators use a 0.9 floor in the
DX7 probe lowering so the feedback loop stays driven after the attack.
`ANLGSYN 1` now also gates a sustained 2.5-5 kHz band-energy ratio so
the old drifting version cannot pass global metrics alone. `Piano Bass`
graph gain moved to 0.30, bringing its RMS ratio to 0.9909909. Latest
`ANLGSYN 1`: score 0.7245976, log-mel 0.18460114, envelope 0.119950555,
zero-crossing 0.97149533.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 74 passed"
2026-05-14 16:20:18 +01:00
- date: 2026-05-14
summary: >
Tightened the `ANLGSYN 1` parity rung after listening caught the remaining
`deeooh` failure: the hotter feedback attack was close, but sustained
high-band buzz collapsed midway through the note. The DX7 probe lowering
now enables Aquarium's existing output soft clip only for max-feedback
voices with a self-feedback topology. PRC remains `soft_clip=false`.
Latest `ANLGSYN 1`: score 0.70946133, log-mel 0.18456098, envelope
0.10628832, RMS ratio 0.9816304, zero-crossing 0.8657629. Latest PRC:
score 0.7546429, log-mel 0.13874851, envelope 0.067291394.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 73 passed"
2026-05-14 15:49:21 +01:00
- date: 2026-05-14
summary: >
Retuned DX7 max-feedback lowering after listening found `ANLGSYN 1` still
sounded like `woooh` instead of Dexed's buzzier `deeeh`. Route-index
sweeps did not help; increasing only DX7 feedback value 7 from 0.66 to
2.2 restored high-band energy while leaving feedback value 5, and
therefore PRC's feedback amount, unchanged. For `ANLGSYN 1`, log-mel
improves from 0.19427659 to 0.17553389 and centroid ratio from 0.9182808
to 0.9519112. Band evidence: 1.2-2.5 kHz candidate/reference energy
rises from 0.8% to 65.6%, and 2.5-5 kHz from near zero to 32.1%.
Envelope/RMS are still imperfect, so this is a timbre correction rather
than the final word on ANLGSYN.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 73 passed"
2026-05-14 15:39:42 +01:00
- date: 2026-05-14
summary: >
Fixed DX7 fixed-frequency operator lowering after listening caught
`ANLGSYN 1` losing its buzzing modulation and collapsing into the wrong
drone. `Dx7SysEx.FixedOperatorFrequencyHz` now follows Dexed's fixed-mode
log-frequency formula, and `OperatorFrequencyRatio` lowers fixed
operators as absolute Hz divided by the graph base frequency. In
`ANLGSYN 1`, fixed carriers op1/op3 now lower to ratios 0.007615 and
0.009227 instead of the old fake 0.5. Added a focused parity test for
`ANLGSYN 1`; latest metrics improve to log-mel 0.19427659, envelope
0.14924917, zero-crossing 0.94662774, centroid 0.9182808, score
0.659334.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 73 passed"
- date: 2026-05-14
summary: >
Fixed DX7 voice transpose lowering after listening caught `Piano Bass`
rendering an octave too high. Added `Dx7SysEx.NoteFrequencyHz`, where
transpose 24 is neutral and transpose 12 lowers MIDI note 60 to
130.8128 Hz. `Dx7VoiceProbeScript` now uses the voice transpose for graph
frequency and detune note basis. Narrowed the community parity gate to
the two defensible voices, `{ Mooger }` and `Piano Bass`; `ANLGSYN 1`,
`RES SYNTH1`, `DX1 LEAD B`, and `MELLOWSOLO` remain pressure, not passing
parity. Fixed `Piano Bass` improves to log-mel 0.16180529, envelope
0.13544041, zero-crossing 0.905511, and score 0.64267576.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 71 passed"
2026-05-14 15:10:30 +01:00
- date: 2026-05-14
summary: >
Added a rendered public-domain community DX7 parity test against four
actual `analog1.syx` voices from Musical Artifacts artifact 152:
`ANLGSYN 1`, `{ Mooger }`, `Piano Bass`, and `RES SYNTH1`. The test
renders Dexed references, lowers the same voices through the current
Aquarium DX7 operator-graph path, writes listening WAV/report artifacts
under `artifacts/parity/dx7-community-analog1/`, and gates broad parity
at log-mel <= 0.3, envelope <= 0.16, score >= 0.5. First survey also
tried `DX1 LEAD B` and `MELLOWSOLO`; they remain pressure because
log-mel/zero-crossing mismatch is too large for the broad gate.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 70 passed"
- date: 2026-05-14
summary: >
Added split project-authored DX7 algorithm-8 parity probes for the
cascaded `6 -> 5 -> 3` branch and summed `4 + 5 -> 3` branch. The tests
render Dexed references, render Aquarium operator-graph candidates, write
listening WAV/report artifacts under `artifacts/parity/dx7-project-authored/`,
and gate log-mel at <= 0.06. Latest real-Dexed run: combined stack
log-mel 0.04029555/score 0.8664546, summed pair 0.042429477/0.870778,
cascade 0.03811625/0.9157809. The split probes remain test/artifact
material rather than patch-library stock because they are calibration
signals, not usable sounds.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore: 69 passed"
2026-05-14 14:51:49 +01:00
- date: 2026-05-14
summary: >
Added a structured development patch library under `patches/` with a
machine-readable `library.yaml`, README, and `.aqua` files exported from
existing stock/reference catalogs plus the calibrated PRC SYNTH1 parity
candidate. Added tests so every library `.aqua` parses and exports Faust,
while package-boundary tests assert `patches/` and `.aqua` files do not
ship in the AquariumSynth.Dsl NuGet package.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 67 passed"
- date: 2026-05-14
summary: >
2026-05-14 14:20:37 +01:00
Increased `Dx7SysEx.SummedOperatorModulationRouteIndex` from 1.6 to 6.0
after listening identified missing harsh stacked-modulation brightness.
2026-05-14 14:20:37 +01:00
The stronger scale improves PRC log-mel to 0.13874426, envelope distance
to 0.067291506, centroid ratio to 1.1156512, and score to 0.7546445 with
RMS ratio 0.9912135. The independent project-authored algorithm-8
summed-stack test now uses graph gain 0.218 and tighter log-mel/RMS gates.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled|ProjectAuthoredDx7AlgorithmEightSummedStackMeetsParityWhenInstalled\": passed"
2026-05-14 13:40:56 +01:00
- date: 2026-05-14
summary: >
Added `Dx7SysEx.ApproximateAppliedRateLevelEnvelope` and used it in the
hard PRC SYNTH1 probe. The helper traces Dexed-style block-interpolated
applied EG gain, normalizes it against Aquarium operator-output scaling,
and emits curved `env=rl` syntax. PRC log-mel improved from 0.24476814 to
0.21931955 and envelope distance from 0.43700194 to 0.10271241, with RMS
2026-05-14 13:52:44 +01:00
ratio near unity. A follow-up fixed the peak picker for slower rising
envelopes after listening exposed op2's false late swell; PRC now reaches
log-mel 0.17186502, envelope distance 0.13057204, zero-crossing ratio
0.7815517, and score 0.6501268.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled|ProjectAuthoredDx7AlgorithmEightSummedStackMeetsParityWhenInstalled|ApproximatesDx7AppliedEnvelopeAsCurvedRateLevelEnvelope\": passed"
2026-05-14 13:31:15 +01:00
- date: 2026-05-14
summary: >
Added per-segment curves to staged operator envelopes. `env=rl` remains
the same rate/level contour surface, but can now express linear or
exponential segments with deliberate levels above unity. The DX7 envelope
trace artifact includes a curved Aquarium candidate that is much closer
to Dexed's block-interpolated applied gain than the old linear contour.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"OperatorGraphSyntaxParsesReadableRateLevelEnvelope|OperatorGraphSyntaxParsesCurvedRateLevelEnvelope|ProjectAuthoredDx7EnvelopeTraceWritesComparisonArtifact\": passed"
- date: 2026-05-14
summary: >
Added `Dx7SysEx.TraceInterpolatedEnvelope` and extended the DX7 envelope
trace artifact with raw and applied gain columns. Dexed-style operator
rendering samples the EG once per 64-sample block and interpolates the
applied gain across the block, so matching the raw EG state alone is not
enough for audio parity.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"TracesDx7EnvelopeAppliedBlockInterpolatedGain|TracesDx7EnvelopeInternalGainShape|ProjectAuthoredDx7EnvelopeTraceWritesComparisonArtifact\": passed"
2026-05-14 13:18:53 +01:00
- date: 2026-05-14
summary: >
Added `Dx7SysEx.TraceEnvelope` and an envelope trace comparison artifact.
The trace shows DX7 EG behavior that current `env=rl` cannot express:
an initial gain spike above 1 followed by millisecond-scale collapse to a
tiny sustain. A first `env=dx7` runtime lowering attempt was cut because
matching the local trace did not match Dexed plugin audio.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"ProjectAuthoredDx7EnvelopeTraceWritesComparisonArtifact|TracesDx7EnvelopeInternalGainShape\": passed"
2026-05-14 05:50:18 +01:00
- date: 2026-05-14
summary: >
Added test-only project-authored Dexed patch rendering and an independent
algorithm-8 summed-stack parity test. This backs topology-aware summed
route lowering outside the public-domain PRC hard target. An attempted
exponential DX7 EG level curve was tested and cut: it improved some
envelope metrics but failed PRC log-mel, so EG levels remain linear until
isolated envelope parity can pass without harming PRC.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"ProjectAuthoredDx7AlgorithmEightSummedStackMeetsParityWhenInstalled|PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled|Dx7SysExTests\": passed"
2026-05-14 05:33:47 +01:00
- date: 2026-05-14
summary: >
Moved the remaining PRC cascaded-route scalar into
`Dx7SysEx.OperatorRouteIndex(topology, edge)`. Isolated direct branches
use the two-op route scale 6.275; summed edges and direct edges feeding a
summed branch use the summed/cascaded route scale 1.6. The PRC probe no
longer owns a private route-index function.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"Dx7SysExTests|PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled\": passed"
2026-05-14 05:27:42 +01:00
- date: 2026-05-14
summary: >
Added DX7 ratio-mode detune and algorithm output compensation to central
lowering. `Dx7SysEx.OperatorFrequencyRatio` preserves detune in operator
graph ratios, and `Dx7SysEx.OperatorOutputCompensation` maps ROM `COM`
output counts relative to the algorithm-32 six-output amplitude baseline.
The PRC probe no longer carries a manual carrier-level scale table; its
remaining cascaded-route value is fenced as a hard-target probe scar.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"Dx7SysExTests|PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled\": passed"
2026-05-14 05:09:43 +01:00
- date: 2026-05-14
2026-05-14 05:12:29 +01:00
summary: >
Completed the DX7 feedback calibration rung. Isolated feedback sweeps fit
Aquarium feedback amounts `0, .01, .02, .05, .10, .19, .38, .66` for DX7
feedback values 0-7. `Dx7SysEx.OperatorFeedbackAmount` now owns that
table, and the PRC probe no longer uses a local `feedback * constant`.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"CalibratesDx7FeedbackToAquariumFeedbackAmount|PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled\": passed"
- date: 2026-05-14
2026-05-14 05:09:43 +01:00
summary: >
Completed the isolated two-operator modulation-index rung. Dexed sweeps
fit full-level modulation at about 12.55 radians, which maps to Aquarium
route index 6.275 under the current Faust phase formula. The PRC probe
applies that calibrated route only to the isolated `op2 -> op1` branch;
applying it to the cascaded stack made metrics worse, leaving algorithm
output compensation as explicit pressure.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled: passed"
2026-05-14 05:03:50 +01:00
- date: 2026-05-14
summary: >
Added `docs/dx7-calibration-plan.md` and completed the first calibration
rung. A project-authored Dexed single-carrier output-level sweep showed
carrier amplitude follows `2^((outputLevel - 99) / 8)`. `Dx7SysEx` now
exposes `OperatorOutputAmplitude` and `ApproximateOperatorLevel` uses that
measured curve instead of the old internal-level proxy. The PRC log-mel
gate is temporarily 0.26 while the next rung calibrates modulation index.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter \"Dx7SysExTests|PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled\": passed"
2026-05-14 04:16:15 +01:00
- date: 2026-05-14
summary: >
Reoriented the hard DX7 `PRC SYNTH1` probe around log-mel distance after
listening confirmed aggregate score was rewarding the wrong thing.
Spectral diagnosis showed the reference's low body around 131 Hz and
dominant 393 Hz partial; the candidate now uses the DX7 note basis and
scaled high modulators to reach log-mel 0.25093183, with remaining
zero-crossing/centroid mismatch left as explicit pressure.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled: passed"
2026-05-14 01:48:11 +01:00
- date: 2026-05-14
summary: >
Tightened the hard DX7 `PRC SYNTH1` probe to require score >= 0.60 and
improved the candidate to 0.6057491. The useful calibration cuts were
removing Aquarium soft clipping, setting the graph base frequency to 392,
and boosting the op3 carrier branch for algorithm-8 output/body balance.
Global detune and per-edge route damping were tested and cut because they
made the metrics worse.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled: passed"
2026-05-13 19:41:25 +01:00
- date: 2026-05-13
summary: >
Added a hard DX7 `PRC SYNTH1` rendered parity probe that emits listening
WAV artifacts under ignored `artifacts/parity/dx7-prc-synth1` when
dexed-py and Faust are available. The Aquarium candidate uses readable
operator graph syntax and staged `env=rl` envelopes, asserts a modest
hard-target score floor, and currently scores 0.4581856 with duration
close to the Dexed reference but remaining gain/timbre mismatch.
verification: "AQUARIUM_DX7_PYTHON=<bundled python> dotnet test AquariumSynthCSharp.slnx --no-restore --filter PublicDomainDx7PrcSynth1WritesListeningWavsWhenInstalled: passed"
2026-05-13 19:28:07 +01:00
- date: 2026-05-13
summary: >
Added staged operator envelopes for operator graphs through
`env=rl rates=... levels=...`, backed by a `RateLevelEnvelope` model,
parser support, Faust `rl4_env(...)` rendering, and DX7 helper output
from four-rate/four-level operator EG data. Direct DX7 rate/level
lowering on `PRC SYNTH1` only reached ~0.316 in quick probes, so the DSL
surface exists but DX7 EG timing/gain calibration remains the next
pressure.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 53 passed"
2026-05-13 19:10:07 +01:00
- date: 2026-05-13
summary: >
Added `Dx7OperatorLevelApproximation`, which maps DX7 operator output
level plus key/velocity scaling into normal Aquarium operator levels for
reference rebuild work. Retried `PRC SYNTH1`; static level mapping alone
did not produce parity, and envelope tweaks only reached ~0.42 score. The
next pressure is DX7-style operator envelope/gain evolution.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 50 passed"
2026-05-13 18:30:22 +01:00
- date: 2026-05-13
summary: >
Probed the harder `analog1.syx` voice 17 (`PRC SYNTH1`) and found the
routed candidate failed badly instead of being thresholdable. The useful
cut was feedback: operator feedback now emits as Faust delayed recursion
instead of a direct cyclic self-reference, and a render test covers it.
Exact DX7 feedback scaling and EG behavior remain pressure.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 49 passed"
- date: 2026-05-13
summary: >
Added the first thresholded rendered DX7 parity rebuild for
`analog1.syx` voice 13, `MC-MM 5-3`. The candidate is a terse Aquarium
sine-like behavioral match and the test compares dexed-py reference audio
against Faust-rendered Aquarium audio using score, log-mel, envelope,
duration, RMS, zero-crossing, and centroid thresholds. It does not claim
exact DX7 operator execution.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 48 passed; focused dexed-py parity test passed with bundled Python"
- date: 2026-05-13
summary: >
Added a public-domain DX7 SysEx fixture from Musical Artifacts artifact
152, provenance metadata, and a test-only dexed-py renderer. The render
test uses `AQUARIUM_DX7_PYTHON` when set and otherwise stays optional.
Added a package-boundary test that packs `AquariumSynth.Dsl` and asserts
fixtures, SysEx banks, and Python helpers do not ship in the NuGet package.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 47 passed; dexed-py render test passed with bundled Python"
2026-05-13 17:18:42 +01:00
- date: 2026-05-13
summary: >
Added `FaustCompiler.RenderAsync`, which compiles Aquarium Faust source to
Faust-generated C#, runs it in a temp .NET project, and returns mono float
samples. The first render test checks non-silent generated audio and feeds
the buffer through `AudioAnalyzer`; DX7 audio parity remains blocked on a
chosen reference renderer or captured fixture.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 44 passed"
2026-05-13 16:55:30 +01:00
- date: 2026-05-13
summary: >
Added `Dx7EnvelopeApproximation`, a labeled helper that lowers DX7
four-rate/four-level envelopes to Aquarium ADSR plus gate duration.
Reference rebuilds now distinguish approximated envelope lowering from
still-missing exact DX7 EG execution.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 43 passed"
2026-05-13 16:50:43 +01:00
- date: 2026-05-13
summary: >
Added field-site parameter binding for readable operator graphs. Graph
gain/note fields, operator ratio/level/feedback/envelope fields, and route
index fields now bind through exact `/opgraphs/...` paths, and Faust
emission substitutes those bound expressions in operator graph output.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 42 passed"
2026-05-13 16:10:08 +01:00
- date: 2026-05-13
summary: >
Added a patch-level Playback contract and `instrument` authoring surface
for Faust-managed MIDI mono/polyphony. `instrument midi=true polyphony=8`
emits `[midi:on][nvoices:8]` and standard `freq`, `gain`, and `gate`
controls instead of Aquarium-owned voice allocation.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 41 passed"
2026-05-13 12:31:43 +01:00
- date: 2026-05-13
summary: >
Standardized the live envelope model as ADSR and added explicit Note
records for frequency, one-shot gate duration, and host/MIDI source.
2026-05-13 15:39:56 +01:00
SFXR sustain now maps to note gate duration; SFXR punch maps to lower
ADSR sustain level plus voice gain compensation as compatibility import
behavior. Generated Faust can emit one-shot ADSR envelopes or host
gate/frequency controls.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 40 passed"
2026-05-13 11:47:39 +01:00
- date: 2026-05-13
summary: >
Added readable operator graph authoring syntax with `operator`, `route`,
and `carrier` declarations, plus `env=ad:attack:decay` and
2026-05-13 12:31:43 +01:00
`env=adsr:attack:decay:sustain:release` forms. Converted the DX7
2026-05-13 11:47:39 +01:00
algorithm-8 rebuild away from compact number soup.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 36 passed"
2026-05-13 01:25:05 +01:00
- date: 2026-05-13
summary: >
Added first-class OperatorGraph support with operators, modulation edges,
carriers, operator feedback, parser syntax, and Faust emission mixed with
normal voices. Updated the DX7 algorithm-8 rebuild to use the operator
graph; remaining pressure is exact DX7 feedback-register timing and
rate/level envelopes.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 35 passed"
2026-05-13 00:54:59 +01:00
- date: 2026-05-13
summary: >
Added ReferenceRebuild catalog entries and two DX7-style Aquarium DSL
rebuilds. Algorithm 32 maps cleanly to six additive voices; algorithm 8
exposes missing operator graph concepts including explicit modulation
edges, summed modulators, and operator-local self-feedback.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 34 passed"
2026-05-13 00:49:53 +01:00
- date: 2026-05-13
summary: >
Added DX7 algorithm topology metadata for algorithms 1-32 from the
reverse-engineered OPS algorithm ROM table. Topology exposes carrier
operators, modulation edges, feedback-register writers, self-feedback
operators, delayed-feedback targets, raw ROM steps, and ReferencePatch
feature pressure.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 31 passed"
2026-05-13 00:45:00 +01:00
- date: 2026-05-13
summary: >
Added DX7 SysEx records and parsing for 155-byte voice edit buffers,
128-byte packed voices, and 4104-byte packed 32-voice banks. Extracted
operators, envelopes, algorithm, feedback, oscillator sync, LFO,
transpose, voice name, checksum validation, and ReferencePatch features.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 28 passed"
2026-05-13 00:28:31 +01:00
- date: 2026-05-13
summary: >
Added PatchParameter and ReferencePatch contracts, `param` script parsing,
duplicate path validation, and Faust hslider emission for declared
2026-05-13 00:38:23 +01:00
controls. Parameter binding uses field-site references such as
`lpf=@/macro/brightness`; the emitter substitutes the parameter only at
the exact bound field site and warns for unbound parameters.
verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 23 passed"
2026-05-13 00:28:31 +01:00
2026-05-12 22:53:22 +01:00
cut_line:
- "Cut any importer that cannot state source provenance and license."
- "Cut weak tests that only prove parser leniency."
- "Cut voice-field sprawl when a target needs topology."
2026-05-12 22:57:56 +01:00
- "Cut any design that requires recompiling a patch to move an exposed musical parameter."
2026-05-12 22:53:22 +01:00
- "Split a lower-level graph DSL if Faust/Cardinal-style references make the voice DSL lie."