Skip to content

Fix: Octatrack base, a FLEX <-> module machine switch stops the track's stale stock voice (first-trig stutter) - #1032

Merged
repeat98 merged 11 commits into
repeat98:mainfrom
npp1993:fix/ot-switch-stale-voice
Oct 29, 2026
Merged

repeat98 merged 11 commits into
repeat98:mainfrom
npp1993:fix/ot-switch-stale-voice

Conversation

@npp1993

@npp1993 npp1993 commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator
  • What was wrong or hard: On a MKII, switching a track from Analog BD back to FLEX while the pattern plays made the first FLEX trig stutter (a short double hit or a cut); later trigs were fine. A module machine is FLEX underneath, so every one of its trigs also starts stock's FLEX voice from the machine's bytes read as FLEX settings, and the machine's own render never advances that voice. Nothing stopped it when the track left the machine: Analog BD's ot_machines record has no leave, the base's leave() only puts FLEX defaults back, and stock's parameter load (0x40001f18, disassembled to check) only rewrites parameters and never touches the per-track voice records at 0x800049d8 + 168 × track; voice bind (0x40006820) runs only where a commit changes the type. So the stale voice played as a short wrong burst that the first real trig cut or played over. The static Analog BD 0.1.6 draft closes the same gap with clr.b on byte 0 of that record (one MKII pass on image AB015FX4).
  • What this changes: machine_registry.c hush(): when a switch keeps the stored type (FLEX ↔ module machine, the playing Part only) mw_assign clears byte 0 ("playing") of the track's voice record before the track's parameters change, on all three paths (machine chosen, machine left, an absent machine). A type change (STATIC and the other stock machines) stays stock's. On Octatrack base: module machines play right after a boot, the FLEX switch reloads live parameters, SRC label after a boot; USB bridge opens the Octatrack #1024's relive() the same clear belongs just before the stock reload; the source merges cleanly with that branch. Changelog changelog/2026-10-28-octatrack-switch-first-trig.md. Beta base regenerated.
  • How I checked it: npm run pr:ready; test_machine_registry.c maps the voice records and covers Analog BD → FLEX (cleared before the reload, the byte 1 of a neighbouring track untouched), FLEX → FLEX and the same machine again (unchanged), FLEX → Analog BD (cleared), Analog BD ↔ STATIC (not cleared), an absent machine, and a Part that is not playing; making hush a no-op fails four checks. Not yet on a unit: an MKII run of Analog BD → FLEX and FM Synth → FLEX in a full project is still needed.
  • What the guides lacked or got wrong, and where I fixed it: nothing.

Independent of #1024 and #944; whichever lands later regenerates the base.

🤖 Generated with Claude Code

npp1993 and others added 4 commits October 28, 2026 09:18
…'s stale stock voice

Every trig on a module machine track (Analog BD, FM Synth) also starts
stock's FLEX voice from the machine's bytes read as FLEX settings, and
the machine's own render never advances it. Nothing stopped that voice
when the track left the machine, so after a switch back to FLEX while
playing it sounded as a short wrong burst that the first real trig cut
or played over. mw_assign now clears byte 0 ("playing") of the track's
voice record (0x800049d8 + 168 * track) when a switch keeps the stored
type (FLEX <-> machine, the playing Part only), before the track's
parameters change; a type change stays stock's. Host test covers both
directions, the same machine again, FLEX to FLEX, STATIC, an absent
machine, another track and a Part that is not playing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…oice

# Conflicts:
#	sdk/machines/octatrack/base-binding.json
#	src/engine/assets/octatrack-base-variants.json
#	src/engine/assets/octatrack-base.elemod
#	src/engine/assets/octatrack-module-packages.json
… main

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions github-actions Bot added the bug Something isn't working label Oct 28, 2026
@repeat98

Copy link
Copy Markdown
Owner

Thanks, good find, and the host test that maps the voice records is just what I'd want.

Two things before it goes in:

  1. It needs a unit run. Please run Analog BD → FLEX and FM Synth → FLEX while the pattern plays, as you planned. Please also check POLY8 → FLEX and VECTOR → FLEX: those two have their own assign, so hush doesn't run when a track becomes one of them (machine_registry.c:307-308), but it does run when a track leaves them (:323). Their tracks play through stock's FLEX voice, so leaving one now cuts the note that's sounding. That's probably fine, but I'd like to hear it once.
  2. Octatrack base: module machines play right after a boot, the FLEX switch reloads live parameters, SRC label after a boot; USB bridge opens the Octatrack #1024 changes the same three paths in mw_assign (its relive()). The two merge without conflicts, but they've never run together. Since both are yours, either put the clear into Octatrack base: module machines play right after a boot, the FLEX switch reloads live parameters, SRC label after a boot; USB bridge opens the Octatrack #1024 and close this, or give me the order you'd like and I'll rebuild the base once for both. I'd rather ship one base than two.

A minor point: hush runs from the UI task with interrupts on, so a trig that the frame interrupt starts at the same moment could be cleared. That's a single byte and very unlikely; a line in the comment saying it's acceptable is enough.

npp1993 and others added 7 commits October 29, 2026 03:24
…able

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…-stale-voice

# Conflicts:
#	sdk/machines/octatrack/base-binding.json
#	src/engine/assets/octatrack-base-variants.json
#	src/engine/assets/octatrack-base.elemod
#	src/engine/assets/octatrack-module-packages.json
… main (Analog BD 0.1.6)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…oice

# Conflicts:
#	sdk/machines/octatrack/base-binding.json
#	src/engine/assets/octatrack-base-variants.json
#	src/engine/assets/octatrack-base.elemod
#	src/engine/assets/octatrack-module-packages.json
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@repeat98

Copy link
Copy Markdown
Owner

Tested on an MKII (OS 1.40C) over USB, 29 Oct 2026, as an A/B against current main.

Builds: two --dev twins with the beta base's flags, one from main 5d83d27 (07ce064e…) and one from this branch 1b1ad43 (9d952fcd…). Analog BD 0.1.6 was rebound to the twins, and FM Synth 0.1.2 is the published package.

Run: T2 is a FLEX track playing a kick sample on trigs. Play, then switch T2 FLEX → FM SYNTH → FLEX three times, 6 s apart (FUNC+SRC, YES), while recording all 20 USB channels. Same script and same project on both twins.

FM Synth → FLEX: fixed.

  • Before the first switch, the two recordings of T2 are identical (within 2.5e-5).
  • On main, after each switch to FLEX (3 of 3), the old FLEX voice keeps sounding: a steady 271 Hz tone at about -36 dBFS (the FLEX voice looping with FM Synth's bytes as its settings). It lasts until the next trig gets through or the next machine change, up to 6 s. In an earlier main run, one switch instead gave a short decaying burst just before the first kick.
  • With this branch, T2 is exactly silent from the moment of each switch (3 of 3).

Not caused by this branch: after an FM Synth → FLEX switch, the first FLEX kicks come back late (2.5 s or more, once not for 5 s). That happens at the same moments on both twins. It looks like the live parameter reload #1024 addresses.

Analog BD → FLEX: not judged. With this short kick sample, main leaves nothing audible after an Analog BD → FLEX switch either. Also, that switch while playing stopped the DSP in 2 of 3 runs, on both twins, so it is older than this branch: #1051.

@repeat98
repeat98 merged commit 3b79e79 into repeat98:main Oct 29, 2026
8 checks passed
repeat98 pushed a commit that referenced this pull request Oct 30, 2026
…X no longer stops the DSP

Each trig on a module machine track starts stock's FLEX voice from the
machine's bytes, and the machine's render never advances it. #1032 stops
that voice in mw_assign, but a bank, pattern or Part change makes the
track FLEX without mw_assign, and stock then rendered the stale voice.
On a track that had been Analog BD since power-on, the first FLEX frame
stopped DSP core 1 for good (MKII, cold boot, Analog BD on T1 in bank B,
FLEX in bank C, PLAY, B -> C: every time; not with T1 played as FLEX
first, and not with Analog BD on T1 in both banks).

mw_source_render_impl now clears byte 0 of the track's stock voice record
on every render a machine does itself, and on an absent machine's silent
render. Machines without their own render (VECTOR, POLY8) keep stock's
voice. Host test covers the machine's renders, a trig between them, the
Part changing under the track, VECTOR, a FLEX track and an absent machine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@npp1993
npp1993 deleted the fix/ot-switch-stale-voice branch October 30, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants