From 450321d10faa63242215eadbc00c41d83fe2f0c8 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 28 May 2026 12:07:05 +0100 Subject: [PATCH] Audit acoustic graph DSP model --- docs/acoustic-graph-dsp-audit.md | 315 +++++++++++++++++++++++++++++++ state/evidence.jsonl | 1 + state/spine.yaml | 4 +- 3 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 docs/acoustic-graph-dsp-audit.md diff --git a/docs/acoustic-graph-dsp-audit.md b/docs/acoustic-graph-dsp-audit.md new file mode 100644 index 0000000..f179d1f --- /dev/null +++ b/docs/acoustic-graph-dsp-audit.md @@ -0,0 +1,315 @@ +# Acoustic Graph DSP Audit + +This audit asks the blunt question for each live graph-voice component: + +- What is this simulating? +- Does the implementation still make sense? +- If not, what authority should own the correction? + +The answer is mixed. The graph is no longer pure rubble, but several pieces are +still standing because they recently helped a metric rather than because they +have a clean physical contract. + +## Pipeline Map + +`PatchScript` builds neutral acoustic records: + +1. `AcousticPath` owns tract or branch length, rest area, propagation speed, + loss, and optional live area controls. +2. `AcousticTerminal` marks topology, source, branch, and radiation positions + on paths. +3. `AcousticConnection` connects terminals into scatter groups. +4. `AcousticSourcePort` owns glottal, turbulence, reed, labial, click, or + synthetic excitation. +5. `AcousticRadiationPort` owns output boundary behavior. +6. `AcousticPortNetwork` names which paths, terminals, connections, sources, + radiation ports, and wave clock form one graph. + +`FaustExport` lowers that graph into bidirectional delay state: + +1. Terminals become graph nodes. +2. Adjacent nodes on each path become bidirectional segments. +3. Each segment stores right-going and left-going traveling waves. +4. Nodes scatter incoming waves into outgoing waves. +5. Source ports add energy at node context. +6. Radiation ports read boundary flow. +7. Segment delays propagate outgoing waves into the next sample state. + +That is the right high-level architecture. The weak parts are inside the +lowering laws. + +## Component Audit + +### Topology Construction + +What it simulates: fixed graph discretization of acoustic paths, with topology +terminals defining scattering locations. + +Current state: mostly coherent. Interior source terminals no longer create +topology nodes; they attach to existing graph nodes. That fixed a real authority +leak. + +Smells: + +- Interior sources attach to the nearest node, not an interpolated point inside + a segment. Generated tract source banks compensate by creating many fixed + source terminals. That is expressive but heavy. +- A node can effectively belong to one connection through `nodeConnection`. + More complex graph topologies may need a first-class multi-connection node + model instead of assuming one branch connection owns the node. +- `terminalConnection` is built but not used. That is small rot. + +Verdict: keep the model, but source placement wants an interpolated injection +primitive before this becomes a clean alien-tract substrate. + +### Area And Geometry + +What it simulates: time-varying tract cross-sectional area derived from rest +diameter plus tongue, constriction, and lip controls. + +Current state: useful but simplistic. Diameter is squared into area, which is +the correct broad convention. Generated lip opening now owns path-end geometry +instead of also owning radiation opening. + +Smells: + +- Tongue/lip shaping is a hand-authored Gaussian blend, and constriction is a + min-like clamp. This is a serviceable control surface, not a principled + articulatory model. +- Graph propagation does not use `tract_motion` slew. Utterance fixtures smooth + controls externally, but generic graph voices can move morphology abruptly. +- Node area sums co-located non-source terminal areas. That is right for some + admittance joins and suspicious for ordinary labels sharing a location. + +Verdict: acceptable as a compact morphology surface, but motion/smoothing must +move into graph area ownership instead of living only in fixture curves or the +old tract proxy. + +### Wave Clock And Delay + +What it simulates: travel time through each path segment. + +Current state: conceptually correct. Segment delay follows physical length, +speed of sound, and the selected fractional-delay strategy. + +Smells: + +- Audio-rate delay modulation from live morphology can hit Faust fractional + delay primitives directly. That is flexible, but the graph has no explicit + policy for smoothing delay changes or preserving passivity during fast + topology-scale motion. +- Minimum-delay policy is hidden in `WaveClockMinimumDelay`; it deserves clearer + documentation per strategy. + +Verdict: keep fractional delay. Add explicit delay-smoothing/passivity policy +before trusting violent morphology animation. + +### Two-Port Path Scattering + +What it simulates: Kelly-Lochbaum area-discontinuity scattering between two +adjacent tube sections. + +Current state: coherent. The graph now uses the PT/Kelly-Lochbaum traveling-wave +convention: + +`r = (A_left - A_right) / (A_left + A_right)`. + +Smells: + +- Source injection is added equally to both outgoing directions at a two-port + node. That is plausible as a symmetric pressure/flow source only when the + source is actually centered at the discontinuity. It is not yet a general + source impedance law. + +Verdict: keep the scatter law. Revisit source injection weighting separately. + +### Three-Port Branch Scattering + +What it simulates: PT-style oral/nasal side branch scattering. + +Current state: coherent for the one common case: two same-path ports plus one +side branch. Removing the hidden `0.15` velum damper fixed a real nasal failure. + +Smells: + +- The implementation recognizes one special topology shape. It is not yet a + general N-port passive junction. +- Source injection is added per port inside the branch law. That needs a clearer + impedance story if sources can live at branch nodes. + +Verdict: good enough for nasal branches, not enough for arbitrary alien tract +graphs. General N-port scattering should replace the shape-specific path. + +### Generic Connection Fallback + +What it simulates: arbitrary connection scattering when a connection is not the +recognized three-port branch. + +Current state: suspect. It computes a pressure-like expression, applies a +handmade port admittance blend, mixes with bypassed incoming waves, and injects +sources. This is exactly the kind of helper that survives because it is useful, +not because it has a single physical invariant. + +Smells: + +- `0.6 + 0.4 * sqrt(...)` is an unexplained compensator. +- It mixes pressure-continuity language into a graph whose main convention is + KL/PT traveling waves. +- It has no passivity proof. + +Verdict: highest-priority Jenga. Replace with a general passive scattering law +or restrict supported connections until that exists. + +### Glottal Source + +What it simulates: voiced excitation at a source boundary. + +Current state: better after local `tanh` normalization. Before that, the source +could dominate the tract as an overdriven buzzer. + +Smells: + +- The waveform is still a hand-shaped proxy, not an LF/Rosenberg model with + named open quotient, speed quotient, and return phase. +- `opening` is used as waveform skew in generated glottis records. That field + name is too generic for what it does here. +- Source injection bypasses boundary impedance; it is simply added into node + outgoing waves. + +Verdict: acceptable as a bounded placeholder. Rename or split glottal shape +fields, then implement a real glottal flow source with impedance coupling. + +### Turbulence And Release Source + +What it simulates: pressure-driven constriction noise and a short opening +transient. + +Current state: partially coherent. Sustained turbulence now has a local +pressure-drive term, and release pressure can observe node incident pressure. + +Smells: + +- The aperture gate constants `0.85`, `0.04`, source gains `0.62`, `1.2`, + `0.58`, and pressure-drive `0.50 + 1.50 * pressure` are not owned by a named + physical model. +- Release still detects local control opening, not stored upstream pressure + behind a sealed constriction. +- There is no graph-native reservoir state. + +Verdict: keep as a pressure-informed source, but do not call this plosive +modeling yet. The next real primitive is closure reservoir state connected to +the scattering graph. + +### Segment Loss + +What it simulates: propagation loss plus extra loss in narrow/contact-like +sections. + +Current state: directionally correct and audibly important. It stopped closed +sections from preserving wave energy as immortal buzz. + +Smells: + +- The `0.02` area constant is an exposed scar. It says "area-dependent loss" + but not whose units or morphology it belongs to. +- Loss is amplitude-only. There is no frequency-dependent wall/radiation loss + model. + +Verdict: keep the authority, parameterize it. Path or material records should +own contact loss scale and frequency-dependent wall loss. + +### Radiation + +What it simulates: boundary flow emitted from lip, nostril, beak, or other +openings. + +Current state: less wrong after cutting generated lip double gates. Radiation +now reads boundary flow and generated tract lip opening is path geometry, not +also output aperture. + +Smells: + +- The 30/70 raw/high-pass blend is a voicing scar. It approximates radiation + color, but it is not a clear radiation impedance model. +- The admittance expression `sqrt(area / (area + 1.0))` contains an unexplained + unit constant. +- `RadiationBoundaryReflectionExpression` is useful for standalone radiation + openings, but dangerous when the path end area already represents aperture. + +Verdict: keep boundary-flow readout. Replace color/admittance constants with a +named radiation impedance primitive. + +### Generated PT-Style Tract + +What it simulates: a compact human vocal tract morphology expressed through +neutral graph records. + +Current state: much healthier. It no longer relies on PT-shaped runtime modules, +and the accepted utterance smoke now passes without cross-word collapse. + +Smells: + +- It still generates many area terminals and many source terminals. That is a + compiled approximation of continuous morphology, not a beautiful abstraction. +- Nasal and lip reflection both bind to `lip_reflection`, matching PT pressure + but not a general anatomy model. +- `tract_motion` is not applied to graph area controls. + +Verdict: good pressure fixture, not final architecture. Continuous/interpolated +source and area sampling would make it less PT-grid-shaped. + +### Tests And Metrics + +What they simulate: falsification pressure, not hearing. + +Current state: better. Cross-utterance separability caught the metric lie. +Static closure-release no longer pretends a sealed static constriction has +time-history release energy. + +Smells: + +- Smoke floors are still survival rails, not acceptance criteria. +- Artifact WAVs are generated, but the harness has no durable listening verdict. +- Speech-band/articulation metrics are still weak proxies. + +Verdict: keep the new separability check. Add windowed phone/gesture reports as +first-class artifacts because they exposed the nasal and rounded-vowel failures +faster than global scores. + +## Cut List + +Cut or replace these before piling on more tuning: + +1. Generic connection fallback pressure/admittance blend. +2. Unowned radiation constants: 30/70 high-pass blend and `area + 1.0`. +3. Unowned segment contact-loss constant `0.02`. +4. Turbulence/release scalar constants without a named pressure-flow model. +5. Nearest-node source attachment as the only interior source placement model. + +## Keep List + +These foundations deserve to stay: + +1. Path graph with typed terminals. +2. KL/PT traveling-wave convention for two-port and nasal branch scatter. +3. Source terminals not owning topology. +4. Velum as side-port area, not global branch damping. +5. Generated lip opening as path-end geometry, not output double gate. +6. Area-dependent segment loss as a named owner, once parameterized. +7. Cross-utterance separability as a hard guardrail. + +## Next Coherent Build + +The next implementation should not be another gain pass. Build a general +passive N-port junction and a closure reservoir primitive: + +- N-port junction: one law for any connection group, using each connected port's + admittance/area, with a passivity probe and no shape-specific fallback. +- Closure reservoir: a stateful pressure store attached to a constriction owner, + charged while local area is sealed and released through the graph when area + opens. +- Radiation impedance: replace output coloring constants with a named local + radiation model. + +Until those exist, the graph can imitate some Pink Trombone pressure, but it is +not yet a clean general vocal-acoustic machine. diff --git a/state/evidence.jsonl b/state/evidence.jsonl index 8ef7635..a5dd3ce 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -195,3 +195,4 @@ {"evidence":"Added utterance separability diagnostics after user listening reported that mama and papa still sound like nearly identical phone vibrations despite flattering individual log-mel scores. The utterance harness now renders all accepted fixtures, writes `separability.txt`, and fails when candidate pairs are more mutually similar than reference pairs by more than 0.20 log-mel similarity. Latest artifact `artifacts/parity/pink-trombone-utterance-logmel/20260527T225833392` catches mama/papa collapse: referenceLogMel 0.3791, candidateLogMel 0.6069, referenceEnvelope 0.8670, candidateEnvelope 0.8885. Interior source terminals also stopped creating topology nodes or contributing to node area/reflection; they now attach to existing graph nodes and inject energy while geometry terminals own impedance.","claim":"Log-mel cosine can lie by rewarding shared filtered buzz. The parity harness must reject cross-utterance collapse, and graph source ports must inject into wave nodes without mutating the tract topology they are meant to excite.","timestamp":"2026-05-27T23:05:00+01:00","topic":"acoustic-graph-utterance-collapse-source-topology"} {"evidence":"Generated tract lip radiation terminals no longer set terminal `area_scale` from the first frame's lip opening. Lip opening already drives live oral path area and radiation aperture, so the old terminal scale let a word starting with closed lips carry closed-lip admittance through later open vowels. Focused structural tests passed, and static PT graph artifact `artifacts/parity/pink-trombone-logmel/20260527T231611586` passed smoke. The utterance artifact `artifacts/parity/pink-trombone-utterance-logmel/20260527T231056242` still fails: thrombosis remains too silent and mama/papa candidate similarity is 0.6343 versus reference 0.3791.","claim":"Generated radiation terminal area scale is not a lip-opening owner. Removing the baked first-frame scale is a coherent authority cut even though it exposes the remaining source/reservoir/radiation coupling failure more harshly.","timestamp":"2026-05-27T23:20:00+01:00","topic":"acoustic-graph-lip-radiation-authority"} {"evidence":"Repaired graph voice sample-flow ownership: bounded the glottal source with local tanh normalization, added area-dependent segment propagation loss, removed the hidden 0.15 generated nasal side-port damper so velum diameter squared owns nasal admittance, stopped generated tract lips from binding lip opening into radiation-port opening, and stopped multiplying graph boundary flow by aperture after boundary reflection/path geometry already handle opening. Focused structural tests, utterance smoke, and static smoke passed. Latest utterance artifact `artifacts/parity/pink-trombone-utterance-logmel/20260528T070759312`: mama/papa/thrombosis cosine 0.7918/0.8540/0.4366, candidate mama/papa separability 0.3651 versus reference 0.3791. Latest static artifact `artifacts/parity/pink-trombone-logmel/20260528T071240442` treats closure-release as sealed static with peak 0.000005.","claim":"The phone-vibration collapse came from multiple model ownership leaks, not one missing gain knob: unbounded source dominance, immortal closed-section wave storage, damped nasal admittance, and lip radiation double-gating. The graph is still quiet and under-articulated, but different articulations now drive different sample-flow paths. Next fix is true closure reservoir/release through the scattering graph.","timestamp":"2026-05-28T07:15:00+01:00","topic":"acoustic-graph-voice-model-repair"} +{"evidence":"Added `docs/acoustic-graph-dsp-audit.md`, auditing each graph-voice component by asking what it simulates and whether the implementation makes sense. The audit keeps path graphs with typed terminals, KL/PT two-port and nasal branch scatter, source/topology separation, velum side-port area, generated lip geometry ownership, area-dependent segment loss, and utterance separability. It marks the generic connection fallback pressure/admittance blend, radiation color/admittance constants, the segment loss constant, turbulence/release scalar constants, and nearest-node source attachment as Jenga. It recommends replacing the generic fallback with a passive general N-port junction, adding graph-native closure reservoir state, and replacing radiation constants with a named radiation impedance primitive.","claim":"The current graph voice is viable but not clean. Further tuning should start by cutting unowned fallback laws and constants, not by adding more source gain or metric-specific compensation.","timestamp":"2026-05-28T07:45:00+01:00","topic":"acoustic-graph-dsp-audit"} diff --git a/state/spine.yaml b/state/spine.yaml index 30333d1..96a9f7d 100644 --- a/state/spine.yaml +++ b/state/spine.yaml @@ -1,6 +1,6 @@ project: AquaSynth spine_version: 1 -updated: 2026-05-28T07:15:00+01:00 +updated: 2026-05-28T07:45:00+01:00 prime_directive: > Build coherent synth machinery. References exist to reveal missing structure, @@ -46,6 +46,7 @@ current_mechanism: pink_trombone_parity: docs/pink-trombone-parity.md pink_trombone_dsl_parity_plan: docs/pink-trombone-dsl-parity-plan.md physical_voice_modeling_research: docs/physical-voice-modeling-research.md + acoustic_graph_dsp_audit: docs/acoustic-graph-dsp-audit.md physical_voice_modeling_packet: research/physical-voice-modeling parameter_contracts: src/AquaSynth.Core/Model.cs @@ -124,6 +125,7 @@ live_invariants: - PT utterance metrics now include cross-utterance separability because log-mel parity alone hid the user's actual listening failure. Artifact `artifacts/parity/pink-trombone-utterance-logmel/20260527T225833392` shows `mama/papa` candidate collapse: reference log-mel similarity 0.3791 versus candidate 0.6069, with candidate envelope similarity 0.8885. Interior source terminals no longer decide topology or node area/reflection; they attach to existing graph nodes and inject energy, while non-source terminals own geometry. Keep this source/topology cut even if other broken layers get louder. - Generated lip radiation terminals no longer bake first-frame lip opening into terminal `area_scale`; lip opening owns live path area plus radiation aperture. This removes a stale initial-state authority where words starting with closed lips kept closed-lip admittance. Static PT graph artifact `artifacts/parity/pink-trombone-logmel/20260527T231611586` passes, while utterance artifact `artifacts/parity/pink-trombone-utterance-logmel/20260527T231056242` still fails `mama/papa` collapse and silent `thrombosis`. Next work remains source/reservoir/radiation coupling, not restoring terminal-scale double gates. - Graph voice repair pass on 2026-05-28 fixed four model-level ownership leaks: glottal excitation is source-normalized with local `tanh`; segment propagation loss is area-dependent so closures absorb instead of ringing forever; generated nasal side-port area maps velum diameter squared directly instead of through the old hidden 0.15 damper; generated tract lips use live path-end geometry as the aperture owner and no longer double-gate radiation opening/boundary flow. Utterance artifact `artifacts/parity/pink-trombone-utterance-logmel/20260528T070759312` passes smoke and no longer collapses `mama/papa` (`referenceLogMel=0.3791`, `candidateLogMel=0.3651`); `thrombosis` improves to cosine 0.4366 but remains weak/quiet. Static artifact `artifacts/parity/pink-trombone-logmel/20260528T071240442` passes with `closure-release` demoted to sealed-static evidence (`peak=0.000005`). Next pressure is true graph-native closure reservoir/release through the scattering path. + - `docs/acoustic-graph-dsp-audit.md` is the current Jenga audit for graph voice DSP. It says the path graph, typed terminals, KL/PT two-port and nasal branch scatter, source/topology separation, velum side-port area, generated lip geometry ownership, area-dependent segment loss, and utterance separability should stay. It flags the generic connection fallback pressure/admittance blend, unowned radiation constants, unowned segment loss constant, turbulence/release scalar constants, and nearest-node source attachment as suspect. Next coherent build is a passive general N-port junction plus graph-native closure reservoir, then a named radiation impedance primitive. - Graph source lowering now names per-node incident pressure and node-local source sums inside the recursive graph loop. Generated tract injection source banks now use cell-centered positions and `1 / sections` index scaling, so turbulence/release energy is born inside tube cells rather than directly on graph/radiation nodes. Latest source-position artifact under `artifacts/parity/pink-trombone-utterance-logmel/20260527T172949293`: mama/papa/thrombosis cosine 0.6654/0.7746/0.5522, rmsRatio 3.0010/2.5712/2.4943, articulation 0.1444/0.1177/0.1193. Static closure-release RMS improved to 1.0078 under `artifacts/parity/pink-trombone-logmel/20260527T172843945`, but papa articulation worsened; keep the cell-centered source placement because it is the correct graph-level source geometry, not because metrics liked it. - TurbulenceJet now includes a release-timed burst-noise component in addition to the deterministic pressure pulse, but a stronger trial barely moved papa; the source is not the main remaining articulation bottleneck. Graph radiation now mixes 30% raw boundary flow with 70% high-passed flow after local admittance weighting, down from the over-bright 15/85 blend. Latest radiation/source artifact under `artifacts/parity/pink-trombone-utterance-logmel/20260527T174236049`: mama/papa/thrombosis cosine 0.6578/0.7692/0.5585, rmsRatio 3.0006/2.6153/2.3488, articulation 0.1437/0.1173/0.1191. Static `closure-release` under `artifacts/parity/pink-trombone-logmel/20260527T174139661` has rmsRatio 0.9900 and speechBandRatio 0.0842. This is still not speaking; next pressure is true tract resonance/passive scattering and pressure storage, not more burst gain. - Same-path two-port area discontinuities now emit `graph_area_energy_in_*` and `graph_area_energy_out_*` probes alongside the three-port branch `graph_connection_energy_*` probes. Use these to inspect passivity and formant-body failures at the scatter sites rather than judging only final output loudness.