162 lines
99 KiB
JSON
162 lines
99 KiB
JSON
{"kind":"migration","lesson":"The C# repo must own reusable authoring, analysis, preset, scoring, and Faust-generation behavior; only the Rust renderer/runtime and experimental compiler branch are intentionally left behind.","source":"user direction and migration pass through commit 3246672"}
|
|
{"kind":"realtime","lesson":"Runtime-facing audio code must avoid unbounded operations: allocation, locks, I/O, console output, OS calls, and context switches do not belong in audio callbacks.","source":"PortAudio callback documentation"}
|
|
{"kind":"dsp_graph","lesson":"Treat patch scripts as deterministic dataflow graphs with explicit rate and block semantics; terse syntax is acceptable only when lowering remains inspectable.","source":"Pure Data block/subpatch model and Faust block-diagram model"}
|
|
{"kind":"sfxr_parity","lesson":"SFXR normalized filter values are not linear cutoff frequencies. In Faust export, small SFXR high-pass values must remain very low; mapping hpf directly to thousands of Hz removes the body of pickup, jump, powerup, and blip presets while still leaving them audible enough for weak tests to pass.","source":"AquaSynth engine native Faust parity test against C# SFXR reference renderer"}
|
|
{"kind":"dsl_reference_corpus","lesson":"BFXR, SFXR, 808, FM, and wobble presets are reference patches for testing and DSL design, not terseness trophies. Built-ins should be readable enough to teach the patch language, and the parser should support multi-line commands instead of forcing all expressive patches into one-line golf.","source":"user clarified preset purpose for patch DSL iteration"}
|
|
{"kind":"advanced_reference_patches","lesson":"The synth reference catalog needs complex examples that combine defaults, templates, multiple voices, modulation buses, FM, formants, noise layers, repeat, and soft clipping. These patches expose DSL readability and composition pressure better than short one-shot SFX presets.","source":"user asked for sophisticated patch references"}
|
|
{"kind":"reference_synth_roadmap","lesson":"AquaSynth should use external synth and DSP corpora as reference targets, not just internal demo patches. Start with DX7/Dexed SysEx for structured FM, then ZynAddSubFX, Faust examples/libraries, Surge XT, and Cardinal as progressively broader pressure tests. Keep provenance and license state explicit before vendoring fixtures.","source":"user clarified any synth can be broken down and rebuilt via AquaSynth DSL"}
|
|
{"kind":"runtime_patch_parameters","lesson":"Synth patches must expose expressive runtime parameters. Faust supports this through UI controls and hosted parameter APIs, so AquaSynth should compile a graph once and vary declared parameter values without recompilation. Recompile only for structural graph changes.","source":"user asked whether Faust can vary one number without recompiling"}
|
|
{"kind":"synth_test_ownership","lesson":"AquaSynth owns reference-patch correctness. AquaSynth should only smoke-test the engine synth host and bundled Faust boundary; SFXR/BFXR/reference parity belongs here so the engine can keep moving while the synth library is under active surgery.","source":"user questioned synth tests living in AquaSynth"}
|
|
{"kind":"package_boundary","lesson":"AquaSynth consumes AquaSynth.Dsl through a pinned package, not a live project reference. Breaking changes in AquaSynth are allowed during synth construction as long as a new package version is packed and AquaSynth is updated deliberately when the boundary should move.","source":"user wanted AquaSynth builds insulated from synth-agent work"}
|
|
{"kind":"runtime_patch_parameters","lesson":"AquaSynth patch scripts now have first-class `param` declarations and patch/reference model contracts. Faust emission exposes declared parameters as smoothed hslider controls, but target binding is intentionally still absent and warned about; do not claim parameters shape sound until binding is designed.","source":"parameter contract implementation on 2026-05-13"}
|
|
{"kind":"runtime_patch_parameters","lesson":"AquaSynth parameter binding uses Option B: numeric field values may reference declared parameters with `@/path`, producing exact field bindings such as `/voices/0/filter/lpf`. The field owns the meaning; the parameter owns the runtime value. Avoid target-routing parameter semantics unless a new authority is deliberately mapped.","source":"user rejected target binding as a landmine; field-site binding implemented on 2026-05-13"}
|
|
{"kind":"dx7_reference_path","lesson":"DX7 reference elaboration starts with structural extraction, not translation. The repo now parses 155-byte voice edit buffers, 128-byte packed voices, and 4104-byte packed 32-voice SysEx banks into neutral DX7 records with checksum validation and ReferencePatch features. Next pressure point is explicit algorithm topology metadata for carriers, modulation edges, and feedback edge location.","source":"DX7 SysEx parser slice on 2026-05-13"}
|
|
{"kind":"dx7_reference_path","lesson":"DX7 algorithm topology is now derived from the reverse-engineered OPS algorithm ROM table, not hand-drawn diagrams. Topology exposes carrier operators, modulation edges, feedback-register writers, self-feedback operators, delayed-feedback targets, and raw ROM steps. Use this as pressure evidence before adding an AquaSynth operator graph layer.","source":"DX7 algorithm topology slice on 2026-05-13; Ken Shirriff OPS ROM table"}
|
|
{"kind":"dx7_reference_rebuilds","lesson":"Two DX7-style AquaSynth rebuilds now make the pressure explicit: algorithm 32 maps cleanly to layered additive voices, but algorithm 8 exposes missing graph structure (operator modulation edges, summed modulators, and operator-local self-feedback). Do not patch this with more Voice fields; decide whether an operator graph model owns this invariant.","source":"DX7 rebuild catalog slice on 2026-05-13"}
|
|
{"kind":"operator_graph_model","lesson":"DX7 algorithm-8 pressure justified a first-class OperatorGraph abstraction. OperatorGraph owns FM topology: operators, modulation edges, carriers, and feedback. Do not hide this authority inside Voice fields. Remaining DX7 pressure is exact feedback-register timing and rate/level envelopes.","source":"operator graph implementation slice on 2026-05-13"}
|
|
{"kind":"operator_graph_authoring","lesson":"Operator graph authoring should use readable `operator`, `route`, and `carrier` declarations with `env=ad:...` or `env=adsr:...`. Compact `ops=`/`edges=` tuples are acceptable as importer/interchange scaffolding only, not the face of the DSL.","source":"user rejected number-soup operator syntax; readable operator graph syntax slice on 2026-05-13"}
|
|
{"kind":"note_envelope_model","lesson":"AquaSynth's general envelope model is ADSR: attack, decay, sustain level, release. Note timing belongs to `Note` records: frequency, gate duration, and host/MIDI source. SFXR sustain maps to note gate duration; SFXR punch maps to lower sustain level plus voice gain compensation so ADSR peak remains implicit 1 and the held level sits below the transient.","source":"user identified SFXR sustain as note duration and Punch as transient above sustain; punch mapping correction on 2026-05-13"}
|
|
{"kind":"faust_polyphony","lesson":"Prefer Faust-managed MIDI polyphony over AquaSynth graph inflation. AquaSynth should emit a single voice graph with standard `freq`, `gain`, and `gate` controls plus `[midi:on][nvoices:n]`; Faust architectures own MIDI decoding and voice allocation unless a concrete target proves the boundary insufficient.","source":"Faust official MIDI/polyphony docs and user preference for Faust support on 2026-05-13"}
|
|
{"kind":"operator_graph_parameters","lesson":"Readable operator graph fields bind runtime parameters at exact `/opgraphs/...` field paths: graph gain/note fields, operator ratio/level/feedback/envelope fields, and route index fields. Keep compact `ops=`/`edges=` as importer scaffolding and avoid graph-wide macro routing.","source":"operator graph field-site binding slice on 2026-05-13"}
|
|
{"kind":"dx7_envelopes","lesson":"DX7 four-rate/four-level operator envelopes can be lowered to labeled AquaSynth ADSR approximations plus gate duration, but this is not exact DX7 EG execution. Reference rebuilds should record approximation as matched pressure and exactness as still missing.","source":"DX7 envelope approximation slice on 2026-05-13; Yamaha DX7 manual describes EGs as four rates and four levels"}
|
|
{"kind":"render_parity_harness","lesson":"AquaSynth Faust output can now be compiled to Faust-generated C# and rendered into mono float samples for AudioAnalyzer comparisons. This proves the candidate side of parity; DX7 parity still requires a real Dexed/reference render or captured licensed fixture, not self-comparison.","source":"Faust render parity harness slice on 2026-05-13"}
|
|
{"kind":"reference_parity_doctrine","lesson":"External synth references exist to exercise AquaSynth DSL expressiveness, not to clone foreign internals. Consume only references that can be backed by parity tests proving AquaSynth can reproduce the behavior in terse, readable syntax; parsing a format is inventory, not evidence.","source":"user clarified reference-synth purpose and parity-test requirement on 2026-05-13"}
|
|
{"kind":"dx7_reference_rendering","lesson":"DX7 reference rendering now uses dexed-py as optional test tooling against a public-domain SysEx fixture. Keep fixtures and renderer helpers under the test project, preserve provenance and SHA-256 beside vendored banks, and keep AquaSynth.Dsl.nupkg free of SysEx/Python/test assets.","source":"dexed-py public-domain fixture harness slice on 2026-05-13"}
|
|
{"kind":"dx7_rendered_parity","lesson":"The first thresholded rendered DX7 parity target is analog1.syx voice 13, MC-MM 5-3. AquaSynth matches the rendered behavior with a short sine-like patch and explicit score/log-mel/envelope/duration/RMS/zero-crossing/centroid thresholds. Treat this as proof of the parity loop, not proof of exact DX7 operator execution; next target should audibly require operator routing.","source":"first thresholded DX7 rendered parity slice on 2026-05-13"}
|
|
{"kind":"operator_feedback","lesson":"A harder DX7 algorithm-8 target exposed direct operator self-reference as non-renderable Faust. Operator feedback now emits as delayed Faust recursion, which keeps the render path alive and is closer to DX7 feedback pressure; exact DX7 feedback scaling remains unsolved.","source":"PRC SYNTH1 parity probe and delayed feedback render fix on 2026-05-13"}
|
|
{"kind":"dx7_operator_levels","lesson":"DX7 operator output level is nonlinear and includes key/velocity offsets before envelope gain. Added a reference-import helper to approximate effective AquaSynth operator levels, but PRC SYNTH1 still only improved to ~0.34 with static levels and ~0.42 with envelope tweaks; hard parity now points at DX7-style operator envelope/gain evolution rather than static level mapping alone.","source":"DX7 effective operator level probe on 2026-05-13"}
|
|
{"kind":"staged_operator_envelopes","lesson":"Operator graphs now have a readable staged envelope surface, env=rl rates=... levels=..., backed by RateLevelEnvelope and Faust rl4_env rendering. This exercises the DSL with DX7-style multi-target contours without changing the general ADSR voice envelope. Direct DX7 rate/level lowering on PRC SYNTH1 peaked around ~0.316 in quick probes, so the next parity pressure is calibrated DX7 EG timing/gain rather than more syntax.","source":"staged operator envelope slice and PRC SYNTH1 probe on 2026-05-13"}
|
|
{"kind":"dx7_prc_listening_artifacts","lesson":"The hard PRC SYNTH1 parity probe now writes ignored WAV artifacts for ear checks under artifacts/parity/dx7-prc-synth1. A calibrated readable operator-graph candidate with staged env=rl envelopes scores ~0.458: duration is close, while RMS and timbre remain off. Use listening plus metrics to choose the next calibration target instead of blindly adding DSL surface.","source":"PRC SYNTH1 listening WAV probe on 2026-05-13"}
|
|
{"kind":"dx7_prc_calibration","lesson":"PRC SYNTH1 improved to a modest passing score of ~0.606 without new DSL surface. Removing soft clipping, using a 392 Hz graph base, and boosting the op3 carrier branch helped; global detune and per-edge route damping worsened metrics and were cut. Remaining pressure is DX7 output/index scaling or algorithm output compensation, not more envelope syntax.","source":"PRC SYNTH1 calibration pass on 2026-05-14"}
|
|
{"kind":"dx7_prc_logmel","lesson":"Listening and log-mel agreed that the aggregate PRC SYNTH1 score was misleading. The Dexed reference has strong low/body partials around 131 Hz and 393 Hz; AquaSynth's earlier candidate lacked the low body despite a better aggregate score. The probe now gates on log-mel <=0.255 with a loose aggregate floor, and remaining mismatch points at DX7 output/index scaling and algorithm compensation.","source":"PRC SYNTH1 perceptual/log-mel calibration on 2026-05-14"}
|
|
{"kind":"dx7_output_level_curve","lesson":"A project-authored Dexed single-carrier sweep shows DX7 carrier amplitude follows 2^((outputLevel - 99) / 8). The previous internal-level proxy made mid-level operators far too loud. `Dx7SysEx.OperatorOutputAmplitude` now owns the measured curve; next calibration rung is two-operator modulation index.","source":"DX7 single-carrier calibration rung on 2026-05-14"}
|
|
{"kind":"dx7_modulation_index","lesson":"Isolated two-operator Dexed FM fits full-level modulation at about 12.55 radians. Under AquaSynth's current Faust phase formula this maps to route index 6.275 for a full-level modulator. Apply this to isolated two-op branches, but do not blindly apply it to cascaded algorithm stacks before algorithm output compensation is modeled.","source":"DX7 two-operator modulation calibration rung on 2026-05-14"}
|
|
{"kind":"dx7_feedback_scale","lesson":"Isolated Dexed feedback sweeps fit a nonlinear AquaSynth feedback table: 0, .01, .02, .05, .10, .19, .38, .66 for DX7 feedback values 0-7. PRC feedback value 5 was already accidentally close via feedback*0.04; the table moves that knowledge into Dx7SysEx.OperatorFeedbackAmount.","source":"DX7 feedback calibration rung on 2026-05-14"}
|
|
{"kind":"dx7_detune_and_com","lesson":"PRC exposed two separate DX7 facts: ratio-mode detune must lower into operator frequency ratios, and ROM COM output compensation must be applied relative to the algorithm-32 six-output baseline used by the carrier-amplitude calibration. This cut the PRC carrier scale table; the remaining cascaded-route constant is still a fenced hard-target scar needing summed-modulator calibration.","source":"DX7 PRC parity rung on 2026-05-14"}
|
|
{"kind":"dx7_topology_aware_route_index","lesson":"The PRC hard target proved DX7 route index cannot key only on ROM edge kind: a direct edge feeding a later summed branch behaves like part of the cascaded/summed stack, not like the isolated two-op branch. `Dx7SysEx.OperatorRouteIndex(topology, edge)` now owns this distinction; PRC no longer has a private route function.","source":"DX7 summed/cascaded route lowering on 2026-05-14"}
|
|
{"kind":"dx7_project_authored_patch_rendering","lesson":"Project-authored Dexed patches can be generated directly inside tests from explicit operator specs. Use this for lawful calibration rungs instead of squeezing every DX7 fact out of public-domain hard patches.","source":"DX7 project-authored summed-stack parity on 2026-05-14"}
|
|
{"kind":"dx7_envelope_curve_cut","lesson":"Reusing the operator output amplitude curve for DX7 EG levels is not ready: it can improve isolated envelope shape metrics with shorter timing, but it failed the hard PRC log-mel target. Keep EG levels linear until isolated envelope parity passes without regressing PRC.","source":"DX7 envelope level experiment on 2026-05-14"}
|
|
{"kind":"dx7_envelope_trace","lesson":"Direct DX7 EG tracing shows the current `env=rl` abstraction is the wrong shape for some DX7 envelopes: the traced EG can spike above unit gain and drop below .02 within about 9 ms while `env=rl` is still near 1. A runtime `env=dx7` surface was attempted and cut because matching the local trace did not yet match Dexed plugin audio.","source":"DX7 envelope trace artifact on 2026-05-14"}
|
|
{"kind":"dx7_envelope_applied_gain","lesson":"Dexed-style operator audio does not use the raw DX7 EG state directly. It samples the EG once per 64-sample block and linearly interpolates applied gain across the block. A DX7-capable AquaSynth envelope must model that applied-gain timebase; matching raw EG trace alone can make a candidate far too quiet or otherwise wrong.","source":"DX7 interpolated envelope trace artifact on 2026-05-14"}
|
|
{"kind":"curved_rate_level_envelope","lesson":"AquaSynth staged operator envelopes now support per-segment curves and deliberate levels above unity. Keep this authority in `RateLevelEnvelope`: it protects the invariant that multi-target operator contours can model exponential synth envelopes without inventing one-off DX7 syntax.","source":"Curved rate/level envelope implementation on 2026-05-14"}
|
|
{"kind":"dx7_applied_envelope_lowering","lesson":"`Dx7SysEx.ApproximateAppliedRateLevelEnvelope` improves the hard PRC target by tracing Dexed-style block-interpolated EG gain, normalizing it against AquaSynth operator output level, and emitting curved `env=rl`. Latest PRC metrics: log-mel 0.21931955, envelope distance 0.10271241, RMS ratio 1.0003664, score 0.5026183. Zero-crossing worsened to 0.28642866, so contour parity exposed a remaining oscillator/phase mismatch rather than solving DX7 parity outright.","source":"DX7 applied-envelope PRC probe on 2026-05-14"}
|
|
{"kind":"dx7_applied_envelope_peak_picker","lesson":"Listening caught a real lowering bug: the first applied-envelope approximation treated the first 64-sample block as the attack peak, which made slower rising op2 in PRC swell late (`0.014 -> 0.613`) instead of hitting early and decaying. Picking the first near-peak before gate gives op2 `0.981 -> 0.843 -> 0.660` and improves PRC to log-mel 0.17186502, RMS 1.0000212, zero-crossing 0.7815517, score 0.6501268.","source":"PRC SYNTH1 listening-guided envelope fix on 2026-05-14"}
|
|
{"kind":"dx7_summed_route_scale","lesson":"Listening identified missing harsh stacked-modulation brightness. Raising `Dx7SysEx.SummedOperatorModulationRouteIndex` from 1.6 to 2.4 improves PRC to log-mel 0.16794802, envelope distance 0.09510617, centroid ratio 1.1254044, RMS ratio 1.00095, score 0.68491656, and also tightens the project-authored algorithm-8 summed-stack log-mel when graph gain is normalized. Keep isolated direct branches at 6.275; the stronger 2.4 scale belongs only to summed/cascaded DX7 branches.","source":"DX7 stacked modulation brightness calibration on 2026-05-14"}
|
|
{"kind":"dx7_summed_route_scale_hotter","lesson":"Follow-up listening and band analysis showed the previous summed/cascaded scale still sounded underwater. Raising `Dx7SysEx.SummedOperatorModulationRouteIndex` to 6.0 and normalizing PRC graph gain to 0.25 improves PRC to log-mel 0.13874426, envelope distance 0.067291506, RMS ratio 0.9912135, zero-crossing ratio 0.95325506, centroid ratio 1.1156512, score 0.7546445. A hotter 7.0 scale did not buy enough log-mel improvement and worsened RMS/score, so 6.0 is the current coherent stop.","source":"DX7 stacked modulation brightness hot sweep on 2026-05-14"}
|
|
{"kind":"patch_library","lesson":"Repo-owned AquaSynth .aqua stock now lives under patches/ with library.yaml; every .aqua must parse/export in tests and the patch library must remain out of AquaSynth.Dsl.nupkg unless intentionally promoted.","source":"Patch library folder slice on 2026-05-14"}
|
|
{"kind":"dx7_algorithm8_split_route_parity","lesson":"The DX7 summed/cascaded route scale 6.0 is now backed by split project-authored algorithm-8 rendered probes, not only PRC or one combined stack. Latest real-Dexed run: combined stack log-mel 0.04029555 score 0.8664546, summed pair log-mel 0.042429477 score 0.870778, cascade log-mel 0.03811625 score 0.9157809. Keep isolated direct branches at 6.275 and summed/cascaded branches at 6.0 until broader evidence contradicts it.","source":"Split algorithm-8 parity probes on 2026-05-14"}
|
|
{"kind":"patch_library_taste","lesson":"Not every parity probe belongs in the patch library. Harsh project-authored DX7 calibration probes should stay in tests and ignored listening artifacts unless they are musically useful stock; the navigable .aqua library is for reusable inspiration, not measurement torture signals.","source":"User listening correction on 2026-05-14"}
|
|
{"kind":"dx7_community_voice_parity","lesson":"Actual public-domain analog1.syx community voices are useful broader probes, but listening rejected the first loose gate. ANLGSYN 1, RES SYNTH1, DX1 LEAD B, and MELLOWSOLO should remain pressure until their timbre/zero-crossing mismatch is understood. Only Mooger and fixed Piano Bass are currently defensible rendered community parity targets.","source":"Community DX7 analog1.syx survey on 2026-05-14"}
|
|
{"kind":"dx7_voice_transpose","lesson":"Piano Bass in analog1.syx proved imported DX7 voices must lower the voice transpose byte into graph frequency. Transpose 24 is neutral; transpose 12 lowers MIDI note 60 to 130.8128 Hz. Hardcoding 261.6256 made Piano Bass a full octave too high. After the fix, Piano Bass improves to log-mel 0.16180529, zero-crossing 0.905511, score 0.64267576. Do not call the broader analog1.syx survey passing; only Mooger and fixed Piano Bass are currently defensible.","source":"Piano Bass listening correction on 2026-05-14"}
|
|
{"kind":"dx7_fixed_frequency","lesson":"ANLGSYN 1 proved DX7 fixed-frequency operators must lower as absolute Hz divided by the graph base frequency, not as note ratios. Dexed fixed mode uses a log-frequency formula; op1 fixed 0/0 is about 1 Hz and op3 fixed 0/8 detune 14 is about 1.207 Hz, yielding ratios 0.007615 and 0.009227 against the transposed 130.8128 Hz graph base. This restores the low buzzing modulation and improves ANLGSYN 1 to log-mel 0.19427659, zero-crossing 0.94662774, score 0.659334.","source":"ANLGSYN 1 listening correction on 2026-05-14"}
|
|
{"kind":"dx7_max_feedback","lesson":"ANLGSYN 1 still sounded too 'woooh' after fixed-frequency lowering because high-band buzz was missing. Route-index sweeps did not help; increasing only DX7 feedback value 7 from 0.66 to 2.2 restored much more 1.2-5 kHz energy while leaving feedback value 5 at 0.19 for PRC. Latest ANLGSYN 1: log-mel 0.17553389, centroid 0.9519112, zero-crossing 0.90904, score 0.6448498. Envelope/RMS worsened, so this is a timbre correction, not final ANLGSYN parity.","source":"ANLGSYN 1 max-feedback listening correction on 2026-05-14"}
|
|
{"kind":"dx7_output_nonlinearity","lesson":"ANLGSYN 1 listening caught a remaining 'deeooh' failure: the max-feedback candidate had a close attack but lost sustained high-band punch halfway through. Enabling AquaSynth's existing output soft clip only for max-feedback self-feedback DX7 voices improved ANLGSYN to score 0.70946133, log-mel 0.18456098, envelope 0.10628832, RMS 0.9816304 while PRC stayed passing with soft clip disabled at score 0.7546429 and log-mel 0.13874851. Do not apply the nonlinearity globally; PRC proves that would be a compensator.","source":"ANLGSYN 1 sustained-buzz parity correction on 2026-05-14"}
|
|
{"kind":"dx7_max_feedback_envelope_floor","lesson":"Output soft clip alone did not fix ANLGSYN 1's mid-note drift. The self-feedback source operator was under-driven after the attack; preserving a 0.9 applied-envelope sustain floor for max-feedback source operators lifted the sustained 2.5-5 kHz band ratio from about 0.175 to above 1.0 and improved ANLGSYN 1 to score 0.7245976, log-mel 0.18460114, envelope 0.119950555, zero-crossing 0.97149533. Add sustained band gates when broad log-mel allows audible drift through.","source":"ANLGSYN 1 sustained high-band parity gate on 2026-05-14"}
|
|
{"kind":"dx7_com_compensation_cut","lesson":"ROM COM carrier compensation was louder but harmonically wrong for the analog1 community pass. User listening preferred the no-COM renders across patches; the real issue was that they were too quiet. Cut hidden per-carrier COM boosts: `OperatorOutputCompensation` returns unity and graph gain owns loudness recovery. Passing community gains with no COM are Mooger 0.75, Piano Bass 0.90, RES SYNTH1 0.75. DX1 LEAD B and MELLOWSOLO sound closer by ear with no COM but remain numeric pressure targets.","source":"community DX7 listening correction on 2026-05-14"}
|
|
{"kind":"dx7_effective_note_scaling","lesson":"DX7 operator key-scaling and rate-scaling must lower against the effective played MIDI note after voice transpose, not hardcoded MIDI 60. `Dx7SysEx.OperatorRateScaling` now feeds the block-interpolated applied envelope trace, and imported operator levels use the effective note. This improves RES SYNTH1 attack/log-mel and Piano Bass harmonic metrics; Piano Bass graph gain rebalances from 0.90 to 0.72. MELLOWSOLO remains the clearest harmonic mismatch and now has a pressure artifact test rather than a fake parity pass. A trial output-level-dependent applied-envelope trace was cut because it worsened MELLOWSOLO and ANLGSYN 1.","source":"community DX7 listening correction on 2026-05-14"}
|
|
{"kind":"dx7_modulator_peak_headroom","lesson":"Listening found ANLGSYN 1 and RES SYNTH1 blowing out into a drone at the modulator-envelope peak while Piano Bass was spot on. The surviving DX7 probe change caps only algorithm-2 non-carrier applied-envelope Level1 at 0.92, preserving Piano Bass and improving RES SYNTH1 while keeping ANLGSYN judged by log-mel and sustained high-band evidence rather than aggregate score. A wider summed-route headroom experiment for Mooger fan-in was tested and cut because it worsened Mooger metrics and did not isolate the overtone-emphasis issue.","source":"community DX7 listening correction on 2026-05-14"}
|
|
{"kind":"dx7_mellowsolo_tail_window","lesson":"MELLOWSOLO pressure artifacts need a longer render window than 1.0s because the AquaSynth candidate emits a 0.6s release from a 0.65s gate, so the old WAV cut the tail before it could finish. Extending only the MELLOWSOLO pressure render to 1.25s improves log-mel from about 0.429 to 0.347 and makes the tail audible without changing the synth lowering or passing parity targets. A global traced-release-duration experiment was tested and cut because it shortened releases too aggressively and broke PRC, Piano Bass, RES SYNTH1, and ANLGSYN 1. RES SYNTH1 has oscillator sync enabled, so its phase-like attack issue is more likely relative operator attack/peak shape than free-running oscillator phase.","source":"community DX7 listening correction on 2026-05-14"}
|
|
{"kind":"dx7_graph_pitch_lfo","lesson":"ANLGSYN 1's missing beat is DX7 pitch LFO, not amplitude LFO: raw analog1.syx has AMD=71 but all operator AMS values are 0, while PMD=32/PMS=1/sine speed 38/delay 33 are active. AquaSynth operator graphs now own graph-level vibrato (`vibrato`, `vibrato_hz`, `vibrato_delay`) and the DX7 probe lowers that LFO to about depth 0.003694 at 5.993 Hz with a 0.233s fade-in. A hard delay gate was tested and cut because it pushed log-mel over the ANLGSYN gate; fade-in keeps ANLGSYN passing at log-mel about 0.19497 and score about 0.6979.","source":"ANLGSYN 1 pitch-LFO beat correction on 2026-05-14"}
|
|
{"kind":"zyn_reference_start","lesson":"The ZynAddSubFX phase should start with structural feature extraction, not translation. Upstream Zyn instruments live in a separate bank submodule and the preset provenance is not clear enough to vendor casually, so the first parser slice uses project-authored .xiz fixtures. `ZynInstrumentReader` reads plain or gzip-compressed XML and classifies active ADD/SUB/PAD engines, kit layering, envelopes, free envelopes, LFOs, filters, formants, and effects into ReferencePatch features.","source":"ZynAddSubFX feature extraction kickoff on 2026-05-14"}
|
|
{"kind":"zyn_reference_rebuilds","lesson":"The first Zyn-style AquaSynth rebuilds can sketch additive lead, PAD texture, and vocal/formant layer fixtures with existing voices, macros, formants, filters, noise, and modulation, but the missing abstractions are now concrete: 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. Keep these as named pressure before adding new DSL surface.","source":"ZynAddSubFX rebuild catalog slice on 2026-05-14"}
|
|
{"kind":"zyn_worst_case_survey","lesson":"Scanning the upstream ZynAddSubFX instrument bank at commit e9f64a9 found 1358 .xiz files and the hardened reader now parses all of them. The nastiest target is `olivers-100/0032-Drum Kit.xiz`: 16 enabled kit items, mixed ADD/SUB/PAD engines, 106 envelopes, 25 free envelopes, 73 LFOs, 37 filters, and 3 formant filters. The broader top list says named kit/layer routing should come before syntax golf for additive banks, PAD sources, or formant motion; otherwise new abstractions will have no coherent owner.","source":"ZynAddSubFX pressure survey on 2026-05-14"}
|
|
{"kind":"layer_language_golf","lesson":"The first Zyn-driven language-golf abstraction is `layer`: named layer declarations own engine tags, optional MIDI key range metadata, default gain, and effect-send labels, while lowering to ordinary AquaSynth voices for now. The abstraction generalizes across additive, PAD-texture, and vocal/formant rebuilds and gives future additive-bank, PAD-source, free-envelope, and formant-motion syntax a coherent owner. It deliberately does not implement those later features yet.","source":"Zyn named layer DSL slice on 2026-05-14"}
|
|
{"kind":"harmonic_bank_language_golf","lesson":"Additive `harmonics` syntax now records authored ratio/gain partial banks under named layers and lowers them to ordinary AquaSynth voices. This generalizes additive lead and future drawbar/partial-bank targets without hiding Zyn ADDsynth phase, bandwidth, oscillator shaping, or free-envelope semantics behind a fake parity claim.","source":"Zyn harmonic-bank DSL slice on 2026-05-14"}
|
|
{"kind":"voice_rate_level_envelopes","lesson":"The existing readable `env=rl rates=... levels=... curves=... gate=...` contour now applies to normal voices and therefore to named layer defaults, not only operator graphs. This gives PAD and vocal Zyn rebuilds staged non-ADSR onset/release shape while preserving the invariant that Note owns gate timing and envelope data owns level shape. Arbitrary Zyn free-envelope point curves remain missing pressure.","source":"Zyn staged voice envelope DSL slice on 2026-05-14"}
|
|
{"kind":"pad_spectral_cloud","lesson":"PAD-style layers now have `spectrum layer=... root=... spread=... partials=ratio:gain,...`, recorded as `SpectralBank` and generated as PADsynth-style FFT tables: frequency-domain harmonic spreading, deterministic random phase, one inverse FFT, normalization, then Faust waveform/rdtable playback before ordinary voice treatment. This gives PAD texture rebuilds a real spectral source authority without inflating the voice graph; roots/spreads/partials are authoring-time table shape, not runtime controls. It still does not claim full Zyn PAD harmonic-profile/randomness/pitch-zone behavior.","source":"Zyn PAD spectral-cloud DSL slice on 2026-05-14"}
|
|
{"kind":"zyn_reference_oracle","lesson":"ZynAddSubFX source is pinned as GPL test/development material under `external/zynaddsubfx` at 3ab608c432996ba4d582176572c0b0f82328c825. Treat it like dexed-py: a parity oracle for tests and artifacts, not AquaSynth implementation, runtime dependency, or NuGet package content. Before further Zyn DSL golf, build a test-only PAD renderer/wrapper from this source and compare AquaSynth rebuilds against actual Zyn behavior.","source":"Zyn source pinning for parity on 2026-05-14"}
|
|
{"date":"2026-05-14","area":"zyn-reference","lesson":"Pinned Zyn can build on Windows through MSYS2/MinGW when GUI/plugins are disabled, tests are enabled, Werror is off, and the stale non-async MiddleWare Part constructor call is patched. Apply Zyn compatibility patches to ignored artifact source copies, not the clean pinned submodule.","evidence":"tools/zyn-reference/build-zyn-reference.ps1 copies external/zynaddsubfx to artifacts/zyn-source-msys, applies tools/zyn-reference/patches/0001-msys-part-constructor.patch, builds PadNoteTest, and ctest -R PadNoteTest passes."}
|
|
{"date":"2026-05-15","area":"zyn-pad-parity","lesson":"The Zyn PAD oracle now emits real reference material through Zyn PADnoteParameters/PADnote, and the first project-authored PAD comparison is not close: log-mel 0.552296, envelope 0.774501, RMS ratio 0.234763, centroid ratio 1.025735, score 0.236117. Treat this as evidence to isolate source table generation, playback/gain, envelope, and fixture mapping before adding more Zyn DSL syntax.","evidence":"tools/zyn-reference/ZynPadReference.cpp plus tests/AquaSynth.Dsl.Tests/ZynReferenceParityTests.cs write artifacts/parity/zyn-pad-reference/pad-texture-zyn.wav, pad-texture-aqua.wav, and report.txt when the Zyn artifact renderer is built."}
|
|
{"date":"2026-05-15","area":"zyn-pad-parity","lesson":"User listening correctly identified the first AquaSynth PAD rebuild as too noisy. The fix was architectural cleanup before new syntax: cut unearned noise/drive/soft-clip from the rebuild, interpolate spectral table reads, and use Zyn-sized 131072-frame PAD tables. Score improved from 0.236117 to 0.487325, with RMS ratio 1.008516 and centroid ratio 1.083082. Remaining mismatch is source profile/table generation and envelope semantics, not decorative layers.","evidence":"artifacts/parity/zyn-pad-reference/report.txt after the de-bee pass; full dotnet test passed 96/96."}
|
|
{"date":"2026-05-15","area":"zyn-pad-parity","lesson":"The octave-low Zyn PAD mismatch came from conflating spectral table root with note playback frequency. `spectrum root` must own table/base frequency, while `freq` owns the played note. Using Zyn's sample basefreq 77.7813 with playback freq 261.6256, and removing gratuitous spread/vibrato, improved the PAD report to log-mel 0.353365, envelope 0.348752, RMS ratio 0.97283, centroid ratio 0.999243, score 0.612832.","evidence":"PatchScript now preserves spectrum freq as voice note frequency; PatchScriptTests.SpectralBankSeparatesTableRootFromPlaybackFrequency covers the invariant; artifacts/parity/zyn-pad-reference/report.txt records the improved score."}
|
|
{"date":"2026-05-15","area":"zyn-pad-parity","lesson":"Aqua's remaining detuned impression was caused by stacking same-note PAD spectral voices. Collapse body/high content into one coherent spectral table before adding layers for richness. A simple gain trim then brought loudness into line: RMS ratio 1.001704, centroid ratio 1.004072, score 0.6211.","evidence":"BuiltInScripts.ZynStylePadTexture now uses one active PAD spectrum with partials 1, 1.5, and 2 plus patch gain 1.1; artifacts/parity/zyn-pad-reference/report.txt records the focused render."}
|
|
{"date":"2026-05-15","area":"zyn-pad-fixtures","lesson":"More PAD fixtures immediately exposed which pressure is real: `pad-pure` and old `pad-texture` render identically through Zyn, so the filter/category XML in `pad-texture` was not live oracle behavior. `pad-harmonic` changes table and note output through explicit OSCIL harmonics and should be the next PAD parity rung.","evidence":"tests/AquaSynth.Dsl.Tests/Fixtures/ZynAddSubFX/ProjectAuthored/pad-pure.xiz and pad-harmonic.xiz plus artifacts/parity/zyn-pad-fixtures/report.txt."}
|
|
{"date":"2026-05-15","area":"zyn-upstream-gpl-bank","lesson":"GPL Zyn presets are acceptable as test-only feedstock. The upstream instrument submodule at `external/zynaddsubfx/instruments` commit c5c912131b31df5fdf372d2f06a25aaf2375837f provides 1318 `.xiz` files; survey and PAD render tests write ignored reports/WAVs while the NuGet boundary still excludes `.xiz`, `external/`, and artifacts.","evidence":"ZynInstrumentTests.SurveysUpstreamGplInstrumentBankWhenAvailable and ZynReferenceParityTests.ZynPadReferenceRendererSurveysUpstreamGplPadFixturesWhenBuilt; focused Zyn tests passed 14/14."}
|
|
{"date":"2026-05-15","area":"zyn-artifact-layout","lesson":"Zyn PAD listening artifacts now follow the DX7 parity shape: per-synth timestamped run folders with Zyn reference WAVs, source-table WAVs, `report.txt`, and `candidate.aqua`. Upstream GPL PAD runs write `candidate-aquasynth.wav`; this was initially the current ZynStylePadTexture baseline and is now superseded by generated per-preset PAD rebuilds.","evidence":"ZynReferenceParityTests focused run passed 4/4 and wrote folders such as artifacts/parity/zyn-upstream-pad-fixtures/0121-ghost-ensemble-20260515T072330036."}
|
|
{"date":"2026-05-15","area":"zyn-pad-translation","lesson":"Zyn PAD artifacts now use per-preset generated `.aqua` instead of the generic baseline. `ZynInstrumentReader.RebuildFirstPadAsAquaSynthScript` translates the first enabled PAD kit item into one named PAD layer plus a `spectrum` bank using OSCIL harmonic magnitudes, Zyn oracle sample `basefreq` as table root, PAD volume as layer gain, and simple rate/level envelope scaffolding. Reports explicitly list missing Zyn semantics: bandwidth/profile spreading, harmonic profile shaping, and filter envelope/LFO lowering.","evidence":"ZynInstrumentTests.RebuildsProjectAuthoredPadAsAquaSynthSpectrumScript plus focused Zyn tests passed 13/13; latest upstream PAD reports include generated candidate scripts and log-mel scores from ~0.276 to ~0.637."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-profile-table-semantics","lesson":"Zyn PAD bandwidth/profile/position fields belong on SpectralBank as table-generation data, not in parity side channels. Mapping those fields and Zyn's exponential PAD volume curve improved gain/envelope evidence, but profile math alone did not solve log-mel parity.","evidence":"Focused Zyn tests passed 13/13 after adding PadSpectrumProfile and zyn_* script fields; upstream PAD batch still has log-mel roughly 0.34-0.69 depending on fixture."}
|
|
{"date":"2026-05-15","topic":"zyn-oscilgen-approximation","lesson":"Expanding a subset of Zyn OscilGen base_function plus spectrum_adjust is conceptually the right owner for one-harmonic PAD presets, but the first approximation is mixed and must not be treated as solved parity.","evidence":"Soft Pad log-mel improved to 0.342738 and Organ Choir Pad2 to 0.573216, while sin2x pad regressed to 0.524421, DoublePadBass to 0.689315, and Ghost Ensemble to 0.482155. Next cut needs more OscilGen semantics or gating."}
|
|
{"date":"2026-05-15","topic":"zyn-oscilgen-stage-order","lesson":"Zyn OscilGen partial extraction should only run the sampled waveform pipeline when oscillator processing stages are live; otherwise direct harmonics stay readable and capped. A broad base-function expansion made some presets worse without earning its complexity.","evidence":"After adding sampled filter/waveshape/modulation stage order and restoring a capped direct path, sin2x pad improved to log-mel 0.455193, while Soft Pad stayed 0.342738 and Ghost stayed 0.40922. DoublePadBass and Organ Choir remain poor, so this is an incremental rung, not parity."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-kit-layering","lesson":"Do not treat first enabled PAD kit item as a Zyn instrument when kit_mode is multi-kit. Multi-kit PAD presets need per-kit table roots and layered Aqua spectrum banks, or parity artifacts compare against an amputated preset.","evidence":"DoublePadBass has kit_mode=1 with enabled PAD kit items 0 and 1. Rebuilding/summing both moved log-mel from about 0.655 to 0.493 and generated doublepadbass_0 plus doublepadbass_1. Raising the volume cap to 3.0 worsened log-mel to 0.521 and was cut."}
|
|
{"date":"2026-05-15","topic":"zyn-ghost-base-function","lesson":"A direct-harmonic readability gate must not erase source identity. Ghost Ensemble needed power-base OscilGen expansion even without downstream oscillator stages; otherwise it collapsed toward a generic two-partial pad.","evidence":"Ghost Ensemble has base_function=4 with two explicit harmonics. Expanding power-base multi-harmonic sources changed the candidate from two partials to 32 partials and improved score to 0.446977, with log-mel 0.402789."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-static-filter","lesson":"Zyn PAD static global filter frequency is audible layer-balance authority, not optional decoration. Read nested FILTER params under FILTER_PARAMETERS and lower old Zyn cutoff values through the exponential FilterParams curve, not a linear freq/127 guess.","evidence":"DoublePadBass kit0 filter freq=12 and kit1 freq=61. Linear mapping gave lpf=0.094488/0.480315 and still sounded like all kazoo. Zyn's curve maps them to lpf=0.003325/0.047225, improving log-mel to 0.334546 and making the generated patch deep-bass-first. Filter envelopes/LFOs and level recovery remain missing pressure."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-detune-and-filter-order","lesson":"Zyn PAD note frequency is not just the requested note plus table root; FREQUENCY_PARAMETERS coarse/fine detune are live playback authority, and analog LP2 needs a steeper low-pass than AquaSynth's old one-pole default.","evidence":"DoublePadBass has coarse_detune=15360, which Zyn getdetune wraps from octave 15 to -1 octave. Emitting spectrum freq=130.8128 instead of 261.6256 and lpf_order=2 moved DoublePadBass log-mel from 0.334546 after static cutoff mapping to 0.259298; remaining gap is RMS/envelope."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-filter-envelope","lesson":"Zyn PAD FILTER_ENVELOPE is audible transient authority. Static cutoff parity can get the tone right while still missing the opening hit; AquaSynth needs explicit low-pass cutoff envelopes with nonzero start levels.","evidence":"DoublePadBass sounded tonally right but softer at onset. Mapping Zyn ADSR-filter octave offsets into lpf_env=rl with lpf_start improved log-mel from 0.259298 to 0.241993, envelope distance from 0.631427 to 0.554658, RMS ratio from 0.390177 to 0.456173, and score from 0.370218 to 0.404382."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-output-calibration","lesson":"After PAD table roots, detune, filter order, filter envelope, and logarithmic envelope times are mapped, remaining Zyn PAD loudness can be a generated-rebuild output calibration rather than another per-layer fixture tweak.","evidence":"Current PAD fixture RMS ratios before calibration were consistently low: DoublePadBass 0.511669, Soft Pad 0.619347, Organ Choir 0.588127, Ghost 0.730155, sin2x 0.775653. Emitting patch gain=1.6 moved DoublePadBass candidate WAV peak to 0.979 against clipped Zyn reference peak 1.0, envelope distance to 0.226563, RMS ratio to 0.818669, and score to 0.631168 while keeping batch RMS plausible."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-filter-q","lesson":"Zyn PAD analog filter Q is real filter damping authority and belongs as a general AquaSynth filter surface (`lpf_q`), not as a fixture-specific cutoff/gain fudge.","evidence":"Ghost Ensemble has FILTER freq_track=97 and q=28. Adding note-tracked cutoff lowered Ghost lpf from 0.369706 to 0.282776 and adding explicit lpf_q=0.499021 moved log-mel from 0.38424 to 0.375637 and RMS ratio from 1.155288 to 1.09995. DoublePadBass remained acceptable and improved to log-mel 0.247729 / score 0.650069 after Q."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-q-order-cascade","lesson":"Explicit low-pass Q must not erase low-pass order. When a reference filter has both damping and slope, Faust lowering should cascade resonant stages according to `lpf_order` rather than replacing the filter with one generic resonant low-pass.","evidence":"Ghost Ensemble still sounded bright in the middle after lpf_q. Cascading resonlp stages for lpf_order=4 moved Ghost log-mel from 0.375637 to 0.369402 and RMS ratio from 1.09995 to 1.054875 while keeping DoublePadBass near its accepted score: log-mel 0.247748, score 0.650029. ZynPadReference harmonic dumps showed Ghost's first 32 imported OscilGen partial ratios already matched Zyn, so this was filter slope, not first-page harmonic extraction."}
|
|
{"date":"2026-05-15","topic":"zyn-oscil-filter-index","lesson":"Zyn OscilGen oscillator filter functions use one-based harmonic indices. Do not translate them through a zero-based AquaSynth index; that moves spectral features to the wrong partial and can make a preset sound like the wrong overtone is being emphasized.","evidence":"sin2x uses oscillator filter type 13. With zero-based indexing, AquaSynth put the spike on h3 and had centroid ratio 1.227953. After preserving Zyn's one-based index, candidate partials are h2-dominant, centroid ratio improves to 0.998145, log-mel moves from 0.491437 to 0.479782, and UpstreamSin2xOscilFilterKeepsSpikeOnSecondHarmonicWhenAvailable asserts h2 > h3 * 10."}
|
|
{"date":"2026-05-15","topic":"zyn-organ-highpass-selected-root","lesson":"Organ Choir's coherent octave blast needs real Zyn PAD high-pass ownership and selected table roots for OscilGen shift-base sources, but selected roots must not become the global default. The source rule is narrow: keep sample-0 roots unless the PAD OscilGen base function is the shift source (`base_function=7`) and the oracle provides the selected note table root.","evidence":"Organ Choir kit0 has analog HP2 with stages and FILTER_ENVELOPE, while kit1 uses base_function=7. Mapping hpf_order/hpf_env and using the selected 622.25 Hz table root only for kit1 moved the candidate's dominant peak to 522.67 Hz with 261 Hz at -1.29 dB, close to Zyn's 523.33 Hz lead and 261 Hz at -2.23 dB. Latest Organ log-mel is 0.499122 / score 0.51966, while accepted Soft Pad, Ghost, and DoublePadBass remain on sample-0 roots; global selected roots had regressed DoublePadBass."}
|
|
{"date":"2026-05-15","topic":"zyn-organ-basefunc-mod-adaptive","lesson":"Organ Choir's violin-vs-wind mismatch was OscilGen source-table ownership, not pitch, envelope, or gain. Zyn `base_function_modulation` warps the phase before base-function sampling, and `adaptive_harmonics` remaps the prepared oscillator spectrum at the PAD table root; both must happen before PAD bandwidth/profile spreading.","evidence":"Before the fix, Aqua kit1 partials formed a smooth ramp (h3 -3.5 dB, h4 -5.1 dB, h8 -10.2 dB relative to h1) while Zyn's harmonic dump was sparse (h3 -27.1 dB, h4 -70.3 dB, h8 -50.2 dB). Applying base_function_modulation=1 and adaptive_harmonics=1 moved kit1 table energy to 400-800 Hz 0.2713 vs Zyn 0.2780 and 8-16 kHz 0.1471 vs Zyn 0.1355; Organ log-mel improved to 0.471483 and score to 0.541933 without changing accepted DoublePadBass, Ghost, or Soft Pad."}
|
|
{"date":"2026-05-15","topic":"zyn-pad-ear-vs-logmel","lesson":"For sustained Zyn PAD fixtures, log-mel distance can remain pessimistic after the perceptual target has been reached. Keep it as a regression and triage signal, but do not keep grinding accepted fixtures solely to chase a DX7-like numeric threshold when listening and structural source-table evidence agree.","evidence":"After mapping selected roots, HP filter motion, Q/order cascades, one-based OscilGen filter indices, base-function phase modulation, and adaptive harmonics, the user accepted DoublePadBass, Ghost Ensemble, Soft Pad, Organ Choir, and the other recent community PAD fixtures by ear. Organ Choir still reports log-mel 0.471483 despite direct kit1 table energy matching the Zyn body/air balance and the listener judging all fixtures equivalent."}
|
|
{"date":"2026-05-16","topic":"pad-syntax-generalization","lesson":"Reference-synth names must not become canonical AquaSynth syntax or public patch-model vocabulary. Importers may translate Zyn controls, and parser aliases may keep old parity artifacts readable, but generated/authored `.aqua` should use AquaSynth-native `pad_*` terms for general spectral-table intent.","evidence":"Zyn PAD parity had produced generated scripts with `zyn_mode`, `zyn_bandwidth`, `zyn_bwscale`, `zyn_profile`, and `zyn_position`, plus public model names like `ZynHarmonicProfile`. The generalization pass changed generated scripts to `pad_mode`, `pad_bandwidth`, `pad_bwscale`, `pad_profile`, and `pad_position`, renamed the public profile/position records and enums to PAD-native names, preserved legacy `zyn_*` parser aliases, and passed `dotnet test AquaSynth.sln --no-restore` with 108 tests."}
|
|
{"date":"2026-05-16","topic":"project-rename-aquasynth","lesson":"The C# synth repo is now AquaSynth and the Rust reference branch is AquaSynth-rs. Keep repo wiring, package metadata, namespaces, solution/project names, env vars, docs, and state aligned to AquaSynth; do not reintroduce AquariumSynthCSharp/AquariumSynth.Dsl names.","evidence":"Renamed solution to AquaSynth.sln, projects to src/AquaSynth.Dsl and tests/AquaSynth.Dsl.Tests, namespaces/package to AquaSynth.Dsl, package version suffix to 0.1.0-aquasynth.1, DX7 env var to AQUASYNTH_DX7_PYTHON, and origin to https://github.com/GameCult/AquaSynth.git. Verified `dotnet build AquaSynth.sln --no-restore`, `dotnet test tests\\AquaSynth.Dsl.Tests\\AquaSynth.Dsl.Tests.csproj --no-build -v minimal` with 108 passed, and `dotnet pack src\\AquaSynth.Dsl\\AquaSynth.Dsl.csproj -c Release --no-restore` producing AquaSynth.Dsl.0.1.0-aquasynth.1.nupkg."}
|
|
{"date":"2026-05-16","topic":"zyn-coverage-map","lesson":"Zyn coverage must distinguish handled parity-backed behavior, counted pressure, and unknown subtypes. Broad parse success is inventory, not expressivity. The upstream GPL bank currently parses 1318/1318 files and yields 1459 enabled kit items / 63 layered instruments; PAD coverage is strongest, while ADD, SUB, active LFO routing, free envelopes, formant motion, effects, non-analog PAD filters, and several PAD OscilGen filter/waveshaper subtypes remain workout buckets.","evidence":"Added `ZynCoverageStatus`, `ZynCoverageBucket`, `ZynCoverageReport`, `ZynInstrumentSurvey.CoverageDirectory`, and `CoverageMarkdown`; `SurveysUpstreamGplInstrumentBankWhenAvailable` writes `artifacts/parity/zyn-upstream-bank-survey/coverage.md`. Focused ZynInstrumentTests passed 13/13."}
|
|
{"date":"2026-05-16","topic":"zyn-pad-state-variable-filter","lesson":"Zyn PAD state-variable low-pass/high-pass filters are not a new Aqua authority. Category 2 type 0/1 maps cleanly onto existing `lpf`/`hpf` cutoff, Q, and order fields because Zyn `SVFilter` exposes low/high outputs and cascades `stages + 1`. Category 2 type 2/3 are band-pass/notch and must remain unknown until AquaSynth has a real band/notch filter owner.","evidence":"Mapped PAD filter `cat=2 type=0/1` in `ZynInstrumentReader`, moved those coverage buckets to handled, and added `RebuildMapsZynStateVariablePadLowPassToAquaFilterAuthority`. Focused ZynInstrumentTests passed 14/14."}
|
|
{"date":"2026-05-16","topic":"native-bandpass-notch","lesson":"Band-pass and notch are ordinary AquaSynth filter authorities, not Zyn weirdness. `Filter` now owns `bpf`/`bpf_q`/`bpf_order` and `notch`/`notch_q`/`notch_order`; Zyn PAD analog and state-variable BPF/notch filters lower into those fields. Formants remain vowel/body color and PAD spectrum remains source-table construction.","evidence":"Added parser/model/Faust support for native BPF/notch, mapped Zyn PAD `cat=0 type=4/5` and `cat=2 type=2/3`, and added PatchScript plus ZynInstrument tests. Focused PatchScript/ZynInstrument tests passed 71/71."}
|
|
{"date":"2026-05-17","topic":"faust-toolchain-boundary","lesson":"AquaSynth should own patch-to-DSP compilation products, including Faust toolchain selection, target options, cache identity, manifests, diagnostics, provenance, and dynamic patch compilation outside the realtime callback. Aquarium Engine should request or load finished artifacts and host them, not own the meaning of patch compilation.","evidence":"User confirmed Aquarium currently owns dynamic patch compilation but that this belongs in AquaSynth so Aquarium can plug into it. Added `docs/faust-toolchain-boundary.md`, reframed README C# output as authoring/test lane, and updated doctrine/state to split Aqua compile authority from Aquarium realtime hosting."}
|
|
{"date":"2026-05-17","topic":"native-faust-runtime-ownership","lesson":"AquaSynth now owns Aquarium's former native Faust audio-rendering internals: toolchain discovery/loading, script parsing, Faust emission, compile identity, DSP source artifact writing, native Faust factory lifetime, manifests, duration estimation, and offline sample-buffer rendering. Engine hosts should schedule and play completed products instead of knowing synth internals.","evidence":"Added `AquaSynthNativeCompiler`, `AquaSynthCompiledPatch`, `AquaSynthNativeManifest`, and native Faust smoke tests. Aquarium's `AquariumSynthHost` was cut down to scheduling/debounce/status/cache/WASAPI playback and now consumes `AquaSynth.Faust`."}
|
|
{"date":"2026-05-17","topic":"package-split-core-faust","lesson":"AquaSynth package names now follow ownership: `AquaSynth.Core` owns patch meaning, parser/model, analysis, presets, and Faust source emission; `AquaSynth.Faust` depends on Core and owns Faust CLI/native toolchain interaction, compile products, manifests, factory lifetime, and rendering. Do not revive a catch-all `.Dsl` package for runtime-facing behavior.","evidence":"Moved the old `AquaSynth.Dsl` project to `src/AquaSynth.Core`, added `src/AquaSynth.Faust`, moved `FaustCompiler` and `NativeFaustRuntime` to the Faust package, and updated package-boundary tests to pack both packages."}
|
|
{"date":"2026-05-18","topic":"render-session-ownership","lesson":"`AquaSynthRenderSession` is only an offline render-proof convenience. Engine hosts should use `AquaSynthPatchCompiler` for live compiled products and should not hold a render session as their Faust authority.","evidence":"Added `AquaSynthPatchCompiler` to AquaSynth.Faust, made `AquaSynthRenderSession` wrap it, and moved AquariumSynthHost from a live render session to the compiler surface."}
|
|
{"date":"2026-05-17","topic":"package-versioning","lesson":"Use normal SemVer prerelease labels for AquaSynth packages. Do not encode the repo name into the version suffix; `0.1.0-alpha.N` is a real prerelease version, while `0.1.0-aquasynth.N` is project metadata cosplay.","evidence":"Renamed AquaSynth.Core and AquaSynth.Faust package versions from `0.1.0-aquasynth.2` to the `0.1.0-alpha.N` line before repacking Aquarium's local feed."}
|
|
{"date":"2026-05-17","topic":"solution-format","lesson":"AquaSynth uses a normal Visual Studio `.sln` solution because Rider does not reliably like `.slnx`. Keep tests, state, and docs looking for `AquaSynth.sln`, not `AquaSynth.slnx`.","evidence":"Generated `AquaSynth.sln` with `dotnet new sln --format sln`, added Core/Faust/tests projects, removed `AquaSynth.slnx`, and replaced solution references across tests/state."}
|
|
{"date":"2026-05-17","topic":"zyn-formant-motion","lesson":"AquaSynth now owns a first vowel-frame motion surface instead of treating Zyn formants as static filters or loose counted pressure. Voice `vowels=` stores `|`-separated formant banks and `vowel_hz` scans them; Zyn `FORMANT_FILTER` sequences can seed this, while exact Zyn cutoff-position driving, formant slowness, and vowel clearness remain named pressure.","evidence":"Added `FormantFrame`, voice `FormantFrames`/`FormantFrameRateHz`, parser support for `vowels=`/`vowel_hz`, Faust cyclic frame blending, and `ZynInstrumentReader.RebuildFirstFormantMotionAsAquaSynthScript`. `UpstreamWideBassExportsFormantMotionWorkoutWhenAvailable` exercises `Companion/0056-Wide Bass.xiz`; focused PatchScript/ZynInstrument tests passed 73/73 and non-reference tests passed 103/103."}
|
|
{"date":"2026-05-17","topic":"zyn-formant-parity-fixtures","lesson":"The first formant-motion parity workout needs multiple multi-frame ADD/formant fixtures and a real Zyn ADD note oracle. Avoid letting drum-kit envelope/source failures masquerade as formant evidence. Use Wide Bass, Ghost Ensemble, and Ghost Choir as the initial chorus; all currently fail enough to be useful.","evidence":"Added test-only `tools/zyn-reference/ZynVoiceReference.cpp`, wired it into the MSYS reference build, and added `ZynVoiceReferenceRendererSurveysUpstreamFormantFixturesWhenBuilt`. The batch writes ignored artifacts under `artifacts/parity/zyn-upstream-formant-fixtures/`; baseline scores were Wide Bass 0.280990, Ghost Ensemble 0.312813, Ghost Choir 0.363644. The native Zyn reference build succeeded and the focused formant fixture test passed."}
|
|
|
|
|
|
{"date":"2026-05-19","evidence":"Added docs/ipa-vocal-tract-roadmap.md with staged IPA support from tokenization/vowels through pulmonic consonants, expanded IPA, airstream/phonation, and Weksa alien morphologies; linked it from docs/reference-synth-roadmap.md and state.","lesson":"AquaSynth should treat IPA as an authoring input for phonetic intent, not as the internal synth model. The planned machine is tokenizer -\u003e feature mapper -\u003e phonology profile -\u003e gesture planner -\u003e morphology -\u003e tract plan -\u003e Faust renderer, growing supported IPA only as tract/excitation physics earn each category.","topic":"ipa-vocal-tract-roadmap"}
|
|
{"date":"2026-05-19","topic":"vocal-tract-boundary-contracts","lesson":"Defend the Weksa/AquaSynth tract boundary with three real bones: PhoneticIntent for language-owned phones/features/timing, ArticulatoryPlan for AquaSynth-owned gesture realization, and ArticulatoryConstraintReport for host-visible anatomy vetoes. Morphology capabilities must reject impossible phones such as bilabials for a beaked speaker instead of silently substituting liar-slurry.","evidence":"Added VocalTractModel.cs contracts and VocalTractModelTests.cs coverage for inspectable Weksa intent, bilabial veto on a beaked morphology, and acceptance on a human baseline; updated audio doctrine and IPA roadmap boundary section."}
|
|
{"date":"2026-05-19","evidence":"Added VocalTractPlanner.Plan, VocalTractPlanResult, VocalTractHostReaction, rejection coverage for /pa/ against a beaked morphology, and accepted /a/ coverage for the human baseline gesture path.","lesson":"The first vocal-tract proof artifact is VocalTractPlanResult: host-visible branching around one intent and one morphology. Rejected morphology constraints carry diagnostic codes and no plan; accepted vowel intents emit inspectable glottal-source and tract-area gestures before any renderer exists.","topic":"vocal-tract-plan-result-proof"}
|
|
{"date":"2026-05-19","evidence":"Added EspeakNgReferenceTests with optional renderer discovery, tiny fixtures for a/pa/ta/ka/sa/ma, WAV artifact/report generation under artifacts/parity/espeak-ng-ipa-workout, and docs/state entries naming eSpeak as intelligibility/timing pressure only.","lesson":"The first vocal-tract parity workout uses optional eSpeak NG as a development speech reference, not an anatomy oracle. The lane renders tiny speech fixtures and captures eSpeak IPA transcription/audio features when ESPEAK_NG or espeak-ng is available, while normal builds skip cleanly when it is absent.","topic":"espeak-ng-ipa-workout"}
|
|
{"date":"2026-05-19","evidence":"Updated EspeakNgReferenceTests to record log_mel_frames, log_mel_bands, log_mel_mean, and log_mel_distance_matrix in report.md; updated the IPA vocal tract roadmap accordingly.","lesson":"The eSpeak NG speech workout should expose log-mel evidence immediately, not just basic audio features. Each fixture report now carries normalized log-mel band means plus a cross-fixture log-mel distance matrix so future AquaSynth IPA renders can plug into the same spectral comparison shape.","topic":"espeak-ng-logmel-workout"}
|
|
{"date":"2026-05-19","topic":"vocal-tract-learned-controller","lesson":"AquaSynth now has a small learned controller scaffold for the vocal-tract lane: phonetic features plus a semantic embedding vector feed a multilayer tanh/sigmoid MLP trained with SGD/backprop to predict tract controls plus AM/FM, LFO, filter, and mel spectral-envelope expression lanes. This is a trainable controller surface, not proof of eSpeak-level speech yet.","evidence":"Added VocalTractLearning.cs and VocalTractLearningTests.cs with feature encoding, semantic embeddings, 3-layer default network, loss-reduction tests, same-phone semantic steering, expressive modulator/filter control tests, and learned dark/bright mel-envelope steering for PAD-style spectral-table coloration."}
|
|
{"date":"2026-05-19","topic":"vocal-tract-optimizer-hot-path","lesson":"The first learned vocal-tract optimizer should stay native and inspectable until the render-loss boundary proves it needs a tensor framework. The trainer now uses packed row-major weight buffers, owned scratch activation/delta/target buffers, unsafe pointer loops, reusable gradient/moment buffers, batched gradients, deterministic shuffling, and Adam by default instead of allocation-heavy per-example jagged-array SGD.","evidence":"Rebuilt VocalTractLearning.cs hot path around flat float arrays and unsafe loops; enabled unsafe blocks in AquaSynth.Core; VocalTractLearningTests pass against the packed-buffer Adam trainer."}
|
|
{"date":"2026-05-19","topic":"utterance-embedding-learning-boundary","lesson":"AquaSynth should own gradient descent for Weksa speech handoff. Weksa supplies speech text embeddings, prosody/emphasis hints, and Ghostlight/Epiphany-shaped character state vectors; AquaSynth trains the tiny utterance-embedding encoder and passes that embedding into the synth-driver model.","evidence":"Extracted PackedNeuralNetwork as the shared packed-buffer Adam/SGD primitive, rewired VocalTractNeuralMapper through it, and added UtteranceEmbeddingInput/UtteranceEmbeddingNeuralEncoder plus tests for packing, training, and feeding the vocal-tract semantic embedding."}
|
|
{"date":"2026-05-19","topic":"espeak-gradient-descent-fixture","lesson":"The first speech-learning fixture should train on generated eSpeak evidence before pretending AquaSynth has waveform-loss vocal-tract backprop. eSpeak log-mel means can supervise both utterance embedding targets and synth-driver mel/control lanes, giving the packed optimizer real generated speech pressure while the renderer is still catching up.","evidence":"Added EspeakNgGradientDescentTests. When ESPEAK_NG or espeak/espeak-ng is available, it renders a/pa/ta/ka/sa/ma, extracts log-mel means, trains UtteranceEmbeddingNeuralEncoder, trains VocalTractNeuralMapper against eSpeak-seeded control targets, asserts loss reductions, and writes artifacts/parity/espeak-ng-gradient-descent/<timestamp>-tiny/training-report.md."}
|
|
{"date":"2026-05-19","topic":"speech-pipeline-chained-backprop","lesson":"The speech-learning path now has real chained backprop between the utterance encoder and synth driver. The packed network can return gradients with respect to its input, so downstream synth-driver loss can update the upstream utterance encoder instead of training the two models as separate supervised islands.","evidence":"Added PackedNeuralBackpropagation, TrainSingle/TrainSingleFromOutputGradient, SpeechBackpropagationPipeline, and SpeechBackpropagationPipelineTests; updated the eSpeak gradient fixture to train the utterance encoder from synth-driver loss rather than from a separate compressed-mel target."}
|
|
{"date":"2026-05-19","topic":"faust-rendered-speech-loss","lesson":"For speech learning, Core should accept external synth-output gradients while Faust owns rendered loss evaluation. Finite-difference gradients over controller outputs are honest black-box renderer pressure, but too slow for default tests until render compilation is cached or proxied.","evidence":"Added SpeechBackpropagationPipeline.TrainSingleFromSynthOutputGradient and FaustRenderedSpeechLossSurface. The opt-in AQUASYNTH_RUN_FAUST_SPEECH_LOSS=1 proof renders reference and candidate speech targets through Faust, compares log-mel evidence, and returns a finite-difference output gradient for backpropagation through the learned chain."}
|
|
{"date":"2026-05-19","topic":"compiled-faust-speech-loss-surface","lesson":"The usable speech loss surface should compile topology once and vary every neural mapper output through exported Faust controls. Batch rendering through a native compiled factory makes finite-difference and curriculum learning plausible; recompiling per candidate is only a proof scaffold.","evidence":"Added native Faust UI control discovery/set support, AquaSynthCompiledPatch.Render(controlValues), and CompiledFaustRenderedSpeechLossSurface with speech/output/N knobs for all mapper outputs. The opt-in proof renders multiple candidates through one compiled patch and caught the need to clamp dynamic filter cutoff below Nyquist."}
|
|
{"date":"2026-05-19","topic":"cultcache-sound-claim-cards","lesson":"Serious AquaSynth sound claims should be distributed as typed data beside the patch database. Patch and speech claim cards must name the reference/source, intent, tier, proof artifact, latest listening receipt surface, metrics, and known lies; stock sketches stay in the database but should not masquerade as parity without receipts.","evidence":"Added CultCachePatchDocument types, patches/aquasynth-patch-cultcache.json, and tests that load the typed document, check patch database count against library.yaml, and require every ReferenceRebuildCatalog entry to have a claim card."}
|
|
{"date":"2026-05-19","topic":"cultcache-cc-artifact-boundary","lesson":"AquaSynth must not impersonate CultCache persistence. The sound-claim fixture should be a real .cc CultCache store produced and consumed through CultLib; AquaSynth owns typed sound-claim meaning, while CultLib owns serialization, schema cataloging, record keys, and MessagePack backing-store mechanics.","evidence":"Deleted the local CultCacheBinaryCodec, replaced the JSON cache artifact with patches/aquasynth-patch-cultcache.cc, added a GameCult.Caching.MessagePack project reference, and updated CultCachePatchDocumentTests to load the fixture through CultCachePatchDocumentStore.ReadAsync."}
|
|
{"date":"2026-05-19","topic":"distributed-speech-training-cache-contract","lesson":"The speech-learning machine should distribute expensive render evidence instead of renderer authority. AquaSynth emits typed speech render requests, Faust workers write typed score results, and the trainer consumes synced gradients to update the utterance encoder and synth driver; CultCache/CultMesh carry the documents between machines.","evidence":"Added SpeechDistributedTraining.cs with SpeechRenderRequest, SpeechRenderResult, SpeechTrainingCheckpoint, CultCache store helpers, and a coordinator proof. SpeechDistributedTrainingTests round-trip request/result/checkpoint .cc stores and prove synced score gradients reduce local pipeline loss."}
|
|
{"date":"2026-05-20","topic":"utterance-parity-current-objective","lesson":"AquaSynth's active objective is now the utterance parity curriculum: structured utterance metadata lowers into a learned utterance embedding, then into learned synth automation for the vocal tract and associated envelopes/LFOs/filters/spectral lanes, then into rendered speech loss. Broad DX7/Zyn synth digestion is backburner work unless it directly improves this harness.","evidence":"Updated README, docs/audio-doctrine.md, docs/reference-synth-roadmap.md, docs/ipa-vocal-tract-roadmap.md, state/map.yaml, state/spine.yaml, and state/memory.json to make the speech parity harness the current center."}
|
|
{"date":"2026-05-20","topic":"utterance-parity-prior-work","lesson":"Prior work supports AquaSynth's architecture when kept in its lane: Kelly-Lochbaum/Pink Trombone and Story area functions support tract/area authority; TADA/articulatory phonology supports overlapping gestures; eSpeak/Klatt-style formant synthesis is useful fast ground truth but not anatomy; DDSP/neural source-filter work supports learned controllers over interpretable DSP rather than black-box throat replacement.","evidence":"Added docs/utterance-parity-research.md with source ledger covering Pink Trombone, VocalTractLab, Story, TADA, eSpeak NG, PanPhon, PHOIBLE, DDSP, DDSP articulatory vocoders, neural source-filter models, and LF voice-source references."}
|
|
{"date":"2026-05-20","topic":"speech-training-time-witness","lesson":"Speech training receipts need time and confidence as evidence, not only loss. Each curriculum step should record when the stage decided, observed latency, intended latency budget, confidence, and artifact/model identifiers; a good-sounding result from an unbounded clockless path is not trustworthy.","evidence":"Added SpeechTimingReceipt to SpeechRenderRequest, SpeechRenderResult, and SpeechTrainingCheckpoint; seeded timing/confidence receipts in the local distributed-training proof; updated audio doctrine, IPA roadmap, utterance parity research notes, spine, and memory."}
|
|
{"date":"2026-05-20","topic":"weksa-utterance-embedding-contract","lesson":"Do not start serious AquaSynth speech gradient descent from toy Weksa vectors, and do not treat semantic text embeddings as IPA embeddings. The coordinated Weksa handoff contract is `weksa.utterance_embedding_handoff.v0.1`: 1024 `bge-m3:latest` semantic speech-text floats, variable-length PanPhon sequence evidence, 256 AquaSynth-owned phonetic-realization floats produced by `aquasynth.panphon_sequence_encoder.v0.1`, 32 prosody/emphasis floats, 64 projected character-state floats, and a 64-float AquaSynth-owned utterance embedding output.","evidence":"Updated E:/Projects/weksa docs/schema/state to split speech text embedding from PanPhon sequence evidence and marked the existing Nibu toy fixture as non-training; mirrored the training block in AquaSynth IPA roadmap, utterance parity research notes, spine, and memory."}
|
|
{"date":"2026-05-20","topic":"panphon-sequence-encoder-organ","lesson":"The 256D phonetic realization surface is now an AquaSynth-owned learned organ, not fixed phone slots. Weksa supplies variable-length PanPhon feature sequences; AquaSynth encodes them through a trainable phonetic sequence encoder before the utterance embedding encoder consumes the 256D result.","evidence":"Added PhoneticSequenceEncoding.cs with PanPhon feature frames, deterministic sequence sketching, PhoneticSequenceNeuralEncoder, training records, and tests proving the encoder learns compact PanPhon realization embeddings."}
|
|
{"date":"2026-05-20","topic":"weksa-v01-training-artifact","lesson":"The Weksa blocker has moved from schema definition to artifact consumption. Weksa now emits a machine-readable `weksa.utterance_embedding_handoff.v0.1` tiny PanPhon seed batch for `a`, `pa`, `ta`, `ka`, `sa`, and `ma`; AquaSynth's next serious training pass should load that artifact rather than local toy vectors.","evidence":"Added Weksa emitter `E:/Projects/weksa/tools/emit_tiny_panphon_handoffs.py` and generated `E:/Projects/weksa/examples/speech-training/tiny-panphon-v0.1/batch.json` with fixed 1024/32/64 input widths, inline PanPhon 22-feature frames, and pending AquaSynth-owned 256/64 learned outputs."}
|
|
{"date":"2026-05-24","topic":"cultmesh-speech-worker-authority","lesson":"CultMesh should distribute speech render/scoring work, not optimizer authority. AquaSynth emits typed SpeechRenderRequest documents; CultMesh delivers compiled Faust renderers, scoring code, small model/encoder assemblies, and batch/artifact refs to compatible leased workers; workers return SpeechRenderResult documents with loss, gradients, artifacts, and timing receipts. The authority trainer or shard-primary applies gradients through SpeechBackpropagationPipeline and commits SpeechTrainingCheckpoint documents through normal CultCache/CultMesh shard authority.","evidence":"Recorded the authority map in docs/ipa-vocal-tract-roadmap.md, state/spine.yaml, state/map.yaml, state/memory.json, and state/scratch.md. The next implementation layer is transport, admission, worker leases, payload delivery, and result collection; federated averaging waits until the simple authority path is boring."}
|
|
{"date":"2026-05-24","topic":"cultmesh-speech-training-step","lesson":"AquaSynth can now run the first honest CultMesh-distributed speech training step: an authority trainer emits SpeechRenderRequest documents and a SpeechWorkerPayloadManifest, admits only CultMesh peers with valid speech-render-worker leases, records SpeechWorkerAdmissionReceipt documents for admitted/rejected peers, lets admitted workers produce SpeechRenderResult gradients, and applies those gradients centrally through SpeechBackpropagationPipeline. Workers still do not write checkpoints.","evidence":"Added GameCult.Mesh to AquaSynth.Core, added payload/admission/assignment/training-step types and store helpers in SpeechDistributedTraining.cs, added RunCultMeshTrainingStep, and added a test with two leased workers plus rejected unleased/read-replica peers. Focused verification: `dotnet test tests/AquaSynth.Dsl.Tests/AquaSynth.Dsl.Tests.csproj --filter \"SpeechDistributedTrainingTests\" -v minimal`: 3 passed. Remaining infrastructure gap: real remote artifact chunk transfer and process supervision belong to CultMesh, not an AquaSynth-local workaround."}
|
|
{"date":"2026-05-25","topic":"vocal-tract-control-playground","lesson":"The current AquaSynth vocal-tract lane is touchable as a voice-patch target surface before it is a Pink Trombone-class tract simulation. A useful playground should expose the real VocalTractControlTarget knobs directly: these are the controls the learned speech driver predicts from phonetic and utterance input, not learned controls themselves. Keep the tract-ish visualization honest that the WebAudio renderer is a lab proxy rather than full waveguide anatomy.","evidence":"Added tools/vocal-tract-playground with static HTML/CSS/JS, a Node static server, WebAudio source/filter synthesis, tract canvas visualization, presets, and sliders for the 14 base voice-patch target controls plus six mel bands. Verified with `node --check` on app.js/serve.mjs, curl against http://localhost:5125/, and browser interaction: Play toggled audio, Ee preset updated controls and canvas, console errors were empty."}
|
|
{"date":"2026-05-25","topic":"speech-loss-control-authority","lesson":"Exporting `/speech/output/N` controls is not proof that the speech training surface is usable. Every base VocalTractControlTarget output must route into audible DSP before gradient descent is trusted; epsilon keep-alive references are not control authority.","evidence":"The compiled Faust speech-loss surface previously used tongue body, tongue tip, lip aperture, lip rounding, and velum only in the final keep-controls epsilon. Routed tract controls into small resonant source-filter proxies, velum into a nasal tone, LFO depth into tremolo depth, and added tests that fail when base controls are only declared/kept alive. Focused verification: `dotnet test AquaSynth.sln --no-restore --filter FaustRenderedSpeechLossSurfaceTests` passed. Full `dotnet test AquaSynth.sln --no-restore` timed out twice at 120s and 300s without a result; orphaned dotnet workers were stopped."}
|
|
{"date":"2026-05-25","topic":"pink-trombone-parity-boundary","lesson":"Pink Trombone parity must pressure AquaSynth at the tract-DSP authority, not through more source/filter proxy controls. The current DSL can expose parameters and formant/noise proxies, but it cannot exactly represent Pink Trombone's moving bidirectional waveguide graph: 44 main tract cells, 28 nasal cells, diameter-to-area reflection coefficients, velum junction, twice-rate tract stepping, positioned turbulence injection, closure transients, or exact LF glottal coefficient updates.","evidence":"Inspected `chdh/pink-trombone-mod` source (`Synthesizer.ts`, `Glottis.ts`, `Tract.ts`, `TractShaper.ts`) and added `docs/pink-trombone-parity.md`, `PinkTromboneReference`, a current non-passing AquaSynth proxy rebuild, and `PinkTromboneReferenceDeclaresMissingWaveguideAuthority` so the proxy cannot be mistaken for actual tract parity."}
|
|
{"date":"2026-05-25","topic":"tract-voice-dsl","lesson":"Pink Trombone pressure belongs on the voice as an expressive tract treatment before it becomes exact anatomy. The `tract` DSL command now lowers into `Voice.Tract`, exposes PT-shaped runtime controls, and emits a Faust tract-voice proxy; it must not be treated as a separate patch graph owner or as exact 44-cell/28-cell waveguide parity.","evidence":"Added `VocalTract` on `Voice`, `tract` parsing and field-site bindings, Faust tract proxy lowering, an updated built-in Pink Trombone proxy, parity docs/reference metadata, and a WebAudio tract playground with matching knobs. Focused tests covered parse -> model -> Faust and Pink Trombone reference declarations."}
|
|
{"date":"2026-05-25","topic":"pink-trombone-expressive-parity","lesson":"The Pink Trombone path is expressive-parity first, audio-parity second. Do not half-consume PT into one helper. Decompose its pipeline into reusable Aqua DSL primitives, then golf rendered PT fixtures with log-mel cosine similarity once the language can express the pipeline honestly.","evidence":"Added `docs/pink-trombone-dsl-parity-plan.md`, oriented parity docs/spine/map, and implemented the first primitive: `tract_shape` declarations parse into reusable `TractAreaFunction` objects that derive areas/reflection coefficients and feed `Voice.Tract` lowering. Focused tests assert shape ownership, coefficient derivation, and reference matched/missing features."}
|
|
{"date":"2026-05-26","topic":"pink-trombone-low-level-dsp-primitives","lesson":"PT parity must be targeted at the low-level DSP loop: right/left traveling-wave state, reflection coefficients, scattering junctions, nasal branch junctions, and injected excitation. AquaSynth now has reusable primitives for tract shape, glottal source, tract injection, nasal branch, and generated oral/nasal waveguide lowering; remaining gaps are true twice-rate stepping, cell-local turbulence/transient injection, target diameter slew, and rendered PT fixture scoring.","evidence":"Added `GlottalSource`, `TractInjection`, `NasalBranch`, `TractPropagationMode.Waveguide`, parser commands `glottis`, `tract_injection`, `nasal_branch`, and Faust generation for oral right/left waveguide sections plus a velum-controlled three-way nose junction. Focused verification: `dotnet build tests\\AquaSynth.Dsl.Tests\\AquaSynth.Dsl.Tests.csproj --no-restore --disable-build-servers -v minimal` and focused `dotnet test --no-build` passed."}
|
|
{"date":"2026-05-26","topic":"waveguide-cell-injection","lesson":"A positioned injection primitive is not enough; frication has to enter the traveling-wave section updates. AquaSynth waveguide lowering now computes a section-space injection cell and distributes injection pressure across oral waveguide right/left updates by position and width. Remaining PT DSP gaps are true substep execution, obstruction-history transients, diameter target slew, and rendered parity fixtures.","evidence":"Changed Faust waveguide lowering to split glottal excitation from tract injection pressure, emit `wg_injection_cell` and `wg_inject_N` terms, and add those terms to oral waveguide section and nasal-junction updates. Verification required disabling build servers/shared compilation/parallel build after normal dotnet builds hung: `dotnet build tests\\AquaSynth.Dsl.Tests\\AquaSynth.Dsl.Tests.csproj --no-restore --disable-build-servers -p:UseSharedCompilation=false -p:BuildInParallel=false -v minimal`; focused `dotnet test --no-build` passed 3 tests."}
|
|
{"date":"2026-05-26","topic":"tract-motion-obstruction-history","lesson":"PT-style movement and release bursts are temporal DSP semantics, not preset flavor. AquaSynth now has `tract_motion` to own slew rates and obstruction threshold; waveguide lowering smooths tract controls and derives burst pressure from previous obstruction state opening into current non-obstruction. Remaining PT expression gaps are true two-steps-per-sample execution, dynamic per-section target diameter arrays, and rendered parity fixtures.","evidence":"Added `TractMotion`, parser command `tract_motion`, voice references/inline overrides, Faust `slew(rate,x)`, smoothed tongue/constriction/velum controls, `tract_prev_injection_close`, `tract_obstructed`, and `tract_release_memory` burst generation. Verification: no-hang build/test command with `--disable-build-servers -p:UseSharedCompilation=false -p:BuildInParallel=false`; focused tests passed 3."}
|
|
{"date":"2026-05-26","topic":"dynamic-tract-reflection-field","lesson":"A PT-class waveguide cannot keep reflection coefficients as compile-time constants. AquaSynth waveguide lowering now derives live per-section diameter targets from `tract_shape`, tongue, constriction, and lip controls, slews them through `tract_motion`, squares them into section areas, and recomputes reflection coefficients and nasal junction areas as DSP expressions.","evidence":"Replaced static `wg_k_N` constants in `FaustExport.TractWaveguideExpression` with generated `wg_diameter_target_N`, `wg_diameter_N`, `wg_area_N`, and dynamic `wg_k_N` expressions. Focused no-hang build/test command passed 3 tests."}
|
|
{"date":"2026-05-26","topic":"waveguide-substep-clock","lesson":"PT's twice-rate tract clock must be represented explicitly. AquaSynth already had `substeps`; lowering now consumes it through `wg_substep_drive` and `wg_substep_loss` so the field is not decorative. Exact intra-sample recursive state updates remain named debt until the Faust lowering or another backend can prove them.","evidence":"Added substep drive/loss scaling in `TractWaveguideExpression`, updated parity docs/reference metadata, and kept `exact_twice_rate_state_update` as missing. Focused no-hang build/test command passed 3 tests."}
|
|
{"date":"2026-05-26","topic":"pink-trombone-parity-fixtures","lesson":"Expressive parity needs fixed workouts before audio golf. AquaSynth now has `PinkTromboneParityFixtures` for open vowel, front vowel, nasal vowel, sibilant, and closure-release scripts built from reusable low-level tract primitives, plus log-mel cosine similarity in `AudioComparison`. The remaining proof is to generate/capture PT reference audio and set honest thresholds.","evidence":"Added `PinkTromboneParityFixtures`, `AudioComparison.LogMelCosineSimilarity`, `AudioAnalyzer.CosineSimilarity`, and tests that every PT fixture parses, emits Faust, uses tract_shape/glottis/tract_injection/nasal_branch/tract_motion, and exports waveguide lowering. Focused build/test passed 4 tests."}
|
|
{"timestamp":"2026-05-25T21:34:00+01:00","topic":"pink-trombone-logmel-parity","claim":"PinkTromboneReferenceRenderer now gives deterministic PT-style fixture audio and PinkTromboneLogMelParityTests writes log-mel/listening artifacts. The compileable Aqua resonator proxy baseline is measurable but weak: cosine 0.5129 open vowel, 0.5405 front vowel, 0.3882 nasal, 0.1156 sibilant, -0.1830 closure-release. Faust waveguide named-state lowering caused compiler churn and remains backend debt rather than a parity claim.","evidence":"dotnet test tests/AquaSynth.Dsl.Tests/AquaSynth.Dsl.Tests.csproj --no-build --filter PinkTromboneFixturesReportLogMelParityWhenFaustIsInstalled -v minimal passed; artifacts/parity/pink-trombone-logmel/20260525T212806301/summary.txt"}
|
|
{"timestamp":"2026-05-26T09:37:00+01:00","topic":"pink-trombone-waveguide-faust-loop","claim":"The Pink Trombone waveguide lowering now uses one Faust feedback component (`wg_loop ~ si.bus(...)`) instead of scalar named recursive equations. Full 44-section oral and 28-section nasal waveguide candidates compile/render through Faust. Current log-mel cosine baseline: open vowel 0.5578, front vowel 0.5368, nasal 0.4299, sibilant 0.2852, closure-release 0.1147.","evidence":"dotnet test tests/AquaSynth.Dsl.Tests/AquaSynth.Dsl.Tests.csproj --no-build --filter PinkTromboneFixturesReportLogMelParityWhenFaustIsInstalled -v minimal passed; artifacts/parity/pink-trombone-logmel/20260526T093628426/summary.txt"}
|
|
{"timestamp":"2026-05-26T10:10:00+01:00","topic":"continuous-tract-morphology","claim":"PT's 44 oral cells are a reference grid, not anatomy. A 17 cm tract split into 44 cells at 44.1 kHz has about 0.5 samples of acoustic delay per cell, so PT-style substeps are pressure for fractional-delay waveguide lowering rather than a durable Aqua DSL primitive. `TractAreaFunction` now owns physical length, normalized interpolation, resampling, and per-cell delay derivation; `tract sections=...` can choose a compiled lowering grid without forcing the named morphology's authoring sample count to match.","evidence":"Added `length_cm` parsing for `tract_shape`/`nasal_branch`, `TractAreaFunction.DiameterAt`, `Resample`, and `CellDelaySamples`; focused tests cover continuous interpolation, authoring-grid/lowering-grid separation, and the 44-cell half-sample delay fact."}
|
|
{"timestamp":"2026-05-26T10:43:00+01:00","topic":"pink-trombone-acoustic-grid-parity","claim":"Waveguide tracts now default to a compiled acoustic unit-delay grid derived from physical length at the 44.1 kHz target. PT's 17 cm / 44-cell shape lowers to about 22 emitted oral sections; nasal length 12 cm lowers to 15 sections. `VocalTract.IndexScale` maps runtime PT-index controls onto the emitted grid so parameter knobs remain in source morphology coordinates. Removing stale `substeps=2` from PT parity fixtures and applying index scaling improved vowels/sibilant but exposed closure as still wrong: open 0.6143, front 0.6349, nasal 0.5425, sibilant 0.3744, closure-release -0.0820.","evidence":"dotnet test tests/AquaSynth.Dsl.Tests/AquaSynth.Dsl.Tests.csproj --no-build --filter \"WaveguideTractDefaultsToAcousticUnitDelayGrid|PinkTromboneParityFixturesUseReusableLowLevelPrimitives|PinkTromboneFixturesReportLogMelParityWhenFaustIsInstalled\" -v minimal passed; artifacts/parity/pink-trombone-logmel/20260526T104229319/summary.txt"}
|
|
{"timestamp":"2026-05-26T11:03:00+01:00","topic":"physical-voice-modeling-research","claim":"The next voice architecture should be an acoustic port network, not a Pink Trombone module: continuous morphology owns paths/area curves, source ports model larynx/syrinx/reed/noise exciters, branch and radiation ports own topology, and wave-clock policies choose unit/half-sample/fractional-delay lowering. Faust `physmodels.lib` and `delays.lib` provide relevant primitives (`pm.chain`, `pm.l2s`, `pm.waveguideFd*`, `de.fdelay*`, Lagrange, Thiran/allpass), but AquaSynth should generate custom scattering where live area controls and inspectable differentiable parameters matter.","evidence":"Added docs/physical-voice-modeling-research.md after checking Faust 2.85.5 local libraries plus primary literature on half-sample/fractional-delay vocal-tract waveguides, waveguide tract acoustics, and differentiable articulatory/source-filter synthesis."}
|
|
{"timestamp":"2026-05-26T14:50:00+01:00","topic":"physical-voice-research-packet","claim":"Physical voice modeling research is now persisted as a local packet under `research/physical-voice-modeling/`, with a distilled summary, source manifest, hashes, local Faust library captures, an open waveguide vocal-tract PDF, and downloaded HTML snapshots for fractional-delay vocal-tract and DDSP review sources.","evidence":"Added `research/physical-voice-modeling/README.md`, `SUMMARY.md`, `SOURCES.md`, and source files under `research/physical-voice-modeling/sources/`; updated docs and spine to point at the packet."}
|
|
{"timestamp":"2026-05-26T15:30:00+01:00","topic":"physical-voice-practical-researchers","claim":"The practical physical voice modeling lineage points to reusable Aqua semantics: Birkholz/VocalTractLab for multi-level gestures and articulatory controls, Story/TubeTalker for continuous area functions and tract-length/coupling parameters, Smith for bidirectional delay-line scattering and fractional-delay waveguides, and Fels/ArtiSynth for separating biomechanics, acoustics, timeline control, and diagnostics. These are architecture pressures, not modules to clone.","evidence":"Added `research/physical-voice-modeling/PEOPLE.md`, `talks/TALKS.md`, downloaded VTL, Praat, Gnuspeech, SndKit, Story/Birkholz/Fels paper sources, captured talk pages, and saved public YouTube transcripts for Julius Smith CIRMMT and Brad Story NCVS."}
|
|
{"timestamp":"2026-05-26T16:25:00+01:00","topic":"physical-voice-acoustic-port-model","claim":"AquaSynth now has first-cut neutral acoustic voice records and parser commands for paths, source ports, branches, radiation ports, wave clocks, and acoustic port networks. PT-shaped tract commands populate those records as compatibility aliases, while current Faust audio still renders through `Voice.Tract`. This creates the intended migration path: move lowering authority toward acoustic networks without forking a syrinx/bird/PT mode.","evidence":"Added `AcousticPath`, `AcousticSourcePort`, `AcousticBranch`, `AcousticRadiationPort`, `WaveClockPolicy`, `AcousticPortNetwork`; parser commands `path`, `source_port`, `branch`, `radiation_port`, `wave_clock`, `acoustic_network`; focused tests `ParserSupportsReusableAcousticPortNetworkPrimitives`, `ParserSupportsPinkTromboneStyleTractVoice`, and `WaveguideTractDefaultsToAcousticUnitDelayGrid` passed."}
|
|
{"timestamp":"2026-05-26T17:35:00+01:00","topic":"physical-voice-acoustic-network-proxy","claim":"Acoustic port networks are now audible through an `acoustic` / `acoustic_voice` Faust response proxy. The proxy derives modal source/body/branch/radiation expressions from declared acoustic records, so paired labial/syrinx-like networks can render without a special mode. Source, branch, and radiation controls bind through ordinary Aqua parameters into emitted Faust. This is a named proxy lane, not final waveguide truth; full lowering is blocked on explicit acoustic junction ownership.","evidence":"Added acoustic voice parsing and `AcousticNetworkExpression` Faust lowering; focused tests `ParserSupportsReusableAcousticPortNetworkPrimitives`, `ParserSupportsPinkTromboneStyleTractVoice`, and `WaveguideTractDefaultsToAcousticUnitDelayGrid` passed with `--disable-build-servers -p:UseSharedCompilation=false -p:BuildInParallel=false`; serial `dotnet build src/AquaSynth.Core/AquaSynth.Core.csproj --no-restore --disable-build-servers -p:UseSharedCompilation=false -p:BuildInParallel=false` passed."}
|
|
{"timestamp":"2026-05-26T18:05:00+01:00","topic":"physical-voice-typed-path-graph","claim":"Aqua acoustic topology now uses a path graph with typed terminals and connections. `source_port`, `radiation_port`, and `branch` remain authoring sugar that populate terminal/connection records, while `AcousticPortNetwork` carries explicit graph terminal and connection names. This resolves the topology naming blocker; the remaining blocker is compiling that graph into bidirectional fractional-delay waveguide Faust.","evidence":"Added `AcousticTerminal`, `AcousticConnection`, terminal/connection enums, parser commands `terminal` and `connect`, branch/source/radiation graph sugar, and focused parser tests `ParserSupportsReusableAcousticPortNetworkPrimitives` and `ParserSupportsTypedAcousticPathGraph`; focused test command passed 4 tests with disabled build servers."}
|
|
{"timestamp":"2026-05-26T18:35:00+01:00","topic":"physical-voice-typed-graph-faust-lowering","claim":"Typed acoustic path graphs now compile to Faust bidirectional segment state when terminals are present. The lowering splits paths at terminals, creates right/left segment state, scatters connected terminals by area-weighted pressure continuity, injects source terminals, and sums radiation terminals. Remaining known limits are integer sample segment delays, fallback for co-located same-path terminals, and only first area-scattering law lowering.","evidence":"Added `AcousticGraphExpression` in `FaustExport`; focused tests `ParserSupportsReusableAcousticPortNetworkPrimitives`, `ParserSupportsTypedAcousticPathGraph`, `FaustCompilerValidatesAcousticPathGraphWhenInstalled`, `ParserSupportsPinkTromboneStyleTractVoice`, and `WaveguideTractDefaultsToAcousticUnitDelayGrid` passed; `dotnet build src/AquaSynth.Core/AquaSynth.Core.csproj --no-restore --disable-build-servers -p:UseSharedCompilation=false -p:BuildInParallel=false` passed."}
|
|
{"timestamp":"2026-05-26T19:10:00+01:00","topic":"physical-voice-graph-wave-clock-and-node-aggregation","claim":"Acoustic graph lowering now honors `wave_clock` delay strategy and aggregates co-located terminals into shared graph nodes. Sources can inject at connected nodes, and graph delay lowers through unit-grid, half-sample, linear fractional, Lagrange, or Thiran/allpass Faust primitives from physical segment length and `ma.SR`.","evidence":"Updated `AcousticGraphExpression` with wave-clock delay selection, same-position terminal node aggregation, connected-node source injection, and basic connection-law expression routing; focused tests `ParserSupportsReusableAcousticPortNetworkPrimitives`, `ParserSupportsTypedAcousticPathGraph`, `FaustCompilerValidatesAcousticPathGraphWhenInstalled`, `ParserSupportsPinkTromboneStyleTractVoice`, and `WaveguideTractDefaultsToAcousticUnitDelayGrid` passed; core build passed."}
|
|
{"timestamp":"2026-05-26T19:30:00+01:00","topic":"physical-voice-tract-graph-propagation","claim":"PT-shaped `tract` authoring can now opt into typed acoustic graph audio with `propagation=graph`. Generated tract acoustic networks now include typed terminals/connections, normalized tract-index positions, and a Thiran wave-clock default for graph propagation; legacy `propagation=waveguide` remains available as the old baseline.","evidence":"Added `TractPropagationMode.Graph`, parser alias `propagation=graph`, graph-first Faust routing for tract voices in graph mode, generated tract terminal/connection records, and focused test `TractVoiceCanLowerThroughAcousticGraph`; focused tests and core build passed."}
|
|
{"timestamp":"2026-05-26T19:55:00+01:00","topic":"pink-trombone-graph-logmel-evidence","claim":"Pink Trombone parity reporting now renders both legacy waveguide and graph-propagation candidates. Graph output is Faust-valid and audible, but open/front vowel log-mel cosine remains below legacy; nasal graph is near legacy, sibilant score improves while cosine remains low, and closure-release graph cosine becomes positive. Static tongue/constriction/lip baking into graph path did not materially move the latest report, pointing next pressure at source/scattering/radiation/transient behavior.","evidence":"Updated `PinkTromboneParityFixture` with `GraphAquaScript`, parity artifacts now include `candidate-graph.*` and per-lane reports. Latest run under `artifacts/parity/pink-trombone-logmel/20260526T182050731`: open graph cosine 0.3736 vs legacy 0.6143, front 0.3889 vs 0.6349, nasal 0.5318 vs 0.5425, sibilant 0.2102 vs 0.3744, closure 0.1168 vs -0.0820."}
|
|
{"timestamp":"2026-05-26T20:25:00+01:00","topic":"pink-trombone-graph-source-radiation-evidence","claim":"Graph source and radiation semantics are now the live parity levers. LF-style glottal flow with a small harmonic pressure blend, graph radiation high-pass leakage, and aperture-weighted high-passed `TurbulenceJet` sources raise graph open/front vowel cosine above the legacy waveguide lane and make closure-release positive. Nasal remains over-loud and sibilant cosine remains weak, so the next pressure is nasal branch/radiation gain or junction coupling plus frication/transient detail.","evidence":"Latest optional PT log-mel run under `artifacts/parity/pink-trombone-logmel`: graph open 0.6393 vs legacy 0.6143, graph front 0.6596 vs legacy 0.6349, graph nasal 0.4607 with RMS ratio 1.6914 vs legacy nasal 0.5425, graph sibilant 0.2320 vs legacy 0.3744, graph closure 0.1170 vs legacy -0.0820."}
|
|
{"timestamp":"2026-05-26T20:55:00+01:00","topic":"physical-voice-side-branch-scattering-blocker","claim":"Nasal graph parity is blocked by the side-branch port law, not by a missing scalar gain. Terminal-specific admittance in connection pressure is structurally cleaner but does not move PT log-mel metrics. Per-port outgoing coupling and squared generated velum opening both suppress nasal leakage only by making oral fixtures nearly silent, showing that the current pressure-wave normalization lets a weak side branch become an accidental loudness path. The next architecture needs power/flow-consistent branch-port scattering that separates junction admittance from outgoing wave normalization.","evidence":"Focused optional PT log-mel runs after per-port outgoing coupling produced open/front graph RMS ratios near 0.0017 with nasal cosine 0.5338; squared generated velum opening produced open/front RMS ratios near 0.0038/0.0039 and nasal RMS 1.5729. Both were cut. The retained terminal-admittance pressure solve preserves the previous source/radiation metrics."}
|
|
{"timestamp":"2026-05-26T21:20:00+01:00","topic":"physical-voice-side-branch-admittance-progress","claim":"Side-branch graph scattering now uses terminal-specific admittance plus a floored area-ratio pressure normalization for outgoing branch waves. This is not final power parity, but it improves nasal cosine/RMS without erasing the oral vowel cosine win. Raw per-port coupling, squared velum mapping, and lip/beak radiation gain were tested and cut.","evidence":"Latest optional PT log-mel run: graph open 0.6202 RMS 0.1703, graph front 0.6417 RMS 0.1752, graph nasal 0.5159 RMS 1.4815, graph sibilant 0.2268 RMS 1.0643, graph closure 0.1117 RMS 1.8085. Previous source/radiation baseline was open 0.6393 RMS 0.3559, front 0.6596 RMS 0.3661, nasal 0.4607 RMS 1.6914, sibilant 0.2320 RMS 0.9158, closure 0.1170 RMS 1.6650."}
|
|
{"timestamp":"2026-05-26T21:35:00+01:00","topic":"physical-voice-frication-source-pressure","claim":"Generated graph `TurbulenceJet` ports now treat sustained turbulence and burst as separate pressure authorities: continuous frication uses max(turbulence, burst) for source pressure instead of being throttled by burst alone, while turbulence still gates noise amount. Fully ungated noise was tested and cut because it hurt closure-release.","evidence":"Optional PT log-mel after pressure fix: sibilant graph cosine 0.2302 / RMS 1.1387 and closure graph cosine 0.1145 / RMS 1.6627. Setting noise to 1 barely changed sibilant (0.2303) and worsened closure (0.1113 / RMS 1.8777), so that part was reverted."}
|
|
{"timestamp":"2026-05-26T21:07:36+01:00","topic":"vocal-tract-playground-actual-graph-audition","claim":"The vocal tract playground no longer owns a browser-native source/filter audio witness. Audition audio is now rendered from the actual Aqua DSL tract graph path by posting controls to a .NET renderer that emits tract propagation=graph, lowers through FaustEmitter, renders with FaustCompiler, writes a WAV, and serves it back to the browser.","evidence":"Built tools/TractGraphRenderer successfully with disabled build servers. Direct renderer smoke wrote artifacts/vocal-tract-playground/smoke.wav with peak 0.15414488, RMS 0.066947475, and no warnings. Live POST http://127.0.0.1:5126/render returned a rendered WAV and /renders/... served HTTP 200. node --check passed for playground app.js and serve.mjs."}
|
|
{"timestamp":"2026-05-26T21:38:50+01:00","topic":"pink-trombone-graph-nasal-level-balance","claim":"The graph tract nasal path no longer reuses velum as both branch valve and nostril aperture. Generated tract graphs now square velum at the nasal branch entrance, keep nostril radiation independent, and use a lower graph radiation gain so corrected topology does not drive the patch into soft clipping. Playground Ma is now level-matched with Open instead of overdriven.","evidence":"PT log-mel graph run passed with open cosine 0.6219 RMS 0.9743, front 0.6407 RMS 1.0024, nasal 0.5375 RMS 1.1476, new bilabial-nasal-ma 0.4743 RMS 1.2206, sibilant 0.3233 RMS 1.0008, closure 0.0817 RMS 1.5534. Live renderer smoke after lowering patch gain reported Open peak/RMS 0.498/0.257 and Ma 0.480/0.243."}
|
|
{"timestamp":"2026-05-26T21:52:30+01:00","topic":"pink-trombone-time-varying-utterance-reference-fixtures","claim":"AquaSynth now has explicit time-varying Pink Trombone reference utterance fixtures for mama, papa, lulek, and thrombosis. The PT renderer can interpolate timestamped control points sample-by-sample and write reference WAVs plus control CSVs before Aqua parity golf begins.","evidence":"Focused test PinkTromboneUtteranceFixturesWriteReferenceWavs passed and wrote artifacts/parity/pink-trombone-utterances/20260526T205230009. PT reference summaries: mama peak/RMS 0.7033/0.4213, papa 0.7012/0.3618, lulek 0.7200/0.4087, thrombosis 0.7600/0.4658."}
|
|
{"evidence":"Pinned external/pink-trombone-mod at 359c2d3b42b10280404c1650dc601902112b4c90; focused dotnet test passed and wrote artifacts/parity/pink-trombone-utterances/20260526T211902375 with mama/papa/lulek/thrombosis reference WAVs.","claim":"The previous Pink Trombone reference renderer was invalid as a parity oracle because it hand-rolled PT-shaped DSP instead of porting the source graph. The renderer now ports the pinned MIT chdh/pink-trombone-mod DSP source: LF glottis, filtered noise, 512-sample block updates, 2x tract stepping, 44 oral/28 nasal waveguide cells, nasal junction, target-diameter slew, touch-style constriction, frication, and obstruction release transients. Earlier utterance WAVs are invalid for parity golf.","timestamp":"2026-05-26T22:20:18+01:00","topic":"pink-trombone-reference-renderer-authority"}
|