2026-05-25 18:36:06 +01:00
|
|
|
# Pink Trombone Parity Packet
|
|
|
|
|
|
|
|
|
|
## Objective
|
|
|
|
|
|
|
|
|
|
Use Pink Trombone as old-school speech parity pressure, not as a vague mascot
|
2026-05-25 19:36:21 +01:00
|
|
|
for "more vocal knobs." The current AquaSynth tract voice is a tract-shaped
|
|
|
|
|
voice treatment with Pink Trombone-style controls. Pink Trombone itself is still
|
|
|
|
|
a moving vocal-tract waveguide. Those are related machines, but not the same
|
|
|
|
|
machine.
|
2026-05-25 18:36:06 +01:00
|
|
|
|
|
|
|
|
This packet exists so the mismatch stays inspectable.
|
|
|
|
|
|
|
|
|
|
## Reference Source
|
|
|
|
|
|
|
|
|
|
Primary source for this packet:
|
|
|
|
|
|
|
|
|
|
- `chdh/pink-trombone-mod`: MIT TypeScript modularization of Neil Thapen's Pink
|
|
|
|
|
Trombone, <https://github.com/chdh/pink-trombone-mod>
|
2026-05-26 22:20:42 +01:00
|
|
|
- Pinned local source: `external/pink-trombone-mod` at
|
|
|
|
|
`359c2d3b42b10280404c1650dc601902112b4c90`
|
2026-05-25 18:36:06 +01:00
|
|
|
- Source files inspected:
|
|
|
|
|
- `src/Synthesizer.ts`
|
|
|
|
|
- `src/Glottis.ts`
|
|
|
|
|
- `src/Tract.ts`
|
|
|
|
|
- `src/TractShaper.ts`
|
|
|
|
|
|
|
|
|
|
The original interactive/programmatic Pink Trombone lineage is also visible in
|
|
|
|
|
`zakaton/Pink-Trombone`, but that package is GPL-3.0. Treat it as reference
|
|
|
|
|
pressure only unless a later license review says otherwise.
|
|
|
|
|
|
|
|
|
|
## Current Mechanism
|
|
|
|
|
|
|
|
|
|
Pink Trombone's source-readable graph:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
frequency/tenseness/intensity
|
|
|
|
|
-> LF-style glottal source plus aspiration noise
|
|
|
|
|
-> 44-section main tract diameter array
|
|
|
|
|
-> squared diameters become section areas
|
|
|
|
|
-> adjacent section areas become reflection coefficients
|
|
|
|
|
-> right/left traveling-wave delay-line state
|
|
|
|
|
-> 28-section nasal branch through a velum junction
|
|
|
|
|
-> lip output + nose output
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The synthesizer steps the tract twice per output sample. Tract shape changes are
|
|
|
|
|
not static formants: the shaper slews section diameters toward target diameters,
|
|
|
|
|
updates reflections at block boundaries, injects turbulence at constrictions,
|
|
|
|
|
and emits a transient when a closure opens.
|
|
|
|
|
|
2026-05-26 11:21:21 +01:00
|
|
|
The 44 oral and 28 nasal counts are Pink Trombone's implementation grid, not
|
|
|
|
|
the AquaSynth abstraction. At 44.1 kHz, a 17 cm tract split into 44 cells has an
|
|
|
|
|
acoustic travel time of roughly 0.5 samples per cell, so the twice-per-sample
|
|
|
|
|
update is better understood as a discretization/wave-clock choice. AquaSynth's
|
|
|
|
|
live target is continuous morphology plus fractional-delay waveguide lowering,
|
|
|
|
|
with the grid chosen by the backend.
|
|
|
|
|
|
2026-05-25 18:36:06 +01:00
|
|
|
## AquaSynth Capability Map
|
|
|
|
|
|
|
|
|
|
Current AquaSynth can express:
|
|
|
|
|
|
|
|
|
|
- runtime parameters with stable paths;
|
2026-05-26 11:21:21 +01:00
|
|
|
- reusable `tract_shape` declarations with authored diameter or area samples,
|
|
|
|
|
physical length, normalized interpolation, resampling, and per-cell acoustic
|
|
|
|
|
delay derivation;
|
2026-05-25 19:54:26 +01:00
|
|
|
- derived tract areas and adjacent-section reflection coefficients;
|
2026-05-25 20:41:59 +01:00
|
|
|
- reusable `glottis` declarations for tract excitation quality;
|
|
|
|
|
- reusable `tract_injection` declarations for positioned frication/burst
|
|
|
|
|
pressure;
|
|
|
|
|
- reusable `nasal_branch` declarations with velum-controlled junctions;
|
2026-05-25 21:18:49 +01:00
|
|
|
- reusable `tract_motion` declarations for slew and obstruction thresholds;
|
2026-05-25 19:36:21 +01:00
|
|
|
- a `tract` voice command owned by `Voice.Tract`;
|
|
|
|
|
- Pink Trombone-shaped controls for intensity, tenseness, tongue body,
|
|
|
|
|
constriction, velum/nasal opening, turbulence, lip opening, and end
|
|
|
|
|
reflections;
|
|
|
|
|
- a Faust-lowered tract voice proxy with LF-style excitation, aspiration,
|
|
|
|
|
frication, oral resonators, and a velum-controlled nasal lane;
|
2026-05-25 20:41:59 +01:00
|
|
|
- generated oral bidirectional waveguide equations over a `tract_shape` section
|
|
|
|
|
field when `propagation=waveguide`;
|
2026-05-25 18:36:06 +01:00
|
|
|
- oscillator/noise sources;
|
|
|
|
|
- ADSR and staged rate/level envelopes;
|
|
|
|
|
- low/high/band/notch filters;
|
|
|
|
|
- static and frame-scanned formant banks;
|
|
|
|
|
- patch-level and voice-local modulation;
|
|
|
|
|
- compiled Faust control sweeps through `/speech/output/N`.
|
|
|
|
|
|
2026-05-25 19:36:21 +01:00
|
|
|
Current AquaSynth cannot exactly express:
|
2026-05-25 18:36:06 +01:00
|
|
|
|
2026-05-26 11:21:21 +01:00
|
|
|
- fractional-delay tract propagation whose clock derives from physical length,
|
|
|
|
|
propagation speed, and sample rate;
|
2026-05-26 22:20:42 +01:00
|
|
|
- exact Pink Trombone block timing and source/noise/transient behavior inside
|
|
|
|
|
the Faust-lowered Aqua graph.
|
|
|
|
|
|
|
|
|
|
## Reference Renderer Authority
|
|
|
|
|
|
|
|
|
|
`PinkTromboneReferenceRenderer` is a source-port of the pinned MIT TypeScript
|
|
|
|
|
implementation, not a Pink-Trombone-flavored proxy. Its inner graph mirrors the
|
|
|
|
|
upstream DSP authorities:
|
|
|
|
|
|
|
|
|
|
- `Synthesizer`: 512-sample blocks, tract stepping twice per output sample;
|
|
|
|
|
- `Glottis`: LF waveform coefficient solve, aspiration noise, vibrato/wobble,
|
|
|
|
|
and intensity/tenseness/frequency smoothing;
|
|
|
|
|
- `Tract`: 44 oral cells, 28 nasal cells, area-derived reflections, three-way
|
|
|
|
|
nasal junction, lip/nose radiation sum, filtered frication, and closure
|
|
|
|
|
transients;
|
|
|
|
|
- `TractShaper`: tongue/rest diameter targets, touch-style constriction
|
|
|
|
|
reduction, wall slew, velum slew, and obstruction release detection.
|
|
|
|
|
|
|
|
|
|
The renderer keeps AquaSynth's fixture control record as the authoring surface,
|
|
|
|
|
but those controls are now translated into the source graph rather than into a
|
|
|
|
|
hand-rolled approximation. Reference WAVs written before
|
|
|
|
|
`20260526T211902375` were produced by the old approximation and are invalid for
|
|
|
|
|
parity golf.
|
2026-05-25 18:36:06 +01:00
|
|
|
|
2026-05-25 19:36:21 +01:00
|
|
|
## Current Parity Rung
|
2026-05-25 18:36:06 +01:00
|
|
|
|
2026-05-25 19:36:21 +01:00
|
|
|
The current committed rung is an expressive tract voice, not exact Pink
|
|
|
|
|
Trombone anatomy:
|
2026-05-25 18:36:06 +01:00
|
|
|
|
|
|
|
|
- `PinkTromboneReference.ToReferencePatch()` records the source, tract features,
|
|
|
|
|
and relevant controls.
|
|
|
|
|
- `ReferenceRebuildCatalog.PinkTromboneRebuilds` contains the current
|
2026-05-25 19:36:21 +01:00
|
|
|
AquaSynth tract-voice proxy as a deliberately non-passing rebuild.
|
|
|
|
|
- The `tract` DSL command parses into an ordinary `Voice` with `Voice.Tract`,
|
|
|
|
|
so this remains a voice with a very expressive tract treatment.
|
2026-05-26 11:21:21 +01:00
|
|
|
- `tract_shape` owns reusable continuous diameter/area functions. The current
|
|
|
|
|
proxy consumes its shape summaries and derived reflection energy; waveguide
|
|
|
|
|
lowering consumes a compiled grid sampled from that continuous owner, so
|
|
|
|
|
authoring sample count and backend section count can differ.
|
2026-05-25 20:41:59 +01:00
|
|
|
- `glottis` and `tract_injection` own excitation and positioned noise/burst
|
|
|
|
|
controls consumed by tract voices.
|
|
|
|
|
- `propagation=waveguide` emits an oral right/left tube from the derived
|
|
|
|
|
reflection field. It is the first low-level propagation path, not full PT.
|
|
|
|
|
- `nasal_branch` adds a second diameter/area tube and generated three-way
|
|
|
|
|
oral/nasal scattering junction when used by a waveguide tract.
|
2026-05-25 20:57:16 +01:00
|
|
|
- `tract_injection` pressure is distributed into waveguide section updates by
|
|
|
|
|
position and width when waveguide propagation is active.
|
2026-05-25 21:18:49 +01:00
|
|
|
- `tract_motion` smooths tract controls and lets the waveguide derive burst
|
|
|
|
|
pressure from obstruction history.
|
2026-05-25 21:27:02 +01:00
|
|
|
- waveguide lowering derives live per-section diameter targets, areas, and
|
|
|
|
|
reflection coefficients from shape and gesture controls.
|
2026-05-26 11:44:43 +01:00
|
|
|
- waveguide lowering now defaults to an acoustic unit-delay compiled grid from
|
|
|
|
|
physical tract length, currently turning a 17 cm oral tract into 22 compiled
|
|
|
|
|
sections at the 44.1 kHz target instead of treating PT's 44 cells as anatomy.
|
2026-05-26 11:21:21 +01:00
|
|
|
- `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.
|
2026-05-25 21:33:33 +01:00
|
|
|
- `PinkTromboneParityFixtures` defines fixed Aqua DSL workouts for open,
|
|
|
|
|
front, nasal, sibilant, and closure cases using the reusable low-level
|
2026-05-25 22:30:55 +01:00
|
|
|
primitives.
|
|
|
|
|
- `PinkTromboneReferenceRenderer` renders deterministic test-only traveling-wave
|
|
|
|
|
references for those fixture controls.
|
2026-05-26 10:38:41 +01:00
|
|
|
- `PinkTromboneLogMelParityTests` renders Aqua waveguide candidates,
|
2026-05-25 22:30:55 +01:00
|
|
|
writes listening WAV/report artifacts under
|
2026-05-26 10:38:41 +01:00
|
|
|
`artifacts/parity/pink-trombone-logmel/`, and reports the current waveguide
|
2026-05-26 11:44:43 +01:00
|
|
|
baseline: open vowel cosine 0.6143, front vowel 0.6349, nasal 0.5425,
|
|
|
|
|
sibilant 0.3744, closure-release -0.0820.
|
2026-05-26 10:38:41 +01:00
|
|
|
- Waveguide lowering now uses one Faust feedback component
|
2026-05-26 11:44:43 +01:00
|
|
|
`wg_loop ~ si.bus(...)` for the compiled oral tract and nasal branch. The
|
|
|
|
|
previous scalar named-recursion form was cut because it was the wrong Faust
|
|
|
|
|
shape, and the PT 44/28 grid is now reference pressure rather than the
|
|
|
|
|
default emitted topology.
|
2026-05-25 19:36:21 +01:00
|
|
|
- The proxy script parses and emits Faust with live controls, but its missing
|
|
|
|
|
features explicitly name the waveguide authorities AquaSynth does not own.
|
|
|
|
|
- `tools/vocal-tract-playground` exposes the same control surface for fast
|
|
|
|
|
knob-twiddling through a small WebAudio witness.
|
2026-05-25 18:36:06 +01:00
|
|
|
- `PinkTromboneReferenceDeclaresMissingWaveguideAuthority` prevents the proxy
|
|
|
|
|
from being mistaken for real tract parity.
|
|
|
|
|
|
2026-05-25 19:36:21 +01:00
|
|
|
That is the correct shape for now. It should be fun to touch, but still honest
|
|
|
|
|
about the parts of Pink Trombone it cannot claim.
|
2026-05-25 18:36:06 +01:00
|
|
|
|
|
|
|
|
## Next Cut
|
|
|
|
|
|
|
|
|
|
Do not add another formant workaround. The next coherent implementation is one
|
|
|
|
|
of these:
|
|
|
|
|
|
2026-05-25 19:36:21 +01:00
|
|
|
1. Promote `Voice.Tract` from tract-shaped proxy lowering to a dedicated tract
|
|
|
|
|
DSP model in AquaSynth.Faust/Core: typed tract sections, diameter curves,
|
|
|
|
|
reflection calculation, glottal source, nasal branch, and a Faust emitter for
|
|
|
|
|
that structure.
|
2026-05-26 11:21:21 +01:00
|
|
|
2. Replace `substeps` as a musical surface with fractional-delay waveguide
|
|
|
|
|
lowering. Physical length, propagation speed, and sample rate decide delay;
|
|
|
|
|
runtime morphology controls move diameters and junction openings without
|
|
|
|
|
recompiling unless topology changes.
|
2026-05-26 10:38:41 +01:00
|
|
|
3. Use the log-mel artifact loop to golf fixture-by-fixture now that the real
|
|
|
|
|
tract path renders.
|
2026-05-25 18:36:06 +01:00
|
|
|
|
|
|
|
|
The new owner should be explainable as:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
TractPlan owns section diameters and source/injection events so tract acoustics
|
|
|
|
|
remain true during rendering.
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
If that sentence becomes awkward, the design is probably drifting back into
|
|
|
|
|
proxy mud.
|