This roadmap is the companion piece to tests/native_golden. The goal is to
keep simulator renders honest by capturing both the raw audio artifacts and a
manifest of hashes that tests can diff without golden-ear guesswork.
- Render target:
tests/native_golden/test_main.cppnow prints a dozen audio fixtures (including the quadraphonicquad-bus.wav, the 6-lanesurround-bus.wav, and the expanded reseed suite) and a matching set of control logs whenENABLE_GOLDEN=1. Every WAV now drops abuild/fixtures/<fixture>-control.txtsibling (thinksampler-grains-controlandquad-bus-control) that captures the deterministic seed schedule or MIDI automation the render consumed. The quad bus log now explicitly lists the channel order (frontL,frontR,rearL,rearR) plus the mono/stereo routing weights so reviewers can sanity-check spatial decisions by eye. In addition to the 110 Hz mono drone, sampler chord stack, and resonator tail collage we now ship a stereo granular wash (granular-haze.wav, rendered byrender_granular_fixture()), a stereo master-bus composite (mixer-console.wav, blended byrender_mixer_fixture()), a quad bus (quad-bus.wav), a six-channel mid/side surround layout (surround-bus.wav), and four reseed passes. The original A/B cues still prove the event log math, whilereseed-C.wav(132 BPM / four passes) leans into higher-density swing to sniff out tempo-locked bugs, andreseed-poly.wavbolsters the stem list with the "tape rattle" sampler lane plus a resonator "clank shimmer" bus so we can study overlapping plucks without sacrificing determinism. Euclid, Burst, and reseed event transcripts still tag along so reviewers can diff timing logic beside the WAVs. PlatformIO bakes the absolute project root intoSEEDBOX_PROJECT_ROOT_HINT, the runner honors aSEEDBOX_PROJECT_ROOToverride, and it still climbs the filesystem looking forplatformio.iniif all else fails. No matter how you launch the tests, the renders end up in<repo>/build/fixturesinstead of hiding inside.pio/. The freshest entry,stage71-bus.wav, lives intests/native_golden/wav_helpers.cpp: the helperrender_stage71_scene()synthesizes an eight-lane (L,R,C,LFE,Ls,Rs,Lrs,Rrs) pass with a companion control log that literally annotates each bus. That capture proves the mixer can chew on a labeled 7.1 layout even though the helper lives outsidetest_main.cpp, which keeps the stage routing reusable. The newest entry,modulated-sampler.wav, is deliberately noisy: the helperrender_modulated_sampler_fixture()mixes the sampler and granular engines, sweeps tone + spread automation every single frame, and prints a matchingmodulated-sampler-control.txtautomation log so reviewers can see the exact modulation lanes that carved those wobbles. That stress case makes it obvious when downstream automation plumbing drifts from the C++ reference. Hot on its heels isengine-hybrid-stack.wav, minted byrender_engine_hybrid_fixture()and registered viatest_render_engine_hybrid_stack_golden()intests/native_golden/test_main.cpp. It hammers the sampler, resonator, and granular engines with the same Euclid + Burst schedule, then logs every automation lane (brightness, drive, bloom/feedback, grain density, macro pan) toengine-hybrid-stack-control.txt. Think of it as a deterministic track sheet: if a PR nudges the Euclid mask, Burst spacing, or any of the modulation waves, the log diff spells out exactly what changed without ever leaving the CLI. The new sibling,engine-macro-orbits.wav, uses the same engines but leans harder into modulation pedagogy:render_engine_macro_orbits_fixture()bakes in macro pan "orbit" math, sampler contour/crunch sweeps, resonator damping/spark curves, and granular spray lanes, then dumps a 14k-lineengine-macro-orbits-control.txtledger so reviewers can diff every Euclid / Burst hit plus the automation snapshot that sculpted it. The Unity harness wires it up viatest_render_engine_macro_orbits_golden()sopio test -enative_goldenalways emits both the WAV and the control transcript. A fresh sibling,engine-multi-ledger.wav, keeps the Euclid math but cycles through the sampler/resonator/granular trio one hit at a time so the control log can double as a lesson plan. The helperrender_engine_multi_ledger_fixture()sweeps macro orbit and burst-density lanes per gate, writes the stereo WAV, then drops anengine-multi-ledger-control.txtledger that spells out pan, freq, env peak, macro orbit, and burst density for every Euclid strike. The Unity testtest_render_engine_multi_ledger_golden()registers it so CI uploads both artifacts whenever the golden env runs. - Layered Euclid/Burst capture:
layered-euclid-burst.wavnow rides shotgun with every golden run. The helperrender_layered_euclid_burst_fixture()walks a Euclid mask and hands each gate to the Burst engine so sampler, resonator, and granular voices all share the same schedule. The matching test (test_render_layered_euclid_burst_golden()intests/native_golden/test_main.cpp) keeps the WAV + control log wired into the manifest so reviewers can diff the Euclid/Burst event list and the per-frame modulation sweeps (tone,color, andspray) alongside the audio. - Hash discipline:
golden::hash_pcm16still mirrors the Python helper for PCM data, and a sibling FNV-1a byte walker fingerprints the log files. Both feed the same manifest so hashes stay in lockstep between test harness and CLI script. - Manifest:
tests/native_golden/golden.jsonstores the digest, artifact path, and either audio metadata (sample rate, frame count, channel count) or log metadata (line + byte counts). Optional notes keep the liner-book vibe intact, andscripts/generate_native_golden_header.pyrewritesfixtures_autogen.hppstraight from the manifest so Unity tests always pull the latest catalog without manual edits.
pio test -e native_golden
python3 scripts/compute_golden_hashes.py --writeThe native_golden env is just the standard native config with the flag wired
in, which keeps CI from caching a non-golden binary between runs.
(scripts/compute_golden_hashes.py insists on Python 3.7+, so lean on the
explicit python3 binary even if your shell still points python at the
ancient 2.x ghosts.)
Registry acting up or hacking offline? Run ./scripts/offline_native_golden.sh
to compile the standalone helper, regenerate every fixture, and refresh the
manifest without touching PlatformIO. It relies on the same render routines and
hash math, so the golden receipts line up exactly. The helper now pulls in the
heavy spatial renders (engine hybrid stack, macro orbit stack, the 7.1 bus) so
fallback runs never silently drop fixtures from the manifest.
If you mint a brand-new log fixture before updating golden.json, the helper
now scaffolds a placeholder spec instead of rage-quitting with
Missing log fixture spec.... That way a refresh can land the audio + log on
disk first, and you can rerun the hash tooling once you're ready to edit the
manifest/header.
Need the 30-second long-take collage specifically? Kick
tests/native_golden/render_long_take.sh. When PlatformIO is present it still
routes through pio test -e native_golden --filter test_render_long_take_golden,
but if the CLI is missing the wrapper now launches the same offline helper
described above without a filter. That means the empty build/fixtures/
folder on your desktop gets re-seeded every run instead of only refreshing
long-random-take.wav. If you really want to render a subset while offline,
call scripts/offline_native_golden.sh --filter ... directly so you stay in
control of the scope.
Add --note name="liner note" if you want to annotate why a render changed.
The script prints a tidy summary before committing anything to disk, so you can
spot-check hashes before rewriting the manifest.
Need to stage fixtures somewhere else while debugging? Pass
SEEDBOX_FIXTURE_ROOT=/tmp/seedbox-fixtures when running the tests. Pair it
with SEEDBOX_PROJECT_ROOT=/wherever/you/cloned/seedBox if you launched the
binary from an odd working directory and want to skip the auto-discovery.
The manifest continues to publish the canonical build/fixtures/... paths so
reviewers and automation stay in sync, but the raw files can live wherever keeps
your flow snappy.
- Layer more engines. Granular voices and the summing mixer are now in the gallery; the next frontier is pairing them with control streams (MIDI logs, modulation lanes) so reviewers get a full track sheet with each PR.
- Multichannel adventures. Stereo renders are live, so start sketching
surround/mid-side takes or alternate busses once the DSP matures. The
freshly added
surround-bus.wavis a six-channel proof-of-life that folds front mid/side energy into dedicated center/LFE lanes while crossfeeding the surrounds. - CI artifacts. The workflow now replays
pio test -e native_golden, regenerates the autogen header, and uploadsbuild/fixtures/*plus the refreshed manifest. Reviewers can grab the artifact bundle straight from the PR Files tab and spin the mix without cloning. - Docs to tests loop. Whenever you add a fixture, update this page and link directly to the test or example that produces it. Treat the roadmap like a lab book that references both the audio proof and the code sketch.
- GitHub keeps the golden fixtures under the workflow artifacts. Download the
native-golden-fixturesbundle from the PR checks page to hear the latest render set and read the manifest that stamped them.
- Rendering + assertions:
tests/native_golden/test_main.cpp - WAV helpers:
tests/native_golden/wav_helpers.* - Hash/manifest script:
scripts/compute_golden_hashes.py - Manifest source of truth:
tests/native_golden/golden.json