Name graph radiation impedance primitive
This commit is contained in:
parent
a0839a3d2e
commit
0cc03f8b75
5 changed files with 103 additions and 31 deletions
|
|
@ -235,21 +235,25 @@ own contact loss scale and frequency-dependent wall loss.
|
|||
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.
|
||||
Current state: less wrong after cutting generated lip double gates and moving
|
||||
the graph output constants into one named radiation impedance expression.
|
||||
Radiation now reads boundary flow, generated tract lip opening is path
|
||||
geometry, and emitted graph Faust names per-port reference area,
|
||||
differentiation, high-pass cutoff, admittance, and flow.
|
||||
|
||||
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.
|
||||
- The graph no longer has inline `30/70` raw/high-pass blend or `area + 1.0`
|
||||
admittance denominator, but the helper still uses compact empirical kind
|
||||
constants. Those are now in one organ, not scattered through graph lowering.
|
||||
- `RadiationBoundaryReflectionExpression` is useful for standalone radiation
|
||||
openings, but dangerous when the path end area already represents aperture.
|
||||
- Radiation still has no frequency-dependent load matched to tube radius and
|
||||
characteristic impedance.
|
||||
|
||||
Verdict: keep boundary-flow readout. Replace color/admittance constants with a
|
||||
named radiation impedance primitive.
|
||||
Verdict: keep boundary-flow readout and the named primitive. Replace the
|
||||
empirical primitive with a radius/characteristic-impedance model once source
|
||||
and closure storage stop dominating the audible failure.
|
||||
|
||||
### Generated PT-Style Tract
|
||||
|
||||
|
|
@ -292,16 +296,20 @@ faster than global scores.
|
|||
|
||||
Cut or replace these before piling on more tuning:
|
||||
|
||||
1. Unowned radiation constants: 30/70 high-pass blend and `area + 1.0`.
|
||||
2. Unowned segment contact-loss constant `0.02`.
|
||||
3. Turbulence/release scalar constants without a named pressure-flow model.
|
||||
4. Nearest-node source attachment as the only interior source placement model.
|
||||
1. Unowned segment contact-loss constant `0.02`.
|
||||
2. Turbulence/release scalar constants without a named pressure-flow model.
|
||||
3. Nearest-node source attachment as the only interior source placement model.
|
||||
|
||||
Cut in the 2026-05-28 N-port pass:
|
||||
|
||||
- Generic connection fallback pressure/admittance blend.
|
||||
- Shape-specific three-port branch scattering path.
|
||||
|
||||
Cut in the 2026-05-28 radiation pass:
|
||||
|
||||
- Inline graph radiation `30/70` raw/high-pass blend.
|
||||
- Inline graph radiation `area + 1.0` admittance denominator.
|
||||
|
||||
## Keep List
|
||||
|
||||
These foundations deserve to stay:
|
||||
|
|
@ -323,8 +331,8 @@ radiation impedance:
|
|||
- 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.
|
||||
- Radiation impedance: upgrade the named empirical local model to a
|
||||
radius/characteristic-impedance model.
|
||||
|
||||
Until those exist, the graph can imitate some Pink Trombone pressure, but it is
|
||||
not yet a clean general vocal-acoustic machine.
|
||||
|
|
@ -350,3 +358,33 @@ with peak `0.000009`.
|
|||
This is not a victory lap. It is a floor repair. The next real smells are still
|
||||
radiation impedance constants, graph-native closure reservoir state, and source
|
||||
impedance at junction nodes.
|
||||
|
||||
## 2026-05-28 Radiation Primitive Cut
|
||||
|
||||
The second audit cut moved graph radiation coloring and admittance into a named
|
||||
local primitive. The emitter now names per-radiation-terminal:
|
||||
|
||||
- `graph_radiation_reference_area_*`
|
||||
- `graph_radiation_differentiation_*`
|
||||
- `graph_radiation_highpass_*`
|
||||
- `graph_radiation_admittance_*`
|
||||
- `graph_radiation_flow_*`
|
||||
|
||||
This removes the inline `flow * 0.30 + highpass(flow) * 0.70` expression and
|
||||
the inline `area + 1.0` admittance denominator from graph lowering. The current
|
||||
primitive is still empirical, but it has one owner.
|
||||
|
||||
Latest utterance artifact:
|
||||
`artifacts/parity/pink-trombone-utterance-logmel/20260528T113949841`.
|
||||
`mama/papa/thrombosis` cosine is `0.7648/0.8550/0.4556`. `mama/papa`
|
||||
candidate separability is `0.2044` versus reference `0.3791`, so this cleanup
|
||||
does not fix articulation.
|
||||
|
||||
Latest static artifact:
|
||||
`artifacts/parity/pink-trombone-logmel/20260528T113949813`.
|
||||
Static fixtures still pass; `closure-release` remains sealed-static evidence
|
||||
with peak `0.000011`.
|
||||
|
||||
The conclusion is plain: radiation needed an owner, but the voice still needs
|
||||
graph-native closure pressure storage and source impedance before it will stop
|
||||
leaning on boundary color.
|
||||
|
|
|
|||
|
|
@ -490,12 +490,10 @@ public static class FaustEmitter
|
|||
var opening = $"max(0.0, {parameters.Expression(OwnerField(radiationPath, "opening"), port.Opening)})";
|
||||
var reflection = $"min(1.0, abs({parameters.Expression(OwnerField(radiationPath, "reflection"), port.Reflection)}))";
|
||||
var portLoss = $"clip01({parameters.Expression(OwnerField(radiationPath, "loss"), port.Loss)})";
|
||||
var highpass = port.Kind is AcousticRadiationKind.Lip or AcousticRadiationKind.Beak
|
||||
? "80.0"
|
||||
: port.Kind == AcousticRadiationKind.Nostril
|
||||
? "40.0"
|
||||
: "20.0";
|
||||
radiationExpressions.Add($"(({name}_acoustic_body : fi.highpass(1, {highpass})) * {opening} * (0.55 + 0.45 * {reflection}) * {portLoss})");
|
||||
var aperture = RadiationApertureExpression(patch, parameters, port);
|
||||
var highpass = RadiationHighpassExpression(port.Kind, aperture, false);
|
||||
var reflectionWeight = $"(0.55 + 0.45 * {reflection})";
|
||||
radiationExpressions.Add($"(({name}_acoustic_body : fi.highpass(1, {highpass})) * {opening} * {reflectionWeight} * {portLoss})");
|
||||
}
|
||||
if (radiationExpressions.Count == 0)
|
||||
{
|
||||
|
|
@ -798,20 +796,20 @@ public static class FaustEmitter
|
|||
var radiationPath = $"/acoustic/radiation/{radiationIndex}";
|
||||
var opening = RadiationApertureExpression(patch, parameters, radiationPort);
|
||||
var loss = $"clip01({parameters.Expression(OwnerField(radiationPath, "loss"), radiationPort.Loss)})";
|
||||
var highpass = radiationPort.Kind is AcousticRadiationKind.Lip or AcousticRadiationKind.Beak
|
||||
? "220.0"
|
||||
: radiationPort.Kind == AcousticRadiationKind.Nostril
|
||||
? "90.0"
|
||||
: "20.0";
|
||||
var filter = $"fi.highpass(1, {highpass})";
|
||||
var safeTerminal = SafeIdentifier(terminal.Name);
|
||||
var terminalArea = $"{name}_graph_terminal_area_{safeTerminal}";
|
||||
var referenceArea = $"{name}_graph_radiation_reference_area_{safeTerminal}";
|
||||
var differentiation = $"{name}_graph_radiation_differentiation_{safeTerminal}";
|
||||
var highpass = $"{name}_graph_radiation_highpass_{safeTerminal}";
|
||||
var admittance = $"{name}_graph_radiation_admittance_{safeTerminal}";
|
||||
var flow = $"({string.Join(" + ", ports.Select(port => $"({GraphIncoming(name, port)} - {GraphOutgoing(name, port)})"))})";
|
||||
var flowName = $"{name}_graph_radiation_flow_{safeTerminal}";
|
||||
source.AppendLine($" {admittance} = {ProbeSignal(options, $"/debug/{name}/radiation/{terminal.Name}/admittance", $"sqrt(clip01(({terminalArea}) / max(0.000001, ({terminalArea}) + 1.0)))", 0, 1)};");
|
||||
source.AppendLine($" {referenceArea} = {RadiationReferenceAreaExpression(radiationPort.Kind, opening)};");
|
||||
source.AppendLine($" {differentiation} = {RadiationDifferentiationExpression(radiationPort.Kind, opening)};");
|
||||
source.AppendLine($" {highpass} = {RadiationHighpassExpression(radiationPort.Kind, opening, true)};");
|
||||
source.AppendLine($" {admittance} = {ProbeSignal(options, $"/debug/{name}/radiation/{terminal.Name}/admittance", $"sqrt(clip01(({terminalArea}) / max(0.000001, ({terminalArea}) + ({referenceArea}))))", 0, 1)};");
|
||||
source.AppendLine($" {flowName} = {ProbeSignal(options, $"/debug/{name}/radiation/{terminal.Name}/flow", flow, -2, 2)};");
|
||||
radiated.Add($"(({flowName} * 0.30 + ({flowName} : {filter}) * 0.70) * {loss} * {admittance})");
|
||||
radiated.Add($"(({flowName} * (1.0 - ({differentiation})) + ({flowName} : fi.highpass(1, {highpass})) * ({differentiation})) * {loss} * {admittance})");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -865,6 +863,39 @@ public static class FaustEmitter
|
|||
return $"(({closedReflection}) * (1.0 - clip01({aperture})) + ({openReflection}) * clip01({aperture}))";
|
||||
}
|
||||
|
||||
private static string RadiationReferenceAreaExpression(AcousticRadiationKind kind, string aperture) => kind switch
|
||||
{
|
||||
AcousticRadiationKind.Lip or AcousticRadiationKind.Beak => $"max(0.18, 1.50 * 1.50 * (0.35 + 0.65 * clip01({aperture})))",
|
||||
AcousticRadiationKind.Nostril => $"max(0.08, 0.70 * 0.70 * (0.50 + 0.50 * clip01({aperture})))",
|
||||
AcousticRadiationKind.Membrane => "0.35",
|
||||
AcousticRadiationKind.Vent => "0.80",
|
||||
_ => "1.0"
|
||||
};
|
||||
|
||||
private static string RadiationDifferentiationExpression(AcousticRadiationKind kind, string aperture) => kind switch
|
||||
{
|
||||
AcousticRadiationKind.Lip or AcousticRadiationKind.Beak => $"(0.55 + 0.25 * clip01({aperture}))",
|
||||
AcousticRadiationKind.Nostril => $"(0.45 + 0.20 * clip01({aperture}))",
|
||||
AcousticRadiationKind.Membrane => "0.20",
|
||||
AcousticRadiationKind.Vent => $"(0.30 + 0.20 * clip01({aperture}))",
|
||||
_ => "0.50"
|
||||
};
|
||||
|
||||
private static string RadiationHighpassExpression(AcousticRadiationKind kind, string aperture, bool graph) => kind switch
|
||||
{
|
||||
AcousticRadiationKind.Lip or AcousticRadiationKind.Beak => graph
|
||||
? $"(120.0 + 180.0 * clip01({aperture}))"
|
||||
: $"(60.0 + 50.0 * clip01({aperture}))",
|
||||
AcousticRadiationKind.Nostril => graph
|
||||
? $"(55.0 + 75.0 * clip01({aperture}))"
|
||||
: $"(30.0 + 30.0 * clip01({aperture}))",
|
||||
AcousticRadiationKind.Membrane => "15.0",
|
||||
AcousticRadiationKind.Vent => graph
|
||||
? $"(20.0 + 35.0 * clip01({aperture}))"
|
||||
: $"(15.0 + 20.0 * clip01({aperture}))",
|
||||
_ => "20.0"
|
||||
};
|
||||
|
||||
private static string AcousticSourceExpression(
|
||||
SynthPatch patch,
|
||||
AcousticSourcePort port,
|
||||
|
|
|
|||
|
|
@ -197,3 +197,4 @@
|
|||
{"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"}
|
||||
{"evidence":"Replaced the graph connection fallback in `FaustExport` with one general passive N-port area-scattering law for all non-bypass acoustic connections, removed the PT-shaped three-port branch recognizer, and updated structural tests to assert `graph_connection_reflection_*`/`graph_connection_energy_*` instead of `graph_connection_pressure_*`. Focused structural, utterance, and static PT graph tests passed. Latest utterance artifact `artifacts/parity/pink-trombone-utterance-logmel/20260528T113334390`: mama/papa/thrombosis cosine 0.7799/0.8554/0.4555 with mama/papa candidate separability 0.2469 versus reference 0.3791. Latest static artifact `artifacts/parity/pink-trombone-logmel/20260528T113334415` passes with sealed-static closure peak 0.000009.","claim":"Generic connection pressure/admittance fallback was unowned DSP authority. Non-bypass graph connections now share the same traveling-wave N-port area law, leaving closure storage, radiation impedance, and source impedance as the next real smells instead of topology-shaped compatibility code.","timestamp":"2026-05-28T11:45:00+01:00","topic":"acoustic-graph-nport-connection-cut"}
|
||||
{"evidence":"Moved graph radiation output coloring and admittance constants into a named local radiation primitive in `FaustExport`: emitted graph Faust now names `graph_radiation_reference_area_*`, `graph_radiation_differentiation_*`, `graph_radiation_highpass_*`, `graph_radiation_admittance_*`, and `graph_radiation_flow_*` instead of inlining the old `flow * 0.30 + highpass(flow) * 0.70` and `area + 1.0` expressions. Focused structural/Faust checks, accepted utterance smoke, and static PT graph smoke passed. Latest utterance artifact `artifacts/parity/pink-trombone-utterance-logmel/20260528T113949841`: mama/papa/thrombosis cosine 0.7648/0.8550/0.4556, mama/papa candidate separability 0.2044 versus reference 0.3791. Latest static artifact `artifacts/parity/pink-trombone-logmel/20260528T113949813` passes with sealed-static closure peak 0.000011.","claim":"Radiation color was unowned inline math. It now has a single local primitive, but articulation did not materially improve, so the live audible failure is still closure pressure storage/source impedance rather than boundary coloring alone.","timestamp":"2026-05-28T12:05:00+01:00","topic":"acoustic-graph-radiation-primitive-cut"}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
project: AquaSynth
|
||||
spine_version: 1
|
||||
updated: 2026-05-28T11:45:00+01:00
|
||||
updated: 2026-05-28T12:05:00+01:00
|
||||
|
||||
prime_directive: >
|
||||
Build coherent synth machinery. References exist to reveal missing structure,
|
||||
|
|
@ -125,7 +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 scatter, source/topology separation, velum side-port area, generated lip geometry ownership, area-dependent segment loss, and utterance separability should stay. The first audit cut replaced the generic connection fallback pressure/admittance blend and PT-shaped three-port branch recognizer with one passive N-port area-scattering law for all non-bypass connection groups; emitted Faust no longer contains `graph_connection_pressure_*` for graph connections. Latest artifacts after the cut are `artifacts/parity/pink-trombone-utterance-logmel/20260528T113334390` and `artifacts/parity/pink-trombone-logmel/20260528T113334415`; smoke passes, `thrombosis` improves slightly, and `mama/papa` remain differentiated but quiet/under-articulated. Remaining suspect owners are unowned radiation constants, unowned segment loss constant, turbulence/release scalar constants, and nearest-node source attachment. Next coherent build is graph-native closure reservoir plus a named radiation impedance primitive.
|
||||
- `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 scatter, source/topology separation, velum side-port area, generated lip geometry ownership, area-dependent segment loss, and utterance separability should stay. The first audit cut replaced the generic connection fallback pressure/admittance blend and PT-shaped three-port branch recognizer with one passive N-port area-scattering law for all non-bypass connection groups; emitted Faust no longer contains `graph_connection_pressure_*` for graph connections. The second audit cut moved graph radiation color/admittance into one named local primitive with emitted `graph_radiation_reference_area_*`, `graph_radiation_differentiation_*`, `graph_radiation_highpass_*`, `graph_radiation_admittance_*`, and `graph_radiation_flow_*` signals instead of inline `30/70` and `area + 1.0` expressions. Latest artifacts after radiation primitive extraction are `artifacts/parity/pink-trombone-utterance-logmel/20260528T113949841` and `artifacts/parity/pink-trombone-logmel/20260528T113949813`; smoke passes, but `mama/papa` separability and articulation did not materially improve. Remaining suspect owners are unowned segment loss constant, turbulence/release scalar constants, nearest-node source attachment, and the still-empirical radiation primitive. Next coherent build is graph-native closure reservoir/source impedance.
|
||||
- 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.
|
||||
|
|
|
|||
|
|
@ -331,6 +331,8 @@ public sealed class PatchScriptTests
|
|||
Assert.Contains("graph_area_reflection_", export.Source);
|
||||
Assert.Contains("graph_area_energy_in_", export.Source);
|
||||
Assert.Contains("graph_area_energy_out_", export.Source);
|
||||
Assert.Contains("graph_radiation_reference_area_voices_0_lip", export.Source);
|
||||
Assert.Contains("graph_radiation_differentiation_voices_0_lip", export.Source);
|
||||
Assert.Contains("graph_radiation_admittance_voices_0_lip", export.Source);
|
||||
Assert.Contains("graph_radiation_flow_voices_0_lip", export.Source);
|
||||
Assert.Contains("patch_param_0) * (patch_param_0", export.Source);
|
||||
|
|
|
|||
Loading…
Reference in a new issue