diff --git a/src/AquariumSynth.Dsl/BuiltInScripts.cs b/src/AquariumSynth.Dsl/BuiltInScripts.cs index b046a8f..fa80053 100644 --- a/src/AquariumSynth.Dsl/BuiltInScripts.cs +++ b/src/AquariumSynth.Dsl/BuiltInScripts.cs @@ -799,27 +799,25 @@ public static class BuiltInScripts public const string ZynStylePadTexture = """ patch - gain=0.56 - soft_clip=true + gain=1.4 param name=spread path=/macro/spread - default=0.018 + default=0.006 min=0 max=0.04 step=0.001 unit=ratio defaults - wave=saw - attack=0.55 - sustain=1.8 - decay=1.4 - sustain_level=0.78 - lpf=0.42 - hpf=0.025 - drive=0.04 + wave=sine + attack=0.28 + sustain=1.4 + decay=1.2 + sustain_level=0.9 + lpf=1 + hpf=0 mod name=slow_air @@ -828,13 +826,11 @@ public static class BuiltInScripts lpf=0.18 gain=0.05 - layer name=pad_low engine=pad min_key=36 max_key=84 gain=0.07 vibrato=@/macro/spread vibrato_hz=0.09 env=rl rates=0.55,0.68,0.95,1.4 levels=1,0.86,0.78,0 curves=lin,exp,lin,lin gate=2.18 - layer name=pad_high engine=pad min_key=48 max_key=108 gain=0.044 vibrato=0.009 vibrato_hz=0.11 env=rl rates=0.42,0.58,0.9,1.25 levels=1,0.84,0.72,0 curves=lin,exp,lin,lin gate=1.9 - layer name=air engine=add min_key=0 max_key=127 gain=0.018 wave=noise noise=0.82 env=rl rates=0.8,0.6,1.1,1.1 levels=1,0.82,0.55,0 curves=lin,lin,exp,lin gate=2.5 lpf=0.36 hpf=0.22 + layer name=pad_low engine=pad min_key=36 max_key=84 gain=0.14 vibrato=0.002 vibrato_hz=0.09 env=rl rates=0.28,0.42,0.7,1.2 levels=1,0.94,0.88,0 curves=lin,exp,lin,lin gate=2.18 + layer name=pad_high engine=pad min_key=48 max_key=108 gain=0.04 vibrato=0.0015 vibrato_hz=0.11 env=rl rates=0.28,0.42,0.7,1.2 levels=1,0.94,0.88,0 curves=lin,exp,lin,lin gate=2.18 - spectrum layer=pad_low root=130.8128 spread=0.012 partials=1:0.07,1.5:0.052 - spectrum layer=pad_high root=261.6256 spread=0.009 partials=1:0.044 wave=triangle - voice layer=air freq=1800 + spectrum layer=pad_low root=130.8128 spread=0.003 partials=1:0.14,1.5:0.032 + spectrum layer=pad_high root=261.6256 spread=0.002 partials=1:0.04 """; public const string ZynStyleVocalLayer = """ diff --git a/src/AquariumSynth.Dsl/FaustExport.cs b/src/AquariumSynth.Dsl/FaustExport.cs index f227991..89c3bc4 100644 --- a/src/AquariumSynth.Dsl/FaustExport.cs +++ b/src/AquariumSynth.Dsl/FaustExport.cs @@ -259,13 +259,16 @@ public static class FaustEmitter ParameterMap parameters, List warnings) { - const int tableSize = 4096; + const int tableSize = 131072; var table = PadSynthWaveform.Generate(bank, tableSize); var frequency = parameters.Expression(OwnerField(SpectralPath(bankIndex), "note/frequency"), bank.Treatment.Note.FrequencyHz); var readFrequency = $"({F(PadSynthWaveform.SampleRate)} / {F(tableSize)} * ({frequency}) / {F(bank.RootFrequencyHz)})"; source.AppendLine($"{name}_wave = waveform {{{string.Join(",", table.Select(F))}}};"); - source.AppendLine($"{name}_read_index = int(os.phasor({tableSize}, {readFrequency}));"); - source.AppendLine($"{name}_wavetable = {name}_wave, {name}_read_index : rdtable;"); + source.AppendLine($"{name}_read_pos = os.phasor({tableSize}, {readFrequency});"); + source.AppendLine($"{name}_read_index = int({name}_read_pos);"); + source.AppendLine($"{name}_read_frac = {name}_read_pos - float({name}_read_index);"); + source.AppendLine($"{name}_read_next = ({name}_read_index + 1) % {tableSize};"); + source.AppendLine($"{name}_wavetable = ({name}_wave, {name}_read_index : rdtable) * (1 - {name}_read_frac) + ({name}_wave, {name}_read_next : rdtable) * {name}_read_frac;"); EmitVoice(source, patch, bank.Treatment, SpectralPath(bankIndex), name, parameters, warnings, $"{name}_wavetable"); } diff --git a/src/AquariumSynth.Dsl/PadSynthWaveform.cs b/src/AquariumSynth.Dsl/PadSynthWaveform.cs index f9dd10c..949098f 100644 --- a/src/AquariumSynth.Dsl/PadSynthWaveform.cs +++ b/src/AquariumSynth.Dsl/PadSynthWaveform.cs @@ -64,6 +64,17 @@ internal static class PadSynthWaveform var bandwidthHz = (Math.Pow(2.0, bandwidthCents / 1200.0) - 1.0) * bank.RootFrequencyHz * ratio; var bandwidthCyclesPerSample = Math.Max(1e-9, bandwidthHz / (2.0 * SampleRate)); var centerBin = centerCyclesPerSample * tableSize; + if (bandwidthCyclesPerSample * tableSize < 0.5) + { + var bin = (int)Math.Round(centerBin); + if (bin > 0 && bin < amplitudes.Length) + { + amplitudes[bin] += partial.Gain; + } + + continue; + } + var radiusBins = Math.Max(2, (int)Math.Ceiling(bandwidthCyclesPerSample * tableSize * 6)); var left = Math.Max(1, (int)Math.Floor(centerBin - radiusBins)); var right = Math.Min(amplitudes.Length - 1, (int)Math.Ceiling(centerBin + radiusBins)); diff --git a/state/evidence.jsonl b/state/evidence.jsonl index ffbd6f9..0a960df 100644 --- a/state/evidence.jsonl +++ b/state/evidence.jsonl @@ -67,3 +67,4 @@ {"kind":"zyn_reference_oracle","lesson":"ZynAddSubFX source is pinned as GPL test/development material under `external/zynaddsubfx` at 3ab608c432996ba4d582176572c0b0f82328c825. Treat it like dexed-py: a parity oracle for tests and artifacts, not Aquarium implementation, runtime dependency, or NuGet package content. Before further Zyn DSL golf, build a test-only PAD renderer/wrapper from this source and compare Aquarium rebuilds against actual Zyn behavior.","source":"Zyn source pinning for parity on 2026-05-14"} {"date":"2026-05-14","area":"zyn-reference","lesson":"Pinned Zyn can build on Windows through MSYS2/MinGW when GUI/plugins are disabled, tests are enabled, Werror is off, and the stale non-async MiddleWare Part constructor call is patched. Apply Zyn compatibility patches to ignored artifact source copies, not the clean pinned submodule.","evidence":"tools/zyn-reference/build-zyn-reference.ps1 copies external/zynaddsubfx to artifacts/zyn-source-msys, applies tools/zyn-reference/patches/0001-msys-part-constructor.patch, builds PadNoteTest, and ctest -R PadNoteTest passes."} {"date":"2026-05-15","area":"zyn-pad-parity","lesson":"The Zyn PAD oracle now emits real reference material through Zyn PADnoteParameters/PADnote, and the first project-authored PAD comparison is not close: log-mel 0.552296, envelope 0.774501, RMS ratio 0.234763, centroid ratio 1.025735, score 0.236117. Treat this as evidence to isolate source table generation, playback/gain, envelope, and fixture mapping before adding more Zyn DSL syntax.","evidence":"tools/zyn-reference/ZynPadReference.cpp plus tests/AquariumSynth.Dsl.Tests/ZynReferenceParityTests.cs write artifacts/parity/zyn-pad-reference/pad-texture-zyn.wav, pad-texture-aqua.wav, and report.txt when the Zyn artifact renderer is built."} +{"date":"2026-05-15","area":"zyn-pad-parity","lesson":"User listening correctly identified the first Aquarium PAD rebuild as too noisy. The fix was architectural cleanup before new syntax: cut unearned noise/drive/soft-clip from the rebuild, interpolate spectral table reads, and use Zyn-sized 131072-frame PAD tables. Score improved from 0.236117 to 0.487325, with RMS ratio 1.008516 and centroid ratio 1.083082. Remaining mismatch is source profile/table generation and envelope semantics, not decorative layers.","evidence":"artifacts/parity/zyn-pad-reference/report.txt after the de-bee pass; full dotnet test passed 96/96."} diff --git a/state/memory.json b/state/memory.json index e2e6bd0..9ddc171 100644 --- a/state/memory.json +++ b/state/memory.json @@ -85,7 +85,7 @@ }, "zyn_reference_path": { "status": "Initial ZynInstrumentReader parses plain XML and gzip-compressed .xiz-shaped XML from project-authored fixtures into ZynInstrument records and ReferencePatch features. First Zyn-style Aquarium rebuilds exist for additive lead, PAD texture, and vocal/formant layer. `ZynInstrumentSurvey` can rank .xiz directories by feature pressure. Named `layer` declarations provide the first Zyn-driven DSL abstraction; additive `harmonics`, PAD `spectrum`, and staged `env=rl` voice envelopes now attach to those layers. The pinned Zyn source now builds as a test-only MSYS2/MinGW oracle through `tools/zyn-reference/build-zyn-reference.ps1`, which patches an ignored artifact source copy, proves `PadNoteTest`, and builds `ZynPadReference`.", - "lesson": "Start Zyn as structural classification, not translation. Upstream Zyn presets live in a separate bank submodule and should not be vendored until license/provenance is explicit. The ZynAddSubFX engine source is pinned as GPL test/development material under `external/zynaddsubfx` at 3ab608c432996ba4d582176572c0b0f82328c825; use it as a parity oracle only, never as Aquarium runtime or NuGet package content. Zyn build fixes belong in `tools/zyn-reference/patches/` and apply to ignored artifact copies, not the clean pinned submodule. The PAD oracle now renders both generated PAD sample tables and note audio through Zyn `PADnoteParameters`/`PADnote`; optional parity artifacts live under `artifacts/parity/zyn-pad-reference`. The first project-authored PAD comparison is intentionally not a passing gate: Zyn vs Aquarium currently reports log-mel 0.552296, envelope 0.774501, RMS ratio 0.234763, centroid ratio 1.025735, score 0.236117. That proves the harness and shows Aquarium `spectrum` is not yet a close Zyn PAD emulation. The hardened reader parses the observed upstream instrument bank at commit e9f64a9: 1358/1358 .xiz files. The worst target is `olivers-100/0032-Drum Kit.xiz`, with 16 enabled kit items, mixed ADD/SUB/PAD engines, 106 envelopes, 25 free envelopes, 73 LFOs, 37 filters, and 3 formant filters. The first rebuilds show Aquarium can sketch small Zyn fixtures with existing voices/macros/formants/noise, and the upstream survey correctly pushed named kit/layer routing first. `layer` owns name, engine tag, optional key range metadata, default gain, and effect-send labels while lowering to ordinary voices. `harmonics` owns authored ratio/gain partial banks under those layers. `spectrum` owns PAD-style root/spread/partial clouds under those layers and generates PADsynth-style FFT wavetables with frequency-domain spreading, deterministic random phase, and one inverse FFT before ordinary voice treatment. Staged `env=rl` now applies to voices as well as operators, preserving Note as gate authority and envelope data as level-shape authority. Aquarium still does not claim Zyn ADDsynth phase/bandwidth details, full Zyn PAD harmonic-profile/randomness/pitch-zone behavior, arbitrary free-envelope point curves, or richer formant morphing.", + "lesson": "Start Zyn as structural classification, not translation. Upstream Zyn presets live in a separate bank submodule and should not be vendored until license/provenance is explicit. The ZynAddSubFX engine source is pinned as GPL test/development material under `external/zynaddsubfx` at 3ab608c432996ba4d582176572c0b0f82328c825; use it as a parity oracle only, never as Aquarium runtime or NuGet package content. Zyn build fixes belong in `tools/zyn-reference/patches/` and apply to ignored artifact copies, not the clean pinned submodule. The PAD oracle now renders both generated PAD sample tables and note audio through Zyn `PADnoteParameters`/`PADnote`; optional parity artifacts live under `artifacts/parity/zyn-pad-reference`. The first project-authored PAD comparison proved the harness and showed Aquarium `spectrum` was not a close Zyn PAD emulation. User listening identified Zyn as pure wineglass and Aquarium as angry bees. Cutting unearned air/noise/drive/soft-clip from the rebuild, adding interpolated wavetable reads, and raising Aquarium spectral tables to Zyn's 131072-frame PAD size improved the report to log-mel 0.405313, envelope 0.35139, RMS ratio 1.008516, centroid ratio 1.083082, score 0.487325. The remaining gap is source-table/profile and envelope semantics, not more decorative patch layers. The report now also emits `pad-texture-zyn-table0.wav` for source-table listening. The hardened reader parses the observed upstream instrument bank at commit e9f64a9: 1358/1358 .xiz files. The worst target is `olivers-100/0032-Drum Kit.xiz`, with 16 enabled kit items, mixed ADD/SUB/PAD engines, 106 envelopes, 25 free envelopes, 73 LFOs, 37 filters, and 3 formant filters. The first rebuilds show Aquarium can sketch small Zyn fixtures with existing voices/macros/formants/noise, and the upstream survey correctly pushed named kit/layer routing first. `layer` owns name, engine tag, optional key range metadata, default gain, and effect-send labels while lowering to ordinary voices. `harmonics` owns authored ratio/gain partial banks under those layers. `spectrum` owns PAD-style root/spread/partial clouds under those layers and generates PADsynth-style FFT wavetables with frequency-domain spreading, deterministic random phase, and one inverse FFT before ordinary voice treatment. Staged `env=rl` now applies to voices as well as operators, preserving Note as gate authority and envelope data as level-shape authority. Aquarium still does not claim Zyn ADDsynth phase/bandwidth details, full Zyn PAD harmonic-profile/randomness/pitch-zone behavior, arbitrary free-envelope point curves, or richer formant morphing.", "next": "Use the Zyn PAD oracle report to isolate whether the main mismatch is source table generation, note playback/gain, envelope shape, or fixture mapping before adding more Zyn DSL surface." }, "note_and_envelope_model": { @@ -101,7 +101,7 @@ }, "last_verified": { "command": "powershell -NoProfile -ExecutionPolicy Bypass -File tools\\zyn-reference\\build-zyn-reference.ps1; dotnet test AquariumSynthCSharp.slnx --no-restore", - "result": "Zyn source copied to ignored artifact tree, patched, built with MSYS2/MinGW, PadNoteTest passed, ZynPadReference built; C# suite 96 passed and package boundary remains clean", - "commit": "pending Zyn PAD renderer" + "result": "ZynPadReference artifacts include note and source-table WAVs; Aquarium PAD render improved to score 0.487325; C# suite 96 passed", + "commit": "pending Zyn PAD de-bee pass" } } diff --git a/state/spine.yaml b/state/spine.yaml index 9a19880..7255183 100644 --- a/state/spine.yaml +++ b/state/spine.yaml @@ -1,6 +1,6 @@ project: AquariumSynthCSharp spine_version: 1 -updated: 2026-05-15T00:35:00+01:00 +updated: 2026-05-15T01:15:00+01:00 prime_directive: > Build coherent synth machinery. References exist to reveal missing structure, @@ -101,7 +101,7 @@ reference_targets: priority: 2 purpose: "Additive, subtractive, PAD, formant, kit, and layered-instrument pressure test." source: "https://github.com/zynaddsubfx/zynaddsubfx" - status: "Initial ZynInstrumentReader reads plain or gzip-compressed .xiz XML from project-authored fixtures and classifies active ADD/SUB/PAD engines, enabled kit items, layering, envelopes, free envelopes, LFOs, filters, formants, and effects as ReferencePatch features. First Aquarium rebuilds exist for additive lead, PAD texture, and vocal/formant layer and now use named `layer` declarations. Additive rebuilds can use `harmonics` banks attached to layers, PAD rebuilds can use `spectrum` PADsynth-style FFT wavetable banks attached to layers, and PAD/vocal rebuilds use staged voice `env=rl` envelopes through layer defaults. ZynAddSubFX source is pinned under `external/zynaddsubfx` at 3ab608c432996ba4d582176572c0b0f82328c825 for test-only parity work, and `tools/zyn-reference/build-zyn-reference.ps1` now builds an ignored patched source copy with MSYS2/MinGW, proves `PadNoteTest`, and builds `ZynPadReference`. The first optional PAD report against the project-authored fixture emits WAV/listening artifacts and scores poorly but usefully: log-mel 0.552296, envelope 0.774501, score 0.236117. A non-vendored upstream bank survey parsed 1358/1358 .xiz files and identified named kit/layer routing as the first owner abstraction." + status: "Initial ZynInstrumentReader reads plain or gzip-compressed .xiz XML from project-authored fixtures and classifies active ADD/SUB/PAD engines, enabled kit items, layering, envelopes, free envelopes, LFOs, filters, formants, and effects as ReferencePatch features. First Aquarium rebuilds exist for additive lead, PAD texture, and vocal/formant layer and now use named `layer` declarations. Additive rebuilds can use `harmonics` banks attached to layers, PAD rebuilds can use `spectrum` PADsynth-style FFT wavetable banks attached to layers, and PAD/vocal rebuilds use staged voice `env=rl` envelopes through layer defaults. ZynAddSubFX source is pinned under `external/zynaddsubfx` at 3ab608c432996ba4d582176572c0b0f82328c825 for test-only parity work, and `tools/zyn-reference/build-zyn-reference.ps1` now builds an ignored patched source copy with MSYS2/MinGW, proves `PadNoteTest`, and builds `ZynPadReference`. The optional PAD report emits note and source-table WAV/listening artifacts. After cutting unearned noise/drive/soft-clip, adding interpolated table reads, and raising Aquarium spectral tables to 131072 frames, the project-authored PAD report is better but still not passing: log-mel 0.405313, envelope 0.35139, score 0.487325. A non-vendored upstream bank survey parsed 1358/1358 .xiz files and identified named kit/layer routing as the first owner abstraction." first_slice: - "Use the Zyn PAD oracle report to isolate source-table, playback/gain, envelope, and fixture-mapping mismatch before further Zyn DSL golf." - "Use named layers as the owner before promoting richer formant morphing syntax." @@ -143,10 +143,12 @@ next_agent_start_here: through `tools/zyn-reference/build-zyn-reference.ps1` using an ignored patched artifact copy and builds `ZynPadReference`, which emits PAD table samples or note audio from Zyn. The first optional project-authored PAD - comparison writes WAV/report artifacts under `artifacts/parity/zyn-pad-reference` - and is not close yet: log-mel 0.552296, envelope 0.774501, score 0.236117. - Next pressure is isolating whether the mismatch lives in source-table - generation, note playback/gain, envelope shape, or fixture mapping. + comparison writes WAV/report artifacts under `artifacts/parity/zyn-pad-reference`. + User listening called the reference wineglass-pure and Aquarium angry bees. + The current de-bee pass cuts unearned noise/drive/soft-clip, interpolates + spectral wavetable reads, uses 131072-frame PAD tables, and now reports + log-mel 0.405313, envelope 0.35139, score 0.487325. Next pressure is + source-table/profile and envelope semantics, not more decorative layers. must_read: - AGENTS.md - docs/audio-doctrine.md @@ -159,6 +161,20 @@ next_agent_start_here: - "dotnet test AquariumSynthCSharp.slnx --no-restore" completed_slices: + - date: 2026-05-15 + summary: > + De-beed the project-authored Zyn PAD rebuild after listening identified + Aquarium as a noisy swarm while Zyn sounded like a pure blown wineglass. + Cut the unearned `air` noise layer, drive, and soft clipping from the PAD + rebuild; added interpolated Faust wavetable reads for spectral banks; and + raised spectral PAD tables to Zyn's 131072-frame sample size. The optional + Zyn PAD report now also writes the source table WAV + `pad-texture-zyn-table0.wav`. Latest report: log-mel 0.405313, envelope + 0.35139, RMS ratio 1.008516, centroid ratio 1.083082, score 0.487325. + This is a real improvement from 0.236117 but not passing; remaining + pressure is exact source profile/table generation and Zyn amplitude + semantics. + verification: "dotnet test AquariumSynthCSharp.slnx --no-restore: 96 passed" - date: 2026-05-15 summary: > Added `ZynPadReference`, a test-only executable copied into the ignored diff --git a/tests/AquariumSynth.Dsl.Tests/PatchScriptTests.cs b/tests/AquariumSynth.Dsl.Tests/PatchScriptTests.cs index 185d1d1..266a9e5 100644 --- a/tests/AquariumSynth.Dsl.Tests/PatchScriptTests.cs +++ b/tests/AquariumSynth.Dsl.Tests/PatchScriptTests.cs @@ -262,8 +262,9 @@ public sealed class PatchScriptTests if (rebuild.ReferenceId == "zyn/project/pad-texture") { Assert.NotEmpty(patch.SpectralBanks); + Assert.Contains(patch.SpectralBanks, bank => bank.Treatment.RateLevelEnvelope is not null); } - if (rebuild.ReferenceId is "zyn/project/pad-texture" or "zyn/project/vocal-layer") + if (rebuild.ReferenceId == "zyn/project/vocal-layer") { Assert.Contains(patch.Voices, voice => voice.RateLevelEnvelope is not null); } @@ -405,7 +406,8 @@ public sealed class PatchScriptTests Assert.Equal(100, bank.Treatment.Oscillator.FrequencyHz); Assert.Equal(.08f, bank.Treatment.Gain, 5); Assert.Contains("spectral_0_wave = waveform", export.Source); - Assert.Contains("spectral_0_wavetable = spectral_0_wave, spectral_0_read_index : rdtable", export.Source); + Assert.Contains("spectral_0_read_frac", export.Source); + Assert.Contains("spectral_0_wavetable = (spectral_0_wave, spectral_0_read_index : rdtable)", export.Source); Assert.Contains("process =", export.Source); } diff --git a/tests/AquariumSynth.Dsl.Tests/ZynReferenceParityTests.cs b/tests/AquariumSynth.Dsl.Tests/ZynReferenceParityTests.cs index e26963b..ccc237d 100644 --- a/tests/AquariumSynth.Dsl.Tests/ZynReferenceParityTests.cs +++ b/tests/AquariumSynth.Dsl.Tests/ZynReferenceParityTests.cs @@ -38,6 +38,8 @@ public sealed class ZynReferenceParityTests var input = Path.Combine(root, "tests", "AquariumSynth.Dsl.Tests", "Fixtures", "ZynAddSubFX", "ProjectAuthored", "pad-texture.xiz"); var zynRaw = Path.Combine(artifactDir, "pad-texture-zyn.f32"); var zynWav = Path.Combine(artifactDir, "pad-texture-zyn.wav"); + var zynTableRaw = Path.Combine(artifactDir, "pad-texture-zyn-table0.f32"); + var zynTableWav = Path.Combine(artifactDir, "pad-texture-zyn-table0.wav"); var aquaWav = Path.Combine(artifactDir, "pad-texture-aqua.wav"); var reportPath = Path.Combine(artifactDir, "report.txt"); @@ -55,10 +57,26 @@ public sealed class ZynReferenceParityTests var reference = await RunAsync(bash, ["-lc", command]); Assert.Equal(0, reference.ExitCode); + var tableCommand = string.Join(' ', [ + "export PATH=/mingw64/bin:/usr/bin:/bin:$PATH;", + $"cd {BashQuote(ToMsysPath(root))};", + "./artifacts/zyn-reference-build-msys/src/Tests/ZynPadReference.exe", + BashQuote(ToMsysPath(input)), + BashQuote(ToMsysPath(zynTableRaw)), + "0", + "0" + ]); + var tableReference = await RunAsync(bash, ["-lc", tableCommand]); + Assert.Equal(0, tableReference.ExitCode); + var zynSamples = await ReadFloat32Async(zynRaw); + var zynTableSamples = await ReadFloat32Async(zynTableRaw); Assert.Equal(66150, zynSamples.Length); Assert.True(Peak(zynSamples) > 0.001f); + Assert.True(zynTableSamples.Length > zynSamples.Length); + Assert.True(Peak(zynTableSamples) > 0.001f); WriteWav(zynWav, zynSamples, 44100, 0.9f); + WriteWav(zynTableWav, zynTableSamples, 44100, 0.9f); var report = new List { @@ -66,9 +84,13 @@ public sealed class ZynReferenceParityTests $"renderer: {renderer}", $"input: {input}", $"stdout: {reference.Stdout.Trim()}", + $"table_stdout: {tableReference.Stdout.Trim()}", $"zyn_samples: {zynSamples.Length}", $"zyn_peak: {Peak(zynSamples):0.######}", - $"zyn_rms: {Rms(zynSamples):0.######}" + $"zyn_rms: {Rms(zynSamples):0.######}", + $"zyn_table_samples: {zynTableSamples.Length}", + $"zyn_table_peak: {Peak(zynTableSamples):0.######}", + $"zyn_table_rms: {Rms(zynTableSamples):0.######}" }; var aquaExport = FaustEmitter.EmitScript(BuiltInScripts.ZynStylePadTexture, new FaustExportOptions("zyn_pad_texture"));