Add PT waveguide radiation edge

This commit is contained in:
Meta Vens 2026-05-26 23:27:27 +01:00
commit f32d9a81c0
6 changed files with 18 additions and 8 deletions

View file

@ -149,6 +149,10 @@ Trombone anatomy:
- accepted utterance parity lowers the surviving PT control-point sketches into
Faust `age` curves over ordinary `/pink/...` parameters and compares the
continuous Aqua waveguide render against the source-ported PT renderer.
- waveguide radiation now adds a small high-passed lip-radiation emphasis after
the bidirectional tube output. This is the current answer to the accepted
utterance candidate sounding overly padded while already matching gross timing
and articulation.
- `substeps` is now legacy waveguide clock pressure. Current Faust lowering
consumes it through drive/loss scaling, but the coherent target is
fractional-delay propagation from physical tract length and wave speed.

View file

@ -1095,7 +1095,8 @@ public static class FaustEmitter
source.AppendLine($" {name}_wg_out = {name}_tract_oral_waveguide * (0.65 + 0.35 * abs({lipReflection})) + {name}_tract_nose_waveguide;");
source.AppendLine(" };");
source.AppendLine("};");
source.AppendLine($"{name}_tract_radiated = {name}_wg({name}_tract_excitation);");
source.AppendLine($"{name}_tract_radiated_raw = {name}_wg({name}_tract_excitation);");
source.AppendLine($"{name}_tract_radiated = {name}_tract_radiated_raw + ({name}_tract_radiated_raw : fi.highpass(1, 1200.0)) * 0.45;");
return $"{name}_tract_radiated";
static IEnumerable<string> nextStatesPlaceholder(int count) =>

View file

@ -119,9 +119,12 @@ public static class PinkTromboneParityFixtures
IReadOnlyList<string> referenceFeatures) =>
new(id, description, controls, Script(controls, "waveguide"), Script(controls, "graph"), referenceFeatures);
private static string Script(PinkTromboneFixtureControls controls, string propagation) =>
private static string Script(PinkTromboneFixtureControls controls, string propagation)
{
var patchGain = propagation == "graph" ? 0.028f : 0.82f;
return
$$"""
patch gain=0.82 soft_clip=true
patch gain={{F(patchGain)}} soft_clip=true
tract_shape
name=human
@ -134,6 +137,7 @@ public static class PinkTromboneParityFixtures
tract shape=human glottis=modal injection=inj nasal_branch=nose motion=motion propagation={{propagation}} waveguide_loss=.999 freq={{F(controls.Frequency)}} gain={{F(controls.Gain)}} intensity={{F(controls.Intensity)}} tenseness={{F(controls.Tenseness)}} sustain=.45 decay=.12 tongue_index={{F(controls.TongueIndex)}} tongue_diameter={{F(controls.TongueDiameter)}} constriction_index={{F(controls.ConstrictionIndex)}} constriction_diameter={{F(controls.ConstrictionDiameter)}} turbulence={{F(controls.Turbulence)}} velum={{F(controls.Velum)}} lip={{F(controls.LipOpening)}} burst={{F(controls.Burst)}} glottal_reflection={{F(controls.GlottalReflection)}} lip_reflection={{F(controls.LipReflection)}}
""";
}
private static string F(float value) =>
value.ToString("0.######", System.Globalization.CultureInfo.InvariantCulture);

View file

@ -163,3 +163,4 @@
{"evidence":"Focused dotnet test passed and wrote artifacts/parity/pink-trombone-utterances/20260526T212732321. Summary peaks/RMS: mama 0.1745/0.0420, papa 0.2061/0.0423, lulek 0.1283/0.0188, thrombosis 0.1704/0.0248.","claim":"First listening-driven PT utterance control correction after source-porting the renderer: plosive controls now use abrupt closure/release timing, burst strength is wired into obstruction transients, lulek uses a tighter darker u and shorter lateral gestures, and thrombosis has a quieter less chirpy th onset.","timestamp":"2026-05-26T22:27:53+01:00","topic":"pink-trombone-utterance-control-curve-correction"}
{"evidence":"Focused dotnet test passed and wrote artifacts/parity/pink-trombone-utterances/20260526T213359327. Summary peaks/RMS: mama 0.1745/0.0420, papa 0.1986/0.0421, lulek 0.2338/0.0220, thrombosis 0.1455/0.0203.","claim":"Second listening-driven PT utterance correction moved papa/bilabial closures to the lip end with neutral tongue posture, reduced thrombosis th/r/o width to avoid thraaaw onset, and rebuilt lulek around lighter lateral pressure plus stronger vowel continuity instead of near-occluded lateral/glottal behavior.","timestamp":"2026-05-26T22:34:15+01:00","topic":"pink-trombone-utterance-articulator-correction"}
{"evidence":"Focused tests PinkTromboneAcceptedUtterancesReportWaveguideLogMelParityWhenFaustIsInstalled and PinkTromboneUtteranceFixturesWriteReferenceWavs passed. Latest artifact artifacts/parity/pink-trombone-utterance-logmel/20260526T214946598: mama cosine 0.7211 RMS 0.9995; papa cosine 0.8559 RMS 0.9864; thrombosis cosine 0.5736 RMS 1.0021.","claim":"Lulek was cut from PT utterance parity after listening rejected its control sketch. The accepted curriculum is mama, papa, and thrombosis. The new utterance parity harness lowers PT control points into Faust age curves over ordinary /pink parameters and compares continuous Aqua waveguide renders against the source-ported PT renderer. Level drive and utterance envelope timing were the two major golf cuts.","timestamp":"2026-05-26T22:50:52+01:00","topic":"pink-trombone-accepted-utterance-logmel"}
{"evidence":"Focused tests PinkTromboneFixturesReportLogMelParityWhenFaustIsInstalled, PinkTromboneAcceptedUtterancesReportWaveguideLogMelParityWhenFaustIsInstalled, and PinkTromboneUtteranceFixturesWriteReferenceWavs passed with disabled build servers. Latest accepted utterance artifact artifacts/parity/pink-trombone-utterance-logmel/20260526T222603297: mama cosine 0.7098 RMS 1.0177; papa 0.8545 RMS 1.0043; thrombosis 0.5729 RMS 1.0186.","claim":"Listening described the Aqua PT utterance candidate as trying with a mouth full of cotton. The accepted waveguide lane now adds a small high-passed lip-radiation emphasis after the bidirectional tube output, keeping gross log-mel similarity stable while adding edge to the radiated signal. Static graph fixture gain was reduced because source-ported PT references exposed the old graph lane as over-loud; graph remains pressure, not the accepted moving-utterance lane.","timestamp":"2026-05-26T23:27:15+01:00","topic":"pink-trombone-cotton-mouth-radiation"}

View file

@ -120,7 +120,7 @@ live_invariants:
- Physical voice implementation has started moving PT pressure into neutral acoustic owners: `AcousticPath`, `AcousticTerminal`, `AcousticConnection`, `AcousticSourcePort`, `AcousticBranch`, `AcousticRadiationPort`, `WaveClockPolicy`, and `AcousticPortNetwork`. Parser commands `path`, `terminal`, `connect`, `source_port`, `branch`, `radiation_port`, `wave_clock`, and `acoustic_network` now exist. Existing `tract_shape`, `glottis`, `tract_injection`, `nasal_branch`, and `tract` commands populate acoustic records as compatibility aliases while the current `Voice.Tract` Faust renderer still owns audio.
- `acoustic` / `acoustic_voice` can now render an `AcousticPortNetwork` through a compact Faust response proxy or, when typed terminals are present, a compiled bidirectional Faust segment graph. Graph lowering splits paths at terminal positions, aggregates co-located terminals into graph nodes, orders connection ports deterministically, scatters area-weighted/pressure/bypass connection groups, injects source terminals even at connected nodes, and sums radiation terminals. Segment delay follows physical segment length and the network `wave_clock` strategy through unit-grid, half-sample, linear fractional, Lagrange, or Thiran/allpass Faust delay primitives. Source, branch, radiation, terminal, and connection controls can bind through ordinary Aqua parameters into emitted Faust. PT-shaped `tract` authoring can opt into graph audio with `propagation=graph`; legacy `propagation=waveguide` remains the comparison baseline. Remaining pressure: deepen connection-law semantics and run log-mel parity against the graph renderer. Do not expand the proxy into a second fake synthesizer.
- Pink Trombone log-mel parity now writes both legacy waveguide and graph candidates. Latest graph evidence after source/radiation/side-branch/frication cuts: graph open/front cosine is 0.6202/0.6417, still slightly above the legacy waveguide lane at 0.6143/0.6349; nasal graph cosine improved to 0.5159 and RMS ratio dropped from 1.6914 to 1.4815; sibilant graph cosine remains weak at 0.2302; closure-release graph cosine stays positive at 0.1145 and beats the old negative waveguide baseline. The useful changes were LF-style glottal shaping with a modest harmonic pressure blend, graph radiation high-pass leakage by radiation kind, aperture-weighted high-passed `TurbulenceJet` source semantics, terminal-specific admittance in connection pressure, floored area-ratio pressure normalization for branch outputs, and generated frication ports using max(turbulence, burst) as pressure instead of burst alone. Raw per-port outgoing coupling, squared generated velum opening, lip/beak radiation gain, and un-gated turbulence noise were cut as compensators. Remaining pressure is oral RMS/energy normalization and better frication/transient behavior, not more static shape paperwork.
- PT expressive parity should decompose into reusable Aqua primitives before audio golf: `tract_shape` owns continuous diameter/area geometry over normalized position, physical length (`length_cm`), interpolation/resampling, derived reflection coefficients, and per-cell acoustic delay; `tract` may resample that geometry to a chosen compiled `sections` grid without making authoring sample count anatomy; `glottis` owns excitation controls; `tract_injection` owns positioned frication/burst controls and now distributes frication pressure into waveguide section updates; `nasal_branch` owns a second diameter/area tube; `tract_motion` owns control slew and obstruction threshold; `propagation=waveguide` lowers tract voices into a Faust-friendly `wg_loop ~ si.bus(...)` feedback component with compiled right/left traveling-wave state, live per-section diameter/area/reflection fields, obstruction-history burst pressure, and legacy substep clock intent. Waveguide tracts now default to an acoustic unit-delay grid from physical length at the current 44.1 kHz target, so a 17 cm oral tract emits about 22 sections instead of treating PT's 44 half-sample cells as anatomy; `VocalTract.IndexScale` maps runtime PT-index controls onto that emitted grid. PT's 44 oral and 28 nasal cells are reference discretization, not Aqua morphology authority. `PinkTromboneParityFixtures` defines fixed Aqua DSL workouts, `PinkTromboneReferenceRenderer` now ports the pinned MIT `chdh/pink-trombone-mod` DSP source (`external/pink-trombone-mod` at 359c2d3b42b10280404c1650dc601902112b4c90), and `AudioComparison` includes log-mel cosine similarity. Reference WAVs before `artifacts/parity/pink-trombone-utterances/20260526T211902375` came from the old fake renderer and are invalid. The accepted PT utterance curriculum is now mama, papa, and thrombosis; lulek was cut because its control sketch taught a bad artifact. The utterance log-mel harness lowers accepted PT control points into Faust `age` curves over normal `/pink/...` parameters and compares a continuous Aqua waveguide render against the source-ported PT renderer. Latest accepted run: mama cosine 0.7211 / RMS 0.9995, papa 0.8559 / 0.9864, thrombosis 0.5736 / 1.0021 under `artifacts/parity/pink-trombone-utterance-logmel/20260526T214946598`. Remaining low-level Aqua gap is fractional-delay graph lowering with live morphology/source controls; current graph propagation still bakes too much at compile time for moving utterance parity.
- PT expressive parity should decompose into reusable Aqua primitives before audio golf: `tract_shape` owns continuous diameter/area geometry over normalized position, physical length (`length_cm`), interpolation/resampling, derived reflection coefficients, and per-cell acoustic delay; `tract` may resample that geometry to a chosen compiled `sections` grid without making authoring sample count anatomy; `glottis` owns excitation controls; `tract_injection` owns positioned frication/burst controls and now distributes frication pressure into waveguide section updates; `nasal_branch` owns a second diameter/area tube; `tract_motion` owns control slew and obstruction threshold; `propagation=waveguide` lowers tract voices into a Faust-friendly `wg_loop ~ si.bus(...)` feedback component with compiled right/left traveling-wave state, live per-section diameter/area/reflection fields, obstruction-history burst pressure, legacy substep clock intent, and a small high-passed lip-radiation emphasis after the tube output. Waveguide tracts now default to an acoustic unit-delay grid from physical length at the current 44.1 kHz target, so a 17 cm oral tract emits about 22 sections instead of treating PT's 44 half-sample cells as anatomy; `VocalTract.IndexScale` maps runtime PT-index controls onto that emitted grid. PT's 44 oral and 28 nasal cells are reference discretization, not Aqua morphology authority. `PinkTromboneParityFixtures` defines fixed Aqua DSL workouts, `PinkTromboneReferenceRenderer` now ports the pinned MIT `chdh/pink-trombone-mod` DSP source (`external/pink-trombone-mod` at 359c2d3b42b10280404c1650dc601902112b4c90), and `AudioComparison` includes log-mel cosine similarity. Reference WAVs before `artifacts/parity/pink-trombone-utterances/20260526T211902375` came from the old fake renderer and are invalid. The accepted PT utterance curriculum is now mama, papa, and thrombosis; lulek was cut because its control sketch taught a bad artifact. The utterance log-mel harness lowers accepted PT control points into Faust `age` curves over normal `/pink/...` parameters and compares a continuous Aqua waveguide render against the source-ported PT renderer. Latest accepted run after radiation emphasis: mama cosine 0.7098 / RMS 1.0177, papa 0.8545 / 1.0043, thrombosis 0.5729 / 1.0186 under `artifacts/parity/pink-trombone-utterance-logmel/20260526T222603297`. Remaining low-level Aqua gap is fractional-delay graph lowering with live morphology/source controls; current graph propagation still bakes too much at compile time for moving utterance parity.
- If dotnet builds hang in this workspace, stop orphan dotnet workers and retry with `--disable-build-servers -p:UseSharedCompilation=false -p:BuildInParallel=false`; plain parallel/shared builds can stall without useful diagnostics.
- eSpeak NG is an early parity reference for timing, IPA coverage, and log-mel pressure, not an anatomy oracle or final target.
- Do not expand into prosody, emotional context, personality, or broad Weksa expressivity until the tiny IPA utterance harness can show useful loss movement.

View file

@ -120,7 +120,7 @@ public sealed class PinkTromboneLogMelParityTests
foreach (var fixture in PinkTromboneUtteranceFixtures.All.Where(fixture => UtteranceParityIds.Contains(fixture.Id)))
{
var reference = referenceRenderer.RenderUtterance(fixture.Id, fixture.ControlPoints, fixture.DurationSeconds);
var source = AutomatedGraphSource(fixture);
var source = AutomatedWaveguideSource(fixture);
var candidate = await FaustCompiler.RenderAsync(
source,
new FaustRenderOptions(reference.SampleRate, reference.Samples.Length / (float)reference.SampleRate));
@ -157,9 +157,9 @@ public sealed class PinkTromboneLogMelParityTests
CultureInfo.InvariantCulture,
$"{fixture.Id}/{candidate}: cosine={comparison.LogMelCosineSimilarity:0.0000} logMelDistance={comparison.LogMelDistance:0.0000} score={comparison.Score:0.0000} rmsRatio={comparison.RmsRatio:0.0000} centroidRatio={comparison.CentroidRatio:0.0000}");
private static string AutomatedGraphSource(PinkTromboneUtteranceFixture fixture)
private static string AutomatedWaveguideSource(PinkTromboneUtteranceFixture fixture)
{
var source = FaustEmitter.EmitScript(UtteranceGraphScript(fixture), new FaustExportOptions($"pt_utterance_{fixture.Id}")).Source;
var source = FaustEmitter.EmitScript(UtteranceWaveguideScript(fixture), new FaustExportOptions($"pt_utterance_{fixture.Id}")).Source;
var controls = ControlCurves(fixture.ControlPoints);
for (var index = 0; index < controls.Count; index++)
{
@ -231,7 +231,7 @@ public sealed class PinkTromboneLogMelParityTests
return 0.9f;
}
private static string UtteranceGraphScript(PinkTromboneUtteranceFixture fixture) =>
private static string UtteranceWaveguideScript(PinkTromboneUtteranceFixture fixture) =>
$$"""
patch gain=0.12 soft_clip=true