Repository navigation
Description
@repeat98 @timhastie: Mute Modes author here. Several Modwerk reports (#746, #419, #418, #407, #671, #673) say a muted FM Synth track keeps playing in Mute Modes' trig-mute modes. I've reproduced it in the emulator and traced it to how the two modules meet. Neither module is wrong on its own, but the fix needs one of you. Details and two fix options below.
Result
octabam port (ot_emu), remix MUTE_MODES + SYNTH MACHINE + SCALE QUANTIZER on stock effects (octabam 4781ca40; synth v2.9, mute-modes 8e00275). T1 = FLEX, FMSYNTH marker in slot 1, trigs on steps 1/5/9/13 with ATK 0 / HOLD 20 / REL 20 locks, nothing else playing. T1 muted at frame 2600 (MUTE_STATE 0x8000000a = 1); MUTE MODE poked per run. Peak level after each trig:
| after the mute | FM Synth on T1 | control: plain sine sample on T1 |
|---|---|---|
| not muted | −21.0 dBFS every trig | −23.4 dBFS every trig |
| DT-T | −21.0 dBFS on every muted trig | silent |
| OTFX-T | −21.0 dBFS on every muted trig | silent |
| OT | silent | silent |
| OTFX | silent | silent |
- Each muted trig is a new note: the track falls to −100…−120 dBFS between trigs (HOLD 20 / REL 20 end each note), then comes back at full level.
- Mute Modes does drop the trigs: its dispatch gate (
dt_silence) fired on all 4 muted trigs in both trig-mute modes. - The synth starts a note anyway:
sy_coldran 6 times in every run, muted or not (once per trig).
Why
- Every sequencer trig ORs the START bit (0x10) into the live byte
0x46104d15[t]at stock0x4000b9bc. The frame builder copies it to the packer's event byte0x46104d0c[t]at0x4000c642. - Mute Modes' trig-mute modes (DT-T, OTFX-T) leave that bit alone. They block what stock does with it later in the frame: the per-machine trig dispatch
jsr (a0)at0x4000d49c, the voice bind /FUN_4000672cstart in0x40006820/0x40006844, the DSP trig-flag word at0x40004c72, and the arena rebind at0x4000f4dc. That's enough for every stock machine. - FM Synth's
sy_renderis the renderer the packer calls at0x4000d43e, which is before the dispatch at0x4000d49c. It testsNIBBLEbit 4 itself and starts a note (sy_cold/po_start). Since 2.9 the engine also holds the DSP voice open (ATK/HOLD/REL forced to 0/INF/INF), so the new note is heard. The stock path never gets that far on a muted track.
OT and OTFX are unaffected because they cut gains rather than block trigs.
Fix options
A. Synth side (preferred). Before sy_cold / po_start act on a START, ask whether the trig was suppressed. On Modwerk the hook already exists in spirit: Mute Modes answers ev_voice_bind with "drop" (mm_voice_bind) for a muted track in DT-T/OTFX-T. Jannik, you know best whether the synth should raise that event, or whether a small dedicated "is this track's trig suppressed?" event is cleaner. I'm happy to have Mute Modes answer whatever you define. This keeps the mute rule in one place, and covers any future machine that reads the START bit.
B. Mute Modes side. Clear bit 4 at its source for a silenced track in DT-T/OTFX-T, so every reader sees no START. This touches several writers (0x4000b9bc, plus the frame builder's 0x10 | n posts around 0x4000bd74 / 0x4000bdc0), and the copy at 0x4000c634 is exactly where po_retrig is detoured. It would also change behaviour Mute Modes has confirmed on hardware, so it means re-validating every mode, plus re-pins in KYOTI, octabam and Modwerk. Possible, but heavier.
Related, not yet tested: for a muted track in DT-T/OTFX-T, Mute Modes skips stock 0x40006820 (voice reset/kill) entirely. That also skips the synth's po_kill at 0x4000685c. It didn't matter in this test (finite HOLD), but STOP on a muted synth track at HOLD INF is worth a check whichever fix lands.
Meanwhile
I'm telling reporters to use OTFX or OT on FM Synth tracks until this is fixed. I can re-run the repro on any candidate fix. The fixture recipe and emulator command lines are below, and I can share the scratch scripts.
Repro recipe
- Fixture: any 1.40C project; FLEX slot 001
PATH=../AUDIO/FMSYNTH.WAV(4 s of silence), T1 FLEX slot 1 in every Part, pattern A01 T1 trigs 1/5/9/13 with locks ATK(12)=0 HOLD(13)=20 REL(14)=20, all other trigs and locks cleared (tools/hw/ot_bank.py/ot_project.pylayouts);stage_card.py ... --audio "FMSYNTH.WAV:AUDIO/FMSYNTH.WAV". - Run:
ot_emu --image <remix> --card <card> --set OCTABAM --project <name> --sequencer --internal-clock --dsp --main-level 64 --load-ms 90000 --audio-out <boot> --watch-pc <sy_cold>,<dt_silence> --scenario "<log> --step -:poke:0x800000df=<0..3> --step 2600:poke:0x8000000a=1 --frames 7000 --audio-out <prefix>". MUTE MODE word low byte: 0 OT, 1 OTFX-T, 2 DT-T, 3 OTFX. - Note: calling
0x40083ab4(0x10,1)does not set0x80000008in the port; poke the mute byte directly.
Activity
timhastie commentedon Oct 24, 2026
Confirmed. The FM synth makes its own sound, and the mute only stops the sample player, so the FM voice keeps playing. The fix is to make the synth engine obey the track mute. I will build it when Modwerk confirms the new Octatrack base and how it handles mute, so it is done once and in the right place.
repeat98 commentedon Oct 25, 2026
Thanks both. Tim: nothing changes in how FM Synth registers with the base, so build against the current beta base the way 0.1.2 does. For the mute: Mute Modes already answers the base's ev_voice_bind, but the synth starts its note before stock gets there, so it can't use that as is, and a module can't ask another module directly. I'll add a small base query, "is this track's trig muted?", that Mute Modes answers and any machine can ask. I'll tag you both on that PR so FM Synth can use it.
timhastie commentedon Oct 26, 2026
Thanks both! I've answered on #912: FM Synth 0.1.4 will use ev_trig_muted once it lands.
Improvement: Octatrack base answers "is this trig muted?" for machine…
repeat98 commentedon Oct 26, 2026
@timhastie @Zac-Kyoti the base query is live in today's beta base (c1ae2ee9): ev_trig_muted at hook index 35, as described in #912. FM Synth can ask it and Mute Modes can answer it; with either one missing nothing changes. I'll close this once both releases are out.
timhastie commentedon Oct 26, 2026
Thanks Jannik! FM Synth 0.1.4 will raise it, and I'll test the pair against today's base.
repeat98 commentedon Oct 27, 2026
A finding from the USB beta base, not yet reproduced: a beta tester reports that a muted FM Synth track still sounds with MUTE MODE OTFX (27 Oct 2026, FM Synth 0.1.2, Mute Modes 0.2.1). The table above, measured on a card build in the emulator, had OTFX silent.
p1_otfxinpatch_softmute.s).ev_trig_mutedalone won't cover OTFX.The workaround until then is MUTE MODE OT.
timhastie commentedon Oct 28, 2026
I checked this on the emulator with my FM Synth card build plus Mute Modes 0.2.1 installed. OT and OTFX both silenced the FM track: every post-mute trigger window measured digital zero. With DT-T and OTFX-T, sound came back on all four post-mute triggers once the previous sound had decayed.
I also tried the OTFX mechanism directly on a plain FM image, zeroing the VOL/XVOL halfwords at byte offsets +6/+10 every frame. That cut the sustained FM output to digital zero apart from a short onset transient, so FM does not bypass those words. FM's only direct writes to the parameter record are the envelope fields at byte offsets 0/2/4, and it publishes an ordinary source header.
So I have not reproduced the OTFX leak on the emulator. The retriggering in the -T modes is the known trig-mute gap that 0.1.4 closes by raising ev_trig_muted, with Mute Modes as the responder; these are measurements of the current 0.1.2-era behaviour, not verification of that fix over USB or on hardware.
Was the tester using OTFX or OTFX-T, and was it the 0.1.2 USB package? If you can point me at the USB build, I will test it.
repeat98 commentedon Oct 29, 2026
Thanks Tim, that's a careful check, and it matches Zac's table: OT and OTFX silent, the -T modes retrigger until 0.1.4 asks ev_trig_muted.
The tester's report was from the USB beta: FM Synth 0.1.2's USB package with Mute Modes 0.2.1, on a beta base from 27 Oct, and they said OTFX. I'm checking with them whether it might have been OTFX-T, which would explain it. You can test the same package by syncing FM Synth and Mute Modes from the Octatrack page on modwerk.app to a unit on the current beta base (9b7e0eb3). Until we know more, the workaround stays MUTE MODE OT.
repeat98 commentedon Oct 30, 2026
@timhastie, @Zac-Kyoti, one catch I missed:
ev_trig_mutedis a base event, and card builds have no base events (#912), so it only works over USB. But FM Synth's USB package stays at 0.1.2, as I said on #555, so as planned 0.1.4's ask reaches nobody. The same goes for the LFO 3 fix (#932) and the envelope fixes (#883): they would reach card builds only.Tim, could 0.1.4 also ship a slim USB package: 0.1.2 plus the
ev_trig_mutedask and the stock LFO 3 depth read, without the new lock tables? Zac, Mute Modes still has to answer the event: could your next version add the handler, using the same per-track test as yourev_voice_bindhandler?sdk/machines/octatrack/HOOKS.mdhas the contract. On card builds the -T modes still need a native answer, so that half stays open here.timhastie commentedon Oct 30, 2026
Thanks Jannik. I'd be OK with a slim USB package, 0.1.2 plus the
ev_trig_mutedask and the stock LFO 3 depth read, if the site makes clear that it isn't the same as the card build. Could the module page and the sync dialog say when the USB package is an older version than the card build, with thelagReason? Otherwise USB users on FM Synth 0.1.2 will read 0.1.4's description and expect the step and scene locks on every FM control, the chord and envelope fixes and the rest of 0.1.4's changes.I'd still like the full 0.1.4 over USB. On #555 you said that the loader won't get multi-MB DRAM regions for now, and that FM and SY DRUM could share one lock table later. I'm happy to do the base work for the memory when you're ready for it: the loader's own note says arena pages once the OS's page allocator is audited, and I could take that audit and the PR, or a fixed reserve at boot if you'd rather. Just say which, or if you'd rather do it yourself. The lock-table merge and the
fm_runtime.pyupdate for 0.1.4's sources are mine either way.On the muted trigs, agreed: Mute Modes answers the event over USB, and the card half stays open here.
Improvement: say when a module's USB package is older than its card b…
repeat98 commentedon Nov 1, 2026
Hi Tim, #1133 adds that: the module page and the sync dialog now say "Over USB this installs : ". So the slim USB package can go ahead, with
lagsBehindset and alagReasonwritten for players.repeat98 commentedon Nov 3, 2026
A second report, #1177, settles the OTFX question: on a card build with FM Synth 0.1.2 and Mute Modes 0.2.1, every mute mode except plain OT lets FM Synth's notes through, so OTFX leaks as well as the -T modes, and on card builds as well as over USB. @Zac-Kyoti @timhastie, since card builds have no base events,
ev_trig_mutedalone won't cover them.timhastie commentedon Nov 6, 2026
Right,
ev_trig_mutedcan't reach card builds. On my own line (2.19 onwards, in v2.21) the engine handles this natively when Mute Modes is in the build. It reads Mute Modes' MUTE MODE word and mute state, drops the note in DT-T and OTFX-T, cuts a sounding note at the OTFX-T edge, and ends voices at STOP. FM Synth 0.1.4 leaves that code out on Modwerk because of the rule that a module may not read another module's code or data. On a card build every trig therefore still plays.I see four ways to close the card half:
ev_trig_mutedin the shared SDK, which Mute Modes answers and FM Synth calls. That means one SDK PR plus a release of each module. I can write my side.I'd suggest 1, or 2 if you'd rather keep modules apart. Which do you prefer?
On #1177's OTFX leak: in my emulator tests OTFX stays silent on my line, so I'd like to reproduce it with the reporter's exact module set first.
repeat98 commentedon Nov 7, 2026
Thanks Tim, four clear options.
Option 1 is out, sorry: under the no-dependency rule a module can't read another module's words, even stable ones. Let's take option 2: a card-build counterpart of
ev_trig_mutedin the shared SDK, in its own SDK pull request first, the same way as the shared scale file on #1145. Mute Modes answers it, FM Synth asks it, and with either one missing nothing changes. If you'd like to write the SDK part, go ahead and tag me.Meanwhile 0.1.4 ships as it is (option 4), with a note that FM tracks on card builds need MUTE MODE OT for now.
@Zac-Kyoti, are you OK with Mute Modes answering it, on card builds through the SDK and over USB through
ev_trig_muted? And Tim, reproducing #1177's OTFX leak with the reporter's set first sounds right.Zac-Kyoti commentedon Nov 7, 2026
@repeat98 @timhastie Yes, Mute Modes will answer it: on card builds through the SDK counterpart, and over USB through
ev_trig_muted. Three things from my side:mm_voice_bind. The answer will be exactly the per-track test Mute Modes'ev_voice_bindhandler makes (fresh_bind): muted or soloed-out tracks in DT-T and OTFX-T, less a SIDE-CHAIN key track (KEYMASK/KEYHOLD). That way the two can never disagree about which trigs are dropped.ev_trig_mutedhandler and Octatrack base: PERSONALIZE rows as a base table (ot_personalize_rows), so table owners no longer pin package hashes #1023's row in one release (0.2.3), so there's one declaration, one base and one review. I'll write our side once the card-build SDK contract is up; please tag me on that PR.0x40006820is skipped, and the synth'spo_killwith it. So STOP on a muted FM track at HOLD INF is worth a check with the fix.Until both releases are out, MUTE MODE OT remains the workaround for FM tracks.
timhastie commentedon Nov 8, 2026
Thanks both. I checked #1177 with the reporter's exact set: my build matches their fingerprint, 9de69b8c…. I ran it in the emulator on an MKI, on FM Synth 0.1.2 and 0.1.4, muting an FM track and a Flex track with FUNC+track while playing.
An image with only Synth 0.1.2 and Mute Modes 0.2.1 behaves the same. So I can't reproduce the OTFX leak, which matches Zac's point 3. My guess is that the reporter was in OTFX-T (the menu order is OT, OTFX, OTFX-T, DT-T) or was hearing FX tails. Jannik, could you ask them which mode it was and which FX are on the FM track?
The SDK part is up as #1312. Zac, there's one thing in it for you. Dropping new trigs doesn't end a note that is already sounding at an OTFX-T mute, so the PR adds a second byte for "cut the sounding note now". I'd like your OK on that. On your STOP point: with prototypes of both sides, a muted FM note at HOLD INF ends at STOP.