Keep physical branch admittance ownership
This commit is contained in:
parent
cca8e9bf7a
commit
ac33a38e92
6 changed files with 93 additions and 31 deletions
|
|
@ -67,21 +67,18 @@ For a research-backed waveguide junction, nasal opening should affect the side
|
|||
port admittance. The two oral traveling-wave ports should keep clean continuity
|
||||
through the main tube while the nasal port steals energy according to its area.
|
||||
|
||||
The current generated PT graph still uses `AcousticConnection.Coupling` as a
|
||||
global connection scalar. That scalar damps every port in the connection,
|
||||
including the main oral path. It accidentally prevents flooding, but it also
|
||||
means velopharyngeal coupling is partly acting as a main-airway clamp.
|
||||
Generated PT graphs now move the nasal limit onto the nasal terminal and keep
|
||||
the connection itself fully coupled. This preserves the physical ownership:
|
||||
velopharyngeal opening is side-port admittance, not a main-airway clamp.
|
||||
|
||||
A test cut moved the limit onto the nasal terminal and restored full connection
|
||||
coupling. That is closer to the research shape, but the current connection law
|
||||
then over-radiated the body by roughly 3-5x RMS on the utterance fixtures. Even
|
||||
shrinking nasal admittance did not fix it. The failure is therefore in the
|
||||
multi-port lowering/radiation normalization, not in the DSL's ability to name
|
||||
the anatomy.
|
||||
That change makes the broken downstream law louder. Current utterance fixtures
|
||||
over-radiate by roughly 3-5x RMS and articulation worsens. This is not evidence
|
||||
that side-port admittance is wrong; it is evidence that connection scattering
|
||||
and radiation normalization were relying on the old global damper.
|
||||
|
||||
Required cut: connection scattering needs per-port admittance authority and
|
||||
passivity checks. Generated nasal branches should not rely on global connection
|
||||
coupling as a gain patch.
|
||||
Required cut: connection scattering needs passivity checks and radiation needs
|
||||
normalization against local port admittance/boundary aperture. Generated nasal
|
||||
branches must not rely on global connection coupling as a gain patch.
|
||||
|
||||
### Transformed Control Bindings
|
||||
|
||||
|
|
@ -143,16 +140,21 @@ scattering.
|
|||
|
||||
## Next Cut
|
||||
|
||||
The next coherent implementation target is a passive three-port branch law:
|
||||
The live implementation now has a named three-port branch law for connection
|
||||
groups with two same-path ports plus one side-branch port. It is intentionally
|
||||
kept even though it exposes over-radiation, because it moves ownership to the
|
||||
physically correct port.
|
||||
|
||||
1. Build a named lowering path for connection groups with two same-path ports
|
||||
plus one branch port.
|
||||
2. Use segment areas for the two through-path ports and terminal area for the
|
||||
side port.
|
||||
3. Apply branch opening/coupling to the side-port admittance only.
|
||||
4. Keep the main path continuous when side admittance approaches zero.
|
||||
5. Assert this with generated Faust structure tests before re-golfing PT
|
||||
utterances.
|
||||
The next coherent implementation target is to make that law passive and
|
||||
radiation-aware:
|
||||
|
||||
1. Normalize branch scattering by power/admittance, not by a global damping
|
||||
scalar.
|
||||
2. Keep the main path continuous when side admittance approaches zero.
|
||||
3. Normalize radiation against local aperture/admittance so removing a damper
|
||||
does not become raw loudness.
|
||||
4. Add graph-level probes for per-port incoming/outgoing flow before further
|
||||
PT audio golf.
|
||||
|
||||
If that law still floods, radiation normalization should be audited at the same
|
||||
layer. Do not fix this with another global gain.
|
||||
|
|
|
|||
|
|
@ -710,6 +710,11 @@ public static class FaustEmitter
|
|||
}
|
||||
|
||||
var safeConnection = SafeIdentifier(connection.Name);
|
||||
if (TryEmitThreePortBranchScatter(source, name, connection, safeConnection, ports, sources))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var connectionPressure = ConnectionPressureExpression(name, connection, ports);
|
||||
var connectionMaxArea = MaxExpression(ports.Select(item => ConnectionPortAreaExpression(name, item.terminal, item.nodePortCount)));
|
||||
source.AppendLine($" {name}_graph_connection_pressure_{safeConnection} = {connectionPressure};");
|
||||
|
|
@ -1589,6 +1594,60 @@ public static class FaustEmitter
|
|||
private static string ConnectionPortAreaExpression(string voiceName, AcousticTerminal terminal, int nodePortCount) =>
|
||||
$"({voiceName}_graph_terminal_area_{SafeIdentifier(terminal.Name)} / {F(Math.Max(1, nodePortCount))})";
|
||||
|
||||
private static bool TryEmitThreePortBranchScatter(
|
||||
StringBuilder source,
|
||||
string voiceName,
|
||||
AcousticConnection connection,
|
||||
string safeConnection,
|
||||
IReadOnlyList<(AcousticGraphNode node, AcousticTerminal terminal, AcousticGraphPort port, int nodePortCount)> ports,
|
||||
IReadOnlyDictionary<string, AcousticSourcePort> sources)
|
||||
{
|
||||
if (ports.Count != 3 || connection.Law != AcousticConnectionLaw.AreaScattering)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var pathGroups = ports
|
||||
.GroupBy(item => item.port.Segment.Path.Name, StringComparer.OrdinalIgnoreCase)
|
||||
.OrderByDescending(group => group.Count())
|
||||
.ToList();
|
||||
if (pathGroups.Count != 2 || pathGroups[0].Count() != 2 || pathGroups[1].Count() != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var through = pathGroups[0].ToList();
|
||||
if (!through[0].node.Name.Equals(through[1].node.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var side = pathGroups[1].Single();
|
||||
var portItems = new List<(AcousticGraphNode node, AcousticTerminal terminal, AcousticGraphPort port, int nodePortCount)>(through)
|
||||
{
|
||||
side
|
||||
};
|
||||
var areaExpressions = new Dictionary<AcousticGraphPort, string>();
|
||||
foreach (var item in through)
|
||||
{
|
||||
areaExpressions[item.port] = GraphPortArea(voiceName, item.port);
|
||||
}
|
||||
areaExpressions[side.port] = ConnectionPortAreaExpression(voiceName, side.terminal, side.nodePortCount);
|
||||
|
||||
var areaSum = string.Join(" + ", portItems.Select(item => areaExpressions[item.port]));
|
||||
var weightedIncoming = string.Join(" + ", portItems.Select(item => $"({areaExpressions[item.port]}) * {GraphIncoming(voiceName, item.port)}"));
|
||||
source.AppendLine($" {voiceName}_graph_connection_pressure_{safeConnection} = 2.0 * ({weightedIncoming}) / max(0.000001, {areaSum});");
|
||||
foreach (var item in portItems)
|
||||
{
|
||||
var incoming = GraphIncoming(voiceName, item.port);
|
||||
var outgoing = GraphOutgoing(voiceName, item.port);
|
||||
var sourceInjection = NodeSourceExpression(voiceName, item.node, sources);
|
||||
source.AppendLine($" {outgoing} = ({voiceName}_graph_connection_pressure_{safeConnection} - {incoming} + ({sourceInjection}) / {F(Math.Max(1, item.nodePortCount))}) * {voiceName}_graph_connection_loss_{safeConnection};");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryEmitTwoPortPathScatter(
|
||||
StringBuilder source,
|
||||
string voiceName,
|
||||
|
|
|
|||
|
|
@ -1417,7 +1417,7 @@ public static class PatchScript
|
|||
0,
|
||||
AcousticBranchKind.Nasal,
|
||||
nasal.Velum,
|
||||
0.15f,
|
||||
1,
|
||||
true);
|
||||
AddAcousticBranchRecord(branch);
|
||||
AddAcousticTerminalRecord(new AcousticTerminal(
|
||||
|
|
@ -1433,7 +1433,7 @@ public static class PatchScript
|
|||
branch.ToPosition,
|
||||
AcousticTerminalKind.Junction,
|
||||
branch.Name,
|
||||
MathF.Pow(Math.Max(0, branch.Opening), 2) / Math.Max(0.000001f, nasalArea.Diameters[0] * nasalArea.Diameters[0])));
|
||||
0.15f * MathF.Pow(Math.Max(0, branch.Opening), 2) / Math.Max(0.000001f, nasalArea.Diameters[0] * nasalArea.Diameters[0])));
|
||||
AddAcousticConnectionRecord(new AcousticConnection(
|
||||
BranchConnectionName(branch),
|
||||
[BranchFromTerminalName(branch), BranchToTerminalName(branch)],
|
||||
|
|
|
|||
|
|
@ -178,4 +178,4 @@
|
|||
{"evidence":"Added `AudioArticulationComparison` to `AudioComparison` and updated Pink Trombone parity reports with envelope cosine, active-frame ratio, silence mismatch, envelope/spectral flux ratios, motor-band ratio, speech-band ratio, articulation score, and utterance verdicts. Focused tests passed. Latest utterance artifact artifacts/parity/pink-trombone-utterance-logmel/20260527T130026316 reports mama/papa/thrombosis as `not-accepted-articulation` with articulation scores 0.1930/0.1829/0.1848 despite log-mel cosine 0.5712/0.8659/0.4379. Static reports also expose weak speech-band ratios instead of hiding behind cosine.","claim":"Log-mel cosine is a spectral witness, not a speech-articulation authority. The parity harness must surface silence-map, envelope, flux, motor-band, and speech-band failures so filtered buzz cannot forge a listening receipt.","timestamp":"2026-05-27T13:05:00+01:00","topic":"voice-articulation-metric-witness"}
|
||||
{"evidence":"Segment delay lowering no longer clamps physical acoustic graph segments to one sample before wave-clock lowering; `WaveClockPolicy` now owns the legal delay floor. Generated `tract propagation=graph` patches use `HalfSampleGrid` instead of first-order Thiran, matching the PT/Kelly-Lochbaum half-sample regime. Focused graph, Faust validation, utterance, and static parity tests passed. Latest utterance artifact artifacts/parity/pink-trombone-utterance-logmel/20260527T133539554: mama cosine/articulation 0.5982/0.1952, papa 0.8615/0.1979, thrombosis 0.5217/0.2640. Latest static artifact artifacts/parity/pink-trombone-logmel/20260527T133424894. Re-testing the literal SndKit reflection sign made thrombosis loud/unstable; adding a broader glottal harmonic tail worsened voiced-band behavior, so both were cut.","claim":"Physical tract length must lower to sub-sample graph delays; forcing each section to one sample made the tract acoustically overlong and hid failures behind a low resonance crutch. Half-sample graph timing is the correct next foundation, but articulation still fails because body/radiation and pressure-release behavior are incomplete.","timestamp":"2026-05-27T13:40:00+01:00","topic":"acoustic-graph-half-sample-clock"}
|
||||
{"evidence":"Focused PT tests passed. Utterance artifact artifacts/parity/pink-trombone-utterance-logmel/20260527T150836912: mama/papa/thrombosis cosine 0.8337/0.8893/0.5317, rmsRatio 1.0768/1.5626/0.4004, articulation 0.2118/0.1890/0.2594. Static artifact artifacts/parity/pink-trombone-logmel/20260527T150749857: open/front/nasal/ma/sibilant/closure cosine 0.6942/0.6732/0.7386/0.7067/0.4548/0.5449. A long noisy release transient was cut because it drove papa motor-band ratio to 47.0313.","claim":"Generated graph nasal branches no longer mirror velum into connection coupling. Velum owns nasal entrance area and nostril aperture; `AcousticConnection.Coupling` is a structural max-admittance limit. A fixed 0.15 generated nasal coupling avoids the previous double gate without flooding the graph. `TurbulenceJet` transient lowering now emits a short pressure pulse rather than filtered noise, but true plosive intelligibility still needs graph pressure storage/release around severe closures.","timestamp":"2026-05-27T15:03:00+01:00","topic":"pink-trombone-nasal-coupling-authority"}
|
||||
{"evidence":"Added docs/acoustic-graph-flow-audit.md after comparing current Aqua graph lowering with VocalTractLab, Story/TubeTalker, Julius Smith waveguide modeling, ArtiSynth, and PT/SndKit pressure. Tested moving nasal coupling from global connection damping to side-port admittance and tested a special three-port branch scatter; both compiled but over-radiated utterances around 3-5x RMS, with mama/papa/thrombosis articulation falling to roughly 0.173/0.176/0.141, so both code experiments were cut. The audit identifies the live fault as lowering/radiation normalization and transformed admittance, not missing DSL vocabulary.","claim":"Aqua's graph records can express the research-backed vocal-tract architecture, but current Faust lowering still mangles samples at multi-port branch junctions by using global connection coupling as an accidental damper. The next coherent cut is transformed side-port admittance plus passive three-port/radiation normalization tests, not more PT-shaped source tweaks.","timestamp":"2026-05-27T16:12:00+01:00","topic":"acoustic-graph-flow-audit"}
|
||||
{"evidence":"Added docs/acoustic-graph-flow-audit.md after comparing current Aqua graph lowering with VocalTractLab, Story/TubeTalker, Julius Smith waveguide modeling, ArtiSynth, and PT/SndKit pressure. Restored the physical ownership fix: generated nasal branches keep full connection coupling, put the side-port admittance limit on the nasal terminal, and emit a named three-port branch scatter for two same-path ports plus one side branch. Focused structural/Faust and PT parity tests passed. Latest utterance artifact artifacts/parity/pink-trombone-utterance-logmel/20260527T165339231: mama/papa/thrombosis cosine 0.7973/0.8895/0.5398, rmsRatio 3.7320/4.8039/2.9997, articulation 0.1734/0.1766/0.1410. Latest static artifact artifacts/parity/pink-trombone-logmel/20260527T165305967: open/front/nasal/ma/sibilant/closure cosine 0.6157/0.6879/0.6338/0.6089/0.4868/0.6525. The utterance over-radiation is kept as evidence of downstream passivity/radiation-normalization debt, not grounds to revert the physical ownership fix.","claim":"Aqua's graph records can express the research-backed vocal-tract architecture, but current Faust lowering still mangles samples at multi-port branch junctions because radiation normalization and passivity were leaning on a global connection damper. The next coherent cut is passive/admittance-normalized three-port scattering plus radiation normalization probes, not more PT-shaped source tweaks or reverting the side-port ownership fix.","timestamp":"2026-05-27T16:12:00+01:00","topic":"acoustic-graph-flow-audit"}
|
||||
|
|
|
|||
|
|
@ -119,8 +119,8 @@ live_invariants:
|
|||
- The physical voice research packet now includes a practical implementation/researcher map (`research/physical-voice-modeling/PEOPLE.md`) and talk/transcript ledger (`research/physical-voice-modeling/talks/TALKS.md`). Birkholz/VocalTractLab pressures multi-level articulatory control and gestures; Story/TubeTalker pressures continuous parametric area functions and length/coupling; Smith pressures bidirectional delay-line scattering and fractional-delay waveguides; Fels/ArtiSynth pressures separation between biomechanics, acoustics, timeline controls, and diagnostics. These are reusable DSL semantics, not modules to clone.
|
||||
- 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 now routes accepted parity through `propagation=graph`; the old waveguide parity lane is not a comparison baseline or historical pressure lane.
|
||||
- Pink Trombone log-mel parity now writes graph candidates only. Generated tract graphs mirror live `/pink/...` tract bindings into acoustic source, terminal, radiation, and path-area fields. Graph generation stopped baking first-frame tongue/constriction/lip morphology into the path; `AcousticPath.AreaControl` now turns tongue/constriction/lip controls into live area expressions at graph sample points. Velum owns nasal branch entrance area/aperture, while connection coupling is a structural admittance limit and no longer mirrors velum as a second gate. The first nasal tube sample is no longer allowed to decide the velum opening. Graph radiation now uses aperture as a boundary impedance owner: lip/beak opening blends boundary reflection from near-closed termination to declared open-end reflection, and radiation reads boundary flow (`incoming - outgoing`) through a stronger radiation slope instead of raw incoming pressure. Latest static graph evidence after structural nasal coupling is under `artifacts/parity/pink-trombone-logmel/20260527T150749857`: open/front/nasal/ma/sibilant/closure cosine 0.6942/0.6732/0.7386/0.7067/0.4548/0.5449.
|
||||
- `docs/acoustic-graph-flow-audit.md` compares Aqua's graph to Birkholz/VTL, Story/TubeTalker, Smith waveguides, ArtiSynth, and PT/SndKit. The graph records can name the research-backed architecture, but current Faust lowering still mangles multi-port branch sample flow: global connection coupling is acting as an accidental damper, transformed admittance cannot be expressed by raw `ParameterBinding`, and radiation level still depends on connection-law damping. Two code experiments were cut: moving nasal coupling purely to side-port admittance and a special three-port scatter both compiled but over-radiated utterances 3-5x RMS. Next cut is transformed side-port admittance plus passive three-port/radiation normalization tests.
|
||||
- Pink Trombone log-mel parity now writes graph candidates only. Generated tract graphs mirror live `/pink/...` tract bindings into acoustic source, terminal, radiation, and path-area fields. Graph generation stopped baking first-frame tongue/constriction/lip morphology into the path; `AcousticPath.AreaControl` now turns tongue/constriction/lip controls into live area expressions at graph sample points. Velum owns nasal branch entrance area/aperture; generated nasal connections keep full connection coupling, and the nasal terminal carries the side-port admittance limit. The first nasal tube sample is no longer allowed to decide the velum opening. Graph radiation now uses aperture as a boundary impedance owner: lip/beak opening blends boundary reflection from near-closed termination to declared open-end reflection, and radiation reads boundary flow (`incoming - outgoing`) through a stronger radiation slope instead of raw incoming pressure. Latest static graph evidence after side-port branch ownership is under `artifacts/parity/pink-trombone-logmel/20260527T165305967`: open/front/nasal/ma/sibilant/closure cosine 0.6157/0.6879/0.6338/0.6089/0.4868/0.6525; utterances over-radiate 3-5x RMS, exposing normalization debt.
|
||||
- `docs/acoustic-graph-flow-audit.md` compares Aqua's graph to Birkholz/VTL, Story/TubeTalker, Smith waveguides, ArtiSynth, and PT/SndKit. The graph records can name the research-backed architecture, but current Faust lowering still mangles multi-port branch sample flow. The kept physical fix moves nasal coupling from global connection damping into side-port admittance and emits a named three-port branch scatter for two same-path ports plus one side branch. This worsens current utterance RMS/articulation because radiation normalization and passivity checks were leaning on the old damper. Do not revert that ownership fix just because the next broken subsystem screams; next cut is passive/admittance-normalized three-port scattering and radiation normalization probes.
|
||||
- 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; `AcousticAreaControl` owns live sampled morphology controls on a path; `WaveClockPolicy` owns the legal delay floor instead of forcing every segment to one sample; generated graph tracts now use `HalfSampleGrid` to match the PT/Kelly-Lochbaum half-sample regime; ordinary same-path graph interiors now own signed two-port area-discontinuity scattering; `glottis` owns excitation controls with mild harmonic waveshaping and a small higher-harmonic brightness term for graph sources; `tract_injection` owns positioned frication/burst controls; `AcousticSourcePort.Transient` owns graph-native release/click energy as a pressure pulse rather than filtered noise; sustained `TurbulenceJet` lowering owns a narrow-open aperture gate so closed constrictions no longer hiss; `AcousticSourcePositionControl` owns differentiable runtime weights over fixed source terminals so moving articulators can move source energy without recompiling the graph; `AcousticRadiationPort` owns aperture-dependent boundary reflection, flow radiation, and current post-flow normalization; `nasal_branch` owns a second diameter/area tube and branch aperture while `AcousticConnection.Coupling` owns structural max admittance; `tract_motion` owns control slew and obstruction threshold; `AcousticPortNetwork` owns graph lowering. `PinkTromboneReferenceRenderer` ports the pinned MIT `chdh/pink-trombone-mod` DSP source (`external/pink-trombone-mod` at 359c2d3b42b10280404c1650dc601902112b4c90), and reference WAVs before `artifacts/parity/pink-trombone-utterances/20260526T211902375` are invalid. The accepted PT utterance curriculum is mama, papa, and thrombosis; lulek was cut because its control sketch taught a bad artifact. Latest graph-only utterance smoke under `artifacts/parity/pink-trombone-utterance-logmel/20260527T150836912`: mama/papa/thrombosis remain `not-accepted-articulation` with cosine 0.8337/0.8893/0.5317 and articulation scores 0.2118/0.1890/0.2594. `AudioComparison.Articulation` reports envelope cosine, active-frame ratio, silence mismatch, envelope/spectral flux ratios, motor-band ratio, speech-band ratio, and an articulation score so log-mel cannot forge a listening receipt. A direct LF coefficient source was tested and cut because it overdrove the graph and broke static open vowel; a broader harmonic-tail source was tested and cut because it worsened voiced-band behavior. A naive midpoint admittance scatter was tested and cut because it collapsed `mama`; the kept area-discontinuity scatter needed the opposite reflection sign for this graph state convention, and re-testing the literal SndKit sign after the clock fix made `thrombosis` loud/unstable. A long noisy release transient was tested and cut because it turned papa into motor-band energy; deterministic pressure release with PT-scale decay is structurally kept but still not sufficient. Next pressure is true graph pressure storage/release at severe closures; output coloring alone is not allowed to impersonate articulation.
|
||||
- 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.
|
||||
|
|
|
|||
|
|
@ -638,8 +638,9 @@ public sealed class PatchScriptTests
|
|||
Assert.Contains(patch.AcousticPaths, path => path.Name == "voices_0_oral" && path.AreaControl is not null);
|
||||
Assert.Contains(patch.AcousticSourcePorts, port => port.Name.StartsWith("voices_0_inj_", StringComparison.Ordinal) && port.Transient > 0 && port.PositionControl is not null);
|
||||
Assert.Contains(patch.AcousticTerminals, terminal => terminal.Name.StartsWith("voices_0_area_", StringComparison.Ordinal));
|
||||
Assert.Contains(patch.AcousticConnections, connection => connection.Name.Contains("_nose_connection", StringComparison.Ordinal) && MathF.Abs(connection.Coupling - 0.15f) < 0.0001f);
|
||||
Assert.Contains(patch.AcousticConnections, connection => connection.Name.Contains("_nose_connection", StringComparison.Ordinal) && MathF.Abs(connection.Coupling - 1f) < 0.0001f);
|
||||
Assert.DoesNotContain(patch.ParameterBindings, binding => binding.FieldPath.StartsWith("/acoustic/connections/", StringComparison.OrdinalIgnoreCase) && binding.FieldPath.EndsWith("/coupling", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains("graph_connection_pressure_voices_0_nose_connection", export.Source);
|
||||
Assert.Contains("acoustic_graph_radiated", export.Source);
|
||||
Assert.Contains("graph_terminal_area_voices_0_area_", export.Source);
|
||||
Assert.DoesNotContain("wg_diameter_target_", export.Source);
|
||||
|
|
|
|||
Loading…
Reference in a new issue