Summary
Chris Hülsbeck's Dynamic Synthesizer — his pre-TFMX Amiga music format — was added to the libtfmxaudiodecoder backend in v1.0.10. We were pinned at v1.0.7, so the app didn't recognise or play it. This bumps the vendored decoder to v1.0.14 (latest — since we recompile the wasm from source, adopting the newest costs nothing extra and brings all the intervening playback fixes) and widens the pair-recognition routing.
Status: ✅ Implemented on main (#104 routing, #105 decoder bump + naming fix, #106 tests). Pending a production deploy to mods.amiga.fans.
Kudos 🙏
Huge thanks to @mschwendt, maintainer of libtfmxaudiodecoder, whose v1.0.10 release added the Dynamic Synthesizer decoder — and who keeps improving TFMX / Hippel / Future Composer playback for the whole retro-audio community (v1.0.11–v1.0.14 alone added Turrican III support and a string of soundtrack fixes). CoolModFiles' entire TFMX playback path stands on that work.
The format
- Data + samples pair, Amiga prefix style:
dns.<base> (music data) + smp.<base> (samples).
- Recognised as a fourth pair naming convention alongside the existing
.tfx/.sam, mdat./smpl., .mdat/.smpl — no new source type.
- A tiny, self-contained corpus: per the upstream release notes, only three soundtracks were ever made in this format before Hülsbeck moved to TFMX — Hollywood Poker Pro, Starball, and PTC (Danubius). See Modland.
What shipped
- Bumped the vendored decoder v1.0.7 → v1.0.14 and rebuilt the wasm worklet. Beyond Dynamic Synthesizer (added in 1.0.10), this picks up playback fixes the old pin was missing — notably the v1.0.9 correction of a v1.0.4 "loop mode" regression that shortened some song durations, plus Turrican II / R-Type fixes and Turrican III support (1.0.14). The bump is worthwhile on its own merits; Dynamic Synthesizer rides along.
- Recognised
dns./smp. as a fourth pair naming convention — a ~2-line addition to the single shared parseHalfName, which every downstream consumer (local drop, library scan, byte-server partner gate, folder auto-advance) inherits automatically.
- Widened the byte-server allowlist to
dns.* / smp.*, subject to the existing orphan-half rejection.
- Taught the worklet to write DNS pairs under
dns./smp. MEMFS names (see the finding below).
The one non-obvious finding
The initial assumption was that DNS would decode through the existing pair path, which normalises both halves to .tfx/.sam on the in-memory FS. It doesn't — verified against a real Modland dns.ptc/smp.ptc pair, tfx_load returns 0 under that naming. libtfmx's Dynamic Synthesizer decoder discovers its sample bank by the dns↔smp filename token, not the .tfx→.sam extension guess the Hülsbeck-TFMX conventions use. So the worklet now writes DNS pairs as dns.<base>/smp.<base> (driven by a dns flag on the play message). Verified end-to-end: the pair plays through the app's tfmx-library path; FC/Hippel regression clean.
Notes
Summary
Chris Hülsbeck's Dynamic Synthesizer — his pre-TFMX Amiga music format — was added to the libtfmxaudiodecoder backend in v1.0.10. We were pinned at v1.0.7, so the app didn't recognise or play it. This bumps the vendored decoder to v1.0.14 (latest — since we recompile the wasm from source, adopting the newest costs nothing extra and brings all the intervening playback fixes) and widens the pair-recognition routing.
Kudos 🙏
Huge thanks to @mschwendt, maintainer of libtfmxaudiodecoder, whose v1.0.10 release added the Dynamic Synthesizer decoder — and who keeps improving TFMX / Hippel / Future Composer playback for the whole retro-audio community (v1.0.11–v1.0.14 alone added Turrican III support and a string of soundtrack fixes). CoolModFiles' entire TFMX playback path stands on that work.
The format
dns.<base>(music data) +smp.<base>(samples)..tfx/.sam,mdat./smpl.,.mdat/.smpl— no new source type.What shipped
dns./smp.as a fourth pair naming convention — a ~2-line addition to the single sharedparseHalfName, which every downstream consumer (local drop, library scan, byte-server partner gate, folder auto-advance) inherits automatically.dns.*/smp.*, subject to the existing orphan-half rejection.dns./smp.MEMFS names (see the finding below).The one non-obvious finding
The initial assumption was that DNS would decode through the existing pair path, which normalises both halves to
.tfx/.samon the in-memory FS. It doesn't — verified against a real Modlanddns.ptc/smp.ptcpair,tfx_loadreturns 0 under that naming. libtfmx's Dynamic Synthesizer decoder discovers its sample bank by thedns↔smpfilename token, not the.tfx→.samextension guess the Hülsbeck-TFMX conventions use. So the worklet now writes DNS pairs asdns.<base>/smp.<base>(driven by adnsflag on the play message). Verified end-to-end: the pair plays through the app'stfmx-librarypath; FC/Hippel regression clean.Notes