Audit acoustic graph DSP model
This commit is contained in:
parent
854a3cdd01
commit
450321d10f
3 changed files with 319 additions and 1 deletions
315
docs/acoustic-graph-dsp-audit.md
Normal file
315
docs/acoustic-graph-dsp-audit.md
Normal file
|
|
@ -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.
|
||||
|
|
@ -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"}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in a new issue