Skip to content

FM Synth 0.1.3 (draft): cheaper on tracks that don't use it - #1473

Closed
repeat98 wants to merge 3 commits into
mainfrom
module/fm-synth-0.1.3
Closed

repeat98 wants to merge 3 commits into
mainfrom
module/fm-synth-0.1.3

Conversation

@repeat98

Copy link
Copy Markdown
Owner

Draft, work in progress: an optimisation of FM Synth's render path, to be released as 0.1.3-experimental. No function changes; FM Synth is Tim Hastie's module, so this only makes the existing behaviour cheaper. Not ready to merge (see "Still to do").

Why

A tester reported a laggy unit with Amiga and FM Synth installed (SELF TEST: CPU 100 %). FM Synth costs frame-interrupt time on every sample track even when no track uses it: its render is called for every STATIC and FLEX track, and each call tested "is this an FM track" by reading the Part index from battery RAM (about 0.5 µs a read), two or three times a track, plus the GLIDE byte once.

What changes (upstream/synth/poly.s)

  • One read a frame. The Part, GLIDE and each track's FM test are read at a frame's first use (fm_fr_sync, fm_fr_native), keyed on the frame builder's ping and refreshed after 128 uses in any case. Only the render path uses them; the panel, key and MIDI hooks still read the Part themselves.
  • Stock renders what the engine would not change. At sy_render, a track that is not FM, holds no synth voice, has GLIDE off and starts no voice in this call goes straight to stock's renderer. With GLIDE on, or when a legacy FMSYNTH sample starts, the original path runs as before.
  • machine-ports.json and machine-recipes.json: the port's source pin and the recaptured recipe (38 copies, no fills, as before).

Measured

Owner's MKII, a dev twin of the base at main 18b1cceea, one busy project (the one loaded that day), FM Synth on no track, npm run device -- guard:

Build Stopped Playing
No FM Synth 30.2 % 66.8 %, longest frame 102-113 %
FM Synth 0.1.2 42.8 % the unit froze on PLAY (power cycle)
This branch 37.6 % 73.5 %, longest frame 139 %, the guard skipped renders on all eight tracks

The stopped figures were taken after playing, in the order none, 0.1.2, this branch; treat them as indicative.

A sampling profile of the playing unit puts the remaining 6.7 points at about 3.6 in the module's own hooks and about 3.8 in the base, mostly guarded() in machine_registry.c: with a RENDER_FLEX machine installed, every FLEX render is timed. That is base work for its own pull request and the next base.

Still to do

  • Listen on the unit: FM tracks (notes, chords, glide with LEG), GLIDE on a FLEX and a STATIC sample track, a legacy FMSYNTH sample, a track changed from FM back to FLEX.
  • A clean A/B on a lighter project where 0.1.2 also plays.
  • Version 0.1.3-experimental, release notes, README and TESTING, packages, module:doctor, pr:ready.
  • Tell Tim Hastie (the engine's author) before release.

Tried and dropped

Leaving unowned FLEX tracks to stock (no RENDER_FLEX) measured 69.4 % playing, but removes GLIDE on FLEX sample tracks and the legacy FMSYNTH samples. Not acceptable for another author's module.

What the guides lacked

docs/MODULE_PERFORMANCE.md names the battery-RAM reads but not the base's cost for a RENDER_FLEX machine; to add once the base side is settled.

🤖 Generated with Claude Code

…d each track's FM test once a frame, and stock renders a track the engine would not change

Installed on no track, FM Synth cost points of every frame on every sample
track: its test for an FM track read battery RAM two or three times a track,
and GLIDE once. The reads are now taken at a frame's first use, and a track
that is not FM, holds no synth voice, has GLIDE off and starts no voice goes
straight to stock's renderer. No function changes.

Not yet a release: no version, release notes or TESTING entry; not heard on
an FM track. The machine port's pin and recipe follow the changed source.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
repeat98 and others added 2 commits November 13, 2026 10:03
… measurements, USB package

No function changes. The package is the build of ed6188e's source and is
byte-identical after merging main. Listening checks on the unit are still
open and listed in TESTING.md. The package manifest row and the machine
recipes are left to the combined base branch, which recaptures them once.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@repeat98

Copy link
Copy Markdown
Owner Author

Closed into #1502: all changes that need a new Octatrack base go out as one base update. This branch is merged there with its commits, and its description and test notes are carried over.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant