Skip to content

Sidechain Compressor 0.2.0-experimental: base-width key filter, MON/KEY rework (module, adapters, base, packages) - #971

Merged
repeat98 merged 1 commit into
repeat98:mainfrom
Zac-Kyoti:sidechain-compressor-0.2.0b
Oct 27, 2026
Merged

repeat98 merged 1 commit into
repeat98:mainfrom
Zac-Kyoti:sidechain-compressor-0.2.0b

Conversation

@Zac-Kyoti

Copy link
Copy Markdown
Contributor

As agreed in #848: one PR with the module, the adapters, the regenerated beta base and the rebound packages, for your review.

The module. My final SIDECHAIN_COMPRESSOR, imported byte for byte from my own Modwerk copy of it, modwerk-modules/sidechain-compressor (b0d49bf, sdk/imports/sidechain-compressor-b0d49bf.json).

  • KBAS (an 18 dB/oct high-pass, in Hz) and KWID (a 12 dB/oct low-pass, 0.5-9.9 octaves above KBAS) replace KFLT. Page 2 is RMS · MON · KEY · KGN · KBAS · KWID.
  • MON shows OFF on the left and ON on the right. It stores 2 / 3 with its own step handler, and sc_norm turns any other value OFF, so a COMPRESSOR saved with an earlier version comes up with MON OFF.
  • KEY is a 9-position rotary switch with its own step handler, so a pressed turn moves one position (stock's generic handler moves 7).
  • MON and KEY changes fade over 256 samples.
  • The changelog says what a 0.1.x COMPRESSOR turns into: KEY kept, KGN = old KFLT, KBAS = old KGN, KWID = old MON, MON OFF.

The base and SDK (owner review). The record is docs/verification/2026-10-26-octatrack-sidechain-0-2-0-base.md.

  • DspSection.ptable2 in the vendored schema and builder, the resident engine and the hooked DSP packages: a second table straight after the ptable, with its own $fab2e0 literal, as upstream octabam places it. An unfilled literal is refused.
    • Why: my first 0.2.0 image (MW_SC020) loaded the key-filter table from a register the gain store had already moved, and that broke KBAS/KWID on hardware. The table now has its own literal.
    • Without the package fix, the browser images would have kept the bug. module:verify caught it.
    • sdk/infrastructure-verification/ptable2-builder.json: the floating-cave record's 128 selections, built with the base commit's builder files and with these, both with main's Sidechain folder, give 100 identical images and 28 identical refusals. EXTENSIONS gains it, and the emulator-gates test now lets a later record move a file it froze.
  • resident_dsp.py: new pins. Your key-phase change still applies exactly once; only the detector half's hash moved, and the key bus tap is byte-identical. keybus_executed is 25 (was 41), and dsp-sites.json keeps the 51-cycle hardware charge measured on the old tap.
  • stock_hook_controllers.py: two linked units (sc_cf 698 B, sc_ui 616 B at 0x400d7300) checked against my references, with eight stock copies.
    • The MWPP page record may name 16 routines (was 8), in controller_board.c and page_record. Sidechain's page names 9: MON's formatter, switch and step handler, KEY's formatter, switch and step handler, KBAS's and KWID's formatters, and KWID's clip.
    • Please look at ui_switch.s: it lends one entry of stock's switch glyph table (0x400bde2a) for the duration of the stock widget call.
  • machine_registry.c sidechain() (Fix: a Sidechain Compressor no longer empties the Octatrack's current bank at power-on #712) shows stock's validator its own COMPRESSOR values in slots 7-11. MON is now 2/3, and stock's value count of 2 for slot 7 would refuse the bank.
    • A side-chain is MON 0..3, KEY ≤ 8, slots 9-11 < 0x80, so a bank saved with 0.1.x matches too.
    • test_machine_registry.c covers 0.2.0 OFF/ON, a pre-0.2.0 MON, a 0.1.x bank, stock KEY 127, slot 7 and slot 11 out of range, and another effect.
  • Regenerated: the base (--beta --write, browser .bin eef42677…), Analog BD's recipe (only imageSha256 moved) and the base-bound packages. Both stock-free scans pass (longest run 11).
  • Pins that follow: Tape Echo's and Euclid's standalone recipes now name the regenerated package asset files (as the Direct Jump and Deja Vu PRs did) and the new schema.py. octatrack-module-packages.py --check rebuilds every package identically; Play Modes stays as main has it (Play Modes 0.2.0 has no USB package: USB installs still get 0.1.1 #764).

Newly refused. npm run modules:pairs: no pair is newly refused; the refused list (10) is main's. The suites, regenerated in the toolchain image:

Suite Built with 0.2.0 With 0.1.2 Newly refused (smallest)
sidechain (512) 169 200 31, core A DSP space and ColdFire (MiniVerb + Modulation)
sidechain-visible (1,024) 618 786 168, ColdFire space (Euclid + Scale Quantizer)
analog-bd (212) 146 162 16, core A DSP space (Analog BD + Airwindows Chorus)

Nothing that 0.1.2 refused builds now. Linking sc_ui in DRAM would likely give the ColdFire-space ones back; I kept the cave, the placement the hardware test ran. Say if you want it.

How I checked it.

  • module:verify sidechain-compressor: 154 selections, 66 matching images (24 identical outright, 42 outside the platform writes), 88 matching refusals, 0 mismatches.
  • Resident engines with the real dsp_asm and dsp56300 (test_resident_engines.py: key phase on every enable order and skew; MON ends with its COMPRESSOR over the 16-block fade). Also test_resident_stock_dsp.py, test_resident_stock_fills.py, test_stock_hook_controllers.py, test_controller_board.py, test_machine_events.py, test_infrastructure_regressions.py, test_sidechain_compressor.py, and the TypeScript tests for Sidechain, descriptors, DSP packages and Analog BD.
  • Screenshots: native and browser-composed images draw the same three frames, pixel for pixel.
  • Hardware: my Octatrack MKI, 26 October 2026, Modwerk's native image of the module alone (MAIN OS 131142e1…, card file MW_SC021). KBAS/KWID with MON on and off, MON's switch and its OFF on an older project, KEY's pressed turn, the fades, and a MON ON project across a power cycle all work (evidence/hardware.md). The USB beta base itself is not hardware-tested.
  • npm run pr:ready: Ready (on main 1d61937a).

What the guides lacked:

  • manifest.py's author must be the GitHub login even when author.name differs.
  • A source change to Sidechain needs, in this order: the packages built, the base regenerated, Analog BD's recipe recaptured, and the base-bound packages rebound.
  • A change to the vendored builder needs its own sdk/infrastructure-verification record and an EXTENSIONS entry.

No Docs: PR yet.

🤖 Generated with Claude Code

…upport (ptable2, page pointers, power-up check)

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

Copy link
Copy Markdown
Owner

@Zac-Kyoti thanks, this is a really thorough PR, and the ptable2 record and the hardware run on MW_SC021 make it easy to follow.

Two small things before it can go in:

  1. public/octatrack-modules/sidechain-compressor/0.1.2-experimental.mwrm is still in the branch. Nothing points at it any more, and it is still linked to the old base (c1ae2ee9). Other module updates delete the previous version's file, so could you git rm it?

  2. About the selections that no longer fit (168 in the visible suite, mostly ColdFire space): how big a change would linking sc_ui in DRAM be, and would it need another hardware run on your side? I'd rather do it as a follow-up than hold this PR for it, but I want to know what it costs first.

A heads-up on timing: a few other open PRs also rebuild the beta base (#943, #944, #914), so whichever merges later needs the base and the base-bound packages regenerated on top of the others. I'll say here if that falls on this one.

@repeat98
repeat98 merged commit 83f9d89 into repeat98:main Oct 27, 2026
9 checks passed
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