Skip to content

SYNTIZ (draft): at most three SYNTIZ tracks in a Part - #1107

Merged
repeat98 merged 1 commit into
repeat98:mainfrom
stigmagit:syntiz-trois-pistes
Nov 1, 2026
Merged

repeat98 merged 1 commit into
repeat98:mainfrom
stigmagit:syntiz-trois-pistes

Conversation

@stigmagit

Copy link
Copy Markdown
Contributor

What changes

SYNTIZ (draft) admits at most three SYNTIZ tracks in a Part. Choosing SYNTIZ for a fourth track is refused, and that
track stays what it was. A track that is SYNTIZ already stays admitted, so a model change still works. A Part saved
with more SYNTIZ tracks plays on as it was: the base asks a machine only when a track is picked (mw_assign, from the
MAIN and SRC SETUP commits). The sound is unchanged.

Why

On the author's MKII, a fourth SYNTIZ track holding a long note overruns the frame interrupt's share. The base's
frame guard then drops renders, and the unit crackles. Measured on the RAM-booted development twin 04e94075, with a
seven-track project playing: 35.2 % of each frame without SYNTIZ, and 79.6 % with it, with 6.35 renders dropped a
frame. Three lighter builds were tried on the unit and none let a fourth long note play clean; the author rejected
half-rate rendering on listening examples. Details are in sdk/drafts/syntiz/TESTING.md.

How it was checked

  • On the author's MKII (flashed b30d9b09), the package f501a6a4 was tried and kept over USB. It is built from the
    author's release branch, which adds the ev_trig_muted question (it needs build.py --raise, Improvement: a C runtime package can raise an event with no site (build.py --raise) #1059); its
    wave_admit_track is this one. Reported by the author: with SYNTIZ on three tracks, choosing it for a fourth is
    refused.
  • A host check of wave_admit_track, copied from machine.c: an empty Part, three tracks, a model change, another
    machine's leftover signature on a FLEX track, a Part saved with seven.
  • The draft builds with build.py (module 970f03ad). npm run pr:ready: Ready.

What the guides lacked

Two lessons for anyone driving an Octatrack twin: npm run device -- lifecycle keeps twice, and on a twin a machine's
trial must start before the project is loaded. They are added to docs/OCTATRACK_DRIVING.md on #1059, the pull
request whose branch already edits that paragraph, not in this module change.

🤖 Generated with Claude Code

On the author's MKII a fourth SYNTIZ track holding a long note overruns the frame interrupt's share and crackles.
wave_admit_track refuses SYNTIZ for a fourth track of the Part; a track that is SYNTIZ already stays admitted, and
a Part saved with more plays on. Tried on the unit from the author's release branch (package f501a6a4).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@repeat98
repeat98 merged commit 561e2fd into repeat98:main Nov 1, 2026
9 checks passed
@stigmagit

Copy link
Copy Markdown
Contributor Author

Hi Jannik,

Two things from the SYNTIZ measurements on my MKII tonight (3 November): a correction of a figure I gave you, and a guard observation that is yours to decide on.

Correction. I told you a SYNTIZ track costs "6-11 %" of a frame. That was wrong. Measured on a --dev base with do guard (idle share subtracted, 120 s runs, power cycle before each): one SYNTIZ track with big settings costs about 11 % of the frame on average and up to 15 % in a normal frame; three heavy tracks on an otherwise empty Part take the frame from 28 % to about 82 %.

The 3-track case on a busy Part. Part: 3 SYNTIZ (two SAW with UNI and WIDE up, one ENS with 4 notes and chorus), 4 FLEX tracks playing long samples.

Part in the frame interrupt worst frame sheds in 120 s
4 samples alone 36 % 87-89 % 0
2 SYNTIZ + 4 samples 56 % 98 % 0
3 SYNTIZ + 4 samples 67-68 % 110-115 % 24, 51, 54, 75 (four runs)

The sheds are audible as a crackle. A diagnostic build of the guard (counters only, not committed) shows what each shed looked like. The last ones: a second render (the render after the trig's sample offset) of T3 or T4, at - t0 40-60 %, that render's last cost 17-21 %, after 16-36 %, credit 10-13 %: predicted 94-96 % against 90-93 % allowed, so the render was shed for 3-4 %. The credit was drained by a few consecutive trig frames over 80 %; the minimum credit seen was -2.8 %. The stock work in those frames is the big part (after the last render reached 50-58 % of the frame in the worst case, with the samples' own work in it); SYNTIZ's render in a trig frame costs up to 2.2x a normal one (33 % against 15 %), which I could not explain yet: it is not code size (a build with half the engine code was worse), not the samples starting in the same frame (nudging their trigs by one micro-timing step changes nothing), and the START path is never taken for SYNTIZ's tracks.

The question. The sheds I measured are all on frames predicted under 100 % (90-96 %). If the guard let a render through whenever the predicted frame stays under FRAME (or under FRAME minus a small margin), even with the credit low, the three-track Part would play clean here, and the worst frames would stay where they are now (110-115 %, with latest start 11-15 %). I understand why the budget is 80 % plus a burst and what the frame interrupt does to USB and the UI when it runs long, so this is your call; I am not asking for a change to SYNTIZ's admission (3 tracks) or to the share, only telling you what the numbers look like. If you want the diagnostic patch (five counters in guarded() and mw_frame_exit(), read over the dev vendor request), it is in my notes and I can post it.

Until then the honest line for players stays: two heavy SYNTIZ tracks on a busy Part, or three with one lighter.

Steve

@stigmagit

Copy link
Copy Markdown
Contributor Author

Hi Jannik,

A follow-up to the SYNTIZ numbers on #1107. Since the ColdFire is the limit for heavy SYNTIZ tracks, I prototyped SYNTIZ's SAW model on the DSP (56300 assembly, run block by block in the dsp56300 emulator with Analog BD's bd909_host, nothing on a unit yet):

  • Output matches engine.c's render_saw within -56 dB (plain) to -70 dB (DRIVE 127) when both run the same 24-bit phase step.
  • Executed instructions per sample, worst block: 141 for a plain saw, 172 with UNI, 197 with UNI+WIDE, 213 with UNI+WIDE+SUB (237 with SUB2 too).

Before writing any integration I would like to know how you want a second DSP machine voice to hook in. Analog BD's engine comes with its package through the resident stock hooks and is placed on demand, priced per voice (source_kind). Can a third-party machine declare its own DSP engine through that same path, or does a second machine need a shared base hook at the source stage, so that Analog BD, SYNTIZ and later machines never patch the same place? I will not touch the base or Analog BD's path without your answer.

Steve

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