Skip to content

Octatrack: SYNTIZ 0.1.0-experimental, out of drafts - #1304

Merged
repeat98 merged 16 commits into
repeat98:mainfrom
stigmagit:module/syntiz
Nov 11, 2026
Merged

repeat98 merged 16 commits into
repeat98:mainfrom
stigmagit:module/syntiz

Conversation

@stigmagit

Copy link
Copy Markdown
Contributor

Octatrack: SYNTIZ 0.1.0-experimental, out of drafts

SYNTIZ is a track machine for the Octatrack MKII: choose it in the machine chooser (FUNC + SRC) and a double tap of
the track key opens six models: SAW, PULSE, ENS, TABLE, MORPH and CHOIR. The track's own filter, AMP, LFOs and
effects shape it as they do a sample, and PTCH plays like FLEX (chromatic keys, scales, locks). It is a Modwerk USB
package only (no card build). The engine and the 32 single-cycle tables are the author's own, computed from formulas
(tools/make_tables.py); nothing is taken from another product.

It has been a draft since #1028 (29 October); #1107 added the limit below. This PR moves it to
sdk/octabam/modules/syntiz, with its manifest, UI captures, release notes, USB package row (f501a6a4, rebuilt
byte for byte by octatrack:module-packages -- --check) and the evidence below. The Part signature WV is now
declared in the package row and the PROTECT test reads it there (as you suggested on #1031).

The limit: three SYNTIZ tracks a Part

A fourth track is refused (wave_admit_track, #1107); a Part saved with more plays on as it was. The reason is the
ColdFire: every SYNTIZ track renders its 16 samples in the frame interrupt, and one render takes about 15 % of a
frame, up to 37 % when it follows stock's trig work in the same frame. Measured on the author's MKII with the base's
frame guard (80 % share), 120 s a run:

Set Frame interrupt without SYNTIZ With SYNTIZ Longest frame Renders dropped
3 heavy SYNTIZ tracks + 4 long samples (3 Nov) 36 % 67-69 % 108-112 % 24-75 per run, a crackle the author hears
Live set: THRU, 2 samples, SAW heavy with filter and chorus, TABLE with filter and chorus, NEIGHBOR + flanger, master compressor (7 Nov, played by hand) 34 % 69 % 111 % 0, clean
The same with a third sample (7 Nov) 36 % 74 % 114 % 259 in 120 s (about 2 a second, 16 samples each), not heard

So two heavy SYNTIZ tracks fit a busy set; three heavy ones with long notes can crackle; a fourth sample or an ENS
does not fit the third row's set. The guard drops a render rather than overrun, which is what keeps the unit from
freezing.

Where the numbers come from

Everything above is from the author's own development twins of his private base (7bce173d, 8af4f9a3, 04e94075;
his flashed base 86388105 is Modwerk's base of 31 October with --raise and a start logo), package f501a6a4,
his own sets, one run per case. Not Modwerk's beta base, and not a second person's unit with a second set. On 3
November the same run repeated gave 24 to 75 dropped renders, so a count is coarse. TESTING.md lists every run and
evidence/hardware.md the dated table.

One finding for module authors

With FM Synth 0.1.2 installed beside SYNTIZ and never played, the SYNTIZ tracks crackled very lightly and the third
sample no longer fit. Removing FM Synth cured both (A/B on the same flashed base, 7 November; mechanism unknown).
An installed but idle module may cost a frame share; see the note for Jannik in the PR comment / guide proposal.

Not tested

  • The MKI; a mute module's muted trigs (SYNTIZ asks the base through ev_trig_muted); a MIDI flood.
  • A static cycle bound: under qemu the heaviest render is 6,372 instructions, but on the unit it costs 2.5 to 8.8
    cycles an instruction, so the bound is not defensible.
  • A stress run of eight tracks with LFOs and locks.
  • The reason a render after stock's trig work costs up to 2.4 times a first one (not the code size, not the samples'
    starts, not stock's START): open.

Request: a waiver for qualifying a heavy machine

npm run module:doctor -- syntiz fails exactly three performance rows, and I did not move the audit's limits:

  1. Static bound missing (cycles.static): see above.
  2. The 10 % rule: with the live set, the longest frame interrupt grows by 37.8 us (10.4 % of a frame) and idle
    falls 37.5 points against the same set without SYNTIZ. A machine that renders audio on the ColdFire adds that by
    design.
  3. Stress: no MIDI flood (SYNTIZ has no MIDI path of its own; notes reach it through PTCH as for FLEX), and the
    run is the author's live set for 120 s, not the audit's flood at 240 BPM. Three instances are claimed
    (maxInstances: 3, the Part limit); one render is the event, and three second-call renders in one frame would sum
    to 106,608 cycles of a 95,782-cycle frame, which the guard handles by dropping one.

I asked @repeat98 by DM on 31 October how a machine like this should be qualified and have no answer yet. The release
needs your decision: a waiver for these three rows at this exact version (sdk/*-build-approval.json, which only you
can add), or the measures you would rather see. module:doctor and npm run check stay red on them until then; the
rest of check is green, and modules:check passes (qualification, memory, hardware report, documentation).

Other changes in this PR

  • machine_registry.c comment and test_machine_events.py: a native module's PROTECT signature comes from its
    package row; the draft FRACT stays named in the test until it has a row. Beta base regenerated for the comment.
  • module-set.test.ts: syntiz among the USB module ids.
  • pr:ready renewed the author's claim module octatrack/syntiz on the agent board.

What the guides lacked or got wrong

Not edited in this PR. Two gaps found: the performance audit has no honest place for a machine whose cost is a share
of the frame and not a per-event cost (what an "event" and an "instance" are for a track machine, and what static bound
a ColdFire render can have once cache and the bus matter); and nothing tells a module author that an installed idle
module can take another's margin. Both belong in docs/module-guides/machines.md; I would write them once you have
decided the first.

🤖 Generated with Claude Code

stigmagit and others added 4 commits November 7, 2026 14:48
Moves SYNTIZ from sdk/drafts to sdk/octabam/modules/syntiz with its manifest, media, USB package row
(f501a6a4, three tracks a Part) and release notes. The Part signature is read from the package row by the
PROTECT test. README, TESTING and evidence record the author's 31 October to 7 November MKII runs on a
named package and base: the live set at 74 % of a frame, the dearest render at 37 %, the FM Synth A/B.
The performance record fails the audit's static-bound, 10 % and MIDI flood rules; the pull request asks
the owner for a waiver.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…un octatrack:base -- --beta --write, octatrack:module-packages); syntiz among the USB module ids

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@stigmagit

Copy link
Copy Markdown
Contributor Author

@repeat98

Hi Jannik, a finding from SYNTIZ's measurements that may belong in the module guide.

On my MKII, FM Synth 0.1.2 installed beside SYNTIZ and never played made the SYNTIZ tracks crackle very lightly, and the
third sample track in my live set no longer fit. Removing FM Synth cured both. It was a clean A/B on the same flashed
base and the same set (7 November): with FM Synth installed, a light crackle; removed for a 180 s trial, none; removed
for good, the complete set (THRU, three samples, SAW, TABLE, NEIGHBOR, master compressor) holds. SYNTIZ alone then runs at
74 % of the frame with 259 renders dropped in 120 s, which I do not hear.

So an installed module that is never used can cost about a sample track's worth of margin. I do not know the mechanism:
a per-frame cost of the idle module, or its placement slowing SYNTIZ's code or data. It is one A/B on one unit.

Proposal: a line in the module guide, for people judging a machine's margin on a unit with several modules kept: measure
with the real kept set, and when a set that should fit crackles, remove the modules that are not in use first. If you
want, I can try to find the mechanism (frame guard timing with and without FM Synth installed).

Separately, the SYNTIZ release PR asks for a waiver on the performance audit's rows for a machine that renders on the
ColdFire (10 % rule, MIDI flood, static bound); I wrote to you about this on 31 October.

@repeat98

repeat98 commented Nov 8, 2026

Copy link
Copy Markdown
Owner

Thanks for bringing SYNTIZ out of drafts, and sorry I never answered your DM from 31 October. The measurements are careful, and the three-track limit with the frame guard dropping a render instead of overrunning is a sound way to make a heavy machine safe.

The performance audit. I'll waive the rows you asked about for 0.1.0-experimental, as I did for POLY8: chip-worst-case-cycles and current-build-hardware, for this exact source. The waiver only covers rows with no numbers, so please set the load and stress fields in performance.json to null, and keep your measurements in their method text and in TESTING.md, where they already are. I'll add sdk/syntiz-build-approval.json last, once everything below is in, since it pins the source hash.

Two things on your side, both small:

  1. Leave the base as it is. The machine_registry.c comment rebuilds the beta base (d18d753a), so merging would offer every tester a base update for a comment. It would also collide with Octatrack base: the key bus to Y $7E00, Sidechain's MON words to Y $FF0 (#1064) #1098, Improvement: add SNAP alignment to Octatrack sample editor #1165 and Improvement: Octatrack base hook ev_engine_job at the engine task's job switch (0x4008485e) #1272, which regenerate the same files. Please revert that comment along with the regenerated base files (base-binding.json, octatrack-base.elemod, the base variants and sources, and Analog BD's sourcePolicySha256 in controller-policies.json), then merge main (not a rebase) and run npm run pr:ready until it says Ready. Keep the test_machine_events.py change, which reads the signature from the package row. I'll fix the comment's path in the next base pull request.

  2. One short run on the beta base testers have. Every run so far is on your own bases. Please update your unit to the current beta base from the site, then go through the USB steps every Octatrack module shows, with f501a6a4:

    • try it, then Undo;
    • try it, Keep, and play your live set for a minute;
    • power cycle;
    • remove SYNTIZ while a Part has SYNTIZ tracks: those tracks go silent, the rest plays on, and a reinstall brings them back.

    A few minutes is enough. Please put it in TESTING.md with the base's identity.

The idle FM Synth. Yes please, look for the mechanism. An installed module that never plays should cost nothing, so if FM Synth does, that's a bug in FM Synth or the base. It gets its own issue rather than a guide line, and one A/B isn't enough for a guide line yet anyway. Until we know, please keep FM Synth's name out of SYNTIZ's limitations, which players read on the module page, and just say "another installed module" there. The named A/B already sits in TESTING.md, where it belongs.

On the guides: the idle-module line can wait for the mechanism.

stigmagit and others added 3 commits November 8, 2026 09:35
…her installed module

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@repeat98

repeat98 commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Thanks for the quick turn. The base is back to main's, the fields are null, and the limitations say "another installed module". That's all in.

The red check comes from the three performance rows, and those clear only when I add the approval record, so pr:ready can't make it green on your side. That's not something you broke; please leave the rows as they are.

What's left on your side is the short beta-base run from my last comment. Please merge main first, since the beta base changed again since your merge, and update the two places that still say my decision is pending (TESTING.md's "Qualification record" and load.method in evidence/performance.json). Then I'll add the approval record and merge.

@stigmagit

Copy link
Copy Markdown
Contributor Author

@repeat98

The beta-base run on my MKII, 9 November: it stopped at the first step. SYNTIZ's trial does not roll back on the beta base, and the base itself did not stay.

  • Base: the beta base built by the local site from main f4c1a3f6 (status 72defb09b9d463fe…), installed with the site's "Update over USB" from my base 86388105.
  • Try then Undo with f501a6a4 (npm run device -- try … --seconds 60), twice: the trial ran 60 s, then "Device refused rollback: needs-recovery", and the unit stayed in recovery, generation 1, active unknown. The first time the project had SYNTIZ tracks; the second time it had none, transport stopped. Still in recovery 40 s later and after unplugging USB for 10 s.
  • During both trials the diaglog has a hot record with the transport stopped: cpu 98.9 %, T1-4 38 %, T5-8 39.8 %. My guess, not checked: with the CPU that loaded, the loader never finds the moment to switch back.
  • The base did not stay. The first USB update ended "Done", but the diaglog shows 72defb09 booting with a stall at +0 s, and the next start was back on 86388105. A second update held through one power cycle (inventory empty). After the second failed Undo and a power cycle, the unit started 86388105 again, with no stall recorded. My guess: the new base was never confirmed, and two unconfirmed starts sent it back to the old one.
  • Not done: Keep and a minute of play, the power cycle with SYNTIZ kept, and the removal while a Part uses it.

Raw outputs and the diaglog are on my computer if you want them. I have not changed TESTING.md: tell me whether you want this recorded there as it stands, or whether I should retry once you have looked.

@repeat98

Copy link
Copy Markdown
Owner

Thanks for running it and for writing it up so precisely. That 72defb09 is still the beta base on main, so this is the base testers have.

Please record it in TESTING.md as it stands: the base identity, the two Undo attempts and the base update that didn't stay, marked as stopped at the first step, with the remaining steps "not tested". A run that stopped is a valid result.

Please don't retry yet. The base update going back to your old base happened before SYNTIZ was involved, and the second Undo had no SYNTIZ tracks, so this looks like the base or the loader first. I'll look into it and come back here with what to run next. Please keep the raw outputs and the diaglog in case I ask for them.

@stigmagit

Copy link
Copy Markdown
Contributor Author

@repeat98

Done: TESTING.md has the run as it stands ("On Modwerk's beta base, 9 November 2026: stopped at the first step"), the remaining steps "not tested", and main is merged. I keep the raw outputs and the diaglog. The red check is still the three performance rows.

One thing from npm run pr:ready on my Mac after the merge, not from this branch: three host tests now stop on machine_registry.c:739:50: runtime error: applying non-zero offset 60 to null pointer (test_machine_events.test_registry_on_the_host, and two in test_fract_public_registry). The line came with #1389 this morning: in look(), s = part + SIG + 30 * t is computed before if (!part) return NOBODY. Your branch passed CI, so it may only show with this Mac's clang sanitizer. I left the base alone as you asked.

Since #1389 is about the beta base and FM Synth on busy projects, tell me if you want the run retried on the new base.

@repeat98

Copy link
Copy Markdown
Owner

Thanks, that's recorded just as I hoped. And good catch on look(): #1390 fixed that line and is merged, so those three host tests pass after your next merge of main.

Yes, please retry once, on the current beta base. On my unit the same kind of update held (details on #1386), so yours is the unit that shows it, and I need these readings:

  1. Before the update: npm run device -- status.
  2. Update the base from the site as before. Right after "Done", status again.
  3. Power-cycle, wait about 15 s, then status, and again 30 s later. I'm after the slot's tries, confirmed and fellBack.
  4. If it falls back, npm run device -- stall and stop there.
  5. If it holds, run SYNTIZ's try and Undo as before and note what Undo answers.

Please put the outputs in a comment on #1386 rather than here, and mark in TESTING.md only what you saw.

repeat98 and others added 4 commits November 11, 2026 18:57
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The approval waives chip worst-case cycles and current-build hardware for
0.1.0-experimental at this exact source. TESTING.md records the run on the
live beta base and on its development twin; the README's limitations say to
keep AMP HOLD/REL below INF and to Undo or remove only while no track uses it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@repeat98
repeat98 enabled auto-merge November 11, 2026 18:50
@repeat98
repeat98 merged commit 8685c11 into repeat98:main Nov 11, 2026
13 checks passed
@stigmagit

Copy link
Copy Markdown
Contributor Author

@repeat98 Thank you for merging SYNTIZ, and for running it on your own MKII and adding your approval yourself. I saw the release notice for 0.1.0-experimental. I'm very happy to see it out.

I'll keep #1386 open with you for the beta base on my unit, and I'll handle SYNTIZ's next updates through the author flow.

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.

2 participants