Skip to content

Improved AMP 0.1.0-experimental (Analog Rytm MKII, OS 1.74) - #1419

Open
npp1993 wants to merge 50 commits into
repeat98:mainfrom
npp1993:claude/rytm-improved-amp
Open

npp1993 wants to merge 50 commits into
repeat98:mainfrom
npp1993:claude/rytm-improved-amp

Conversation

@npp1993

@npp1993 npp1993 commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

A module: Improved AMP 0.1.0-experimental, a new module for the Analog Rytm MKII, OS 1.74 (id improved-amp), by Nathaniel Pavel (@npp1993).

What it changes

Always on while installed; there is no switch.

  • AMP HLD runs from no hold (0) to AUTO (127), never cuts the attack, and is a length in steps of the track: it is counted on the Rytm's musical clock, so it follows the tempo and the track's speed, and the knob reads the steps. FUNC + turn stops at 0, 0.125, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4, 8, 16, 32 and 64 steps, then AUTO.
  • ATK, DEC and REL on the AMP and FILTER pages move in 0.2 ms steps up to 5 ms and read as times.
  • AMP OVR keeps its 0 to 127 number and is finer at its low end; 0 and 127 are stock's.
  • ENV RESET gains AMP and AMP+FILT. A sequenced trig or retrig of such a sound is faded out over the 10 blocks before it, so the envelope restarts from silence without a click. Pad hits, MIDI notes and the first trig after PLAY play as stock.

Saved sounds keep their bytes and play HLD, ATK, DEC, REL and OVR on the new curves while the module is installed; removing it plays every project as before. The README lists each change to a stock flow under "Changes to stock flows".

Version, compatibility

  • 0.1.0-experimental, OS 1.74 only, on Modwerk's Rytm base (core-ar2 0.7) with the amp record hook ev_amp_record (two entries, order 20 and 50) and ev_tick. No new base hook.
  • compatibility.conflicts: ["env-reset-amp"]: it carries ENV RESET's AMP and AMP+FILT itself, so the configurator offers one or the other.
  • Sites it patches and claims are in upstream/README.md and build.json (addresses, lengths and SHA-256 guards only).
  • Memory: 9,676 bytes of the shared mod area. Load, measured on my unit with the sequencer stopped: about 1.6 points of the audio block, about 1.0 of them in the amp record entries (README, TESTING.md).
  • This supersedes my earlier draft for Improved Envelopes (id envelopes), which I will close once this one is reviewed.

Source and attribution

My own code, GPL-2.0-only. ENV RESET's two byte sites and the reading of the amp envelope's commands come from MrScruff's rytm-mods 0015-env-reset-amp by way of Iced-Cream's Env Reset Amp (GPL-2.0-only); upstream/README.md and the licence declaration say so. Screenshots are rytm-emu captures of this package linked alone on the base (media/capture.json).

Evidence

  • On the unit, this source, 11 November 2026 (evening): my Analog Rytm MKII, OS 1.74, run hands off by my automated USB test rig. 25 cases pass on IL05 (this source alone on a development build of the base with a USB test link, loaded to RAM). Five of them were rewritten for the hold in steps and their reference screens kept in this run after a look at each; the other 20 pass against the references of 10 November. One step (HLD 42) held 125.0 ms at 120 BPM, 166.5 ms at 90 BPM and 83.0 ms with the track at 3/2x, and read 1 each time; FUNC + turn showed its 13 stops and AUTO; the musical clock was read running with the sequencer stopped. On an external MIDI clock sent over USB (CLOCK RECEIVE on, no START, sequencer stopped) the Rytm's tempo followed to 90.0 and 150.0 BPM and one step held 165.5 and 101.5 ms; when the clock stopped the Rytm kept its last tempo and the hold with it. The rest as before: lengths by DEC and AUTO, OVR's level curve, the FILTER times, and ENV RESET AMP's fade across sequenced trigs, retrigs, swing, micro timing, sound locks, mutes, lock trigs and trig conditions. Figures are in TESTING.md.
  • The package's own image: IA14 (plain base, this package alone, no link) ran from RAM on the unit with MIDI notes and CCs only: 0.125, 0.5, 1, 2 and 4 steps held 16.5, 63.5, 126.0, 250.5 and 500.5 ms at 120 BPM; decay, attack, AUTO and OVR read as before. The package links to IA14 byte for byte.
  • 9 to 11 November, earlier sources of this version (IL02, IL04, IA12): the same cases with the hold as a fixed time, the idle-path change, and OVR's curve and the FILTER times beside the same base without the module.
  • Not run on a unit: the sequencer running on an external clock and a clock that stands (the fallback is read in the code and host-modelled), a tempo or speed change during a hold, NORMAL scale mode, a boot of the package's image from flash and its keys, screens and sequencer, pads, a power cycle, a project save and load, a +Drive sound, a pattern change inside a fade, probability conditions, the load while a pattern plays. TESTING.md lists them, and the runs that told nothing with their causes.
  • Seen on the way: the first note sent about a second after loading an image to RAM was near silent in some boots, with the module (7 of 12) and without it (3 of 11), never after a 3 s wait (0 of 7). Cause not found. The unit boots with the working kit it kept, not the saved one.
  • Emulator and host: rytm-emu 2ac0f1f, IA14 against the earlier image run for run (the fade mask the same in 19,400 readings, the ENV RESET frames the same bytes, the AMP page's frames different only where HLD's text shows); 68 cases of the pre-fade's scan; the scan before and after on 10 million random states without a difference; a host model of the hold decision over every knob value, tempo, track speed, a tempo change during a hold and a standing clock.

Since the review (11 November)

  • The manifest's load text is corrected: the trig scan runs every block (81356520).
  • The idle path is cheaper, with no change in behaviour (d4e422a9, 637c1411): the words both amp record entries read every block share one cache line, an idle voice leaves both entries without reading its stored record, the scan returns early when no queued event is near and no AMP track runs a retrig series, and the OVR reader keeps its last answer a voice. Metered on the unit, sequencer stopped: the module took about 1.8 points of the audio block and takes 0.4 to 0.6 less. Four independent reviews of that change; the package, catalogue pin and records are rebuilt for it.
  • The short run of the package's own image asked for in the review is the IA14 run above (IA12 before the hold changed). It was loaded to RAM, not flashed.
  • HLD follows the tempo (86376071). The hold was a fixed time, shown as steps of the tempo it was drawn at, which read as if it were tied to the step. It is now counted on the musical clock in steps of the voice's track, so it follows the tempo, the track's speed and an external clock; when a master's clock stands for more than 8 ms it runs on at the tempo word's rate, so a hold always ends. Thirteen knob values were moved by at most 4 % onto the step grid, where FUNC + turn stops, and the knob's text is the same at every tempo. At 120 BPM and 1x every other value holds as long as before. README "Changes to stock flows" has the entry. Idle load on the unit is about 0.1 point higher than before this change (not traced; the emulator counts the same instructions). Two independent reviews (the code, the rig's cases); package, catalogue pin, screenshot and records are rebuilt for it.

What the guides lacked or got wrong

Nothing fixed in this pull request (its only docs/ file is the verification record). Three things went into #1420, merged:

  • The build's source fingerprint covers the module's README, TESTING.md and manifest, so a documentation edit changes runtimeSourceSha256 although the exported package stays the same file.
  • scripts/package-elemod-recipe.mjs refuses to overwrite an existing package; --check is the way to confirm an unchanged export.
  • OS 1.74's sequencer queues up to three events a track and fires one a block, which a module that looks ahead at trigs has to follow.

From the hold change, not fixed here: docs/module-guides/sequencing.md has the Rytm's musical clock, but not that it keeps running while the sequencer is stopped (read on the unit here), nor where a track's speed is read (the pattern's scale mode, the pattern's or the track's speed, stock's pulses-a-step table). The module's README has both under "How it works"; they belong in the guide as their own Docs: pull request.

Vouched

  • Changing a module someone else wrote: not the case, this is a new module.

  • I read the guide for its category in docs/module-guides/ (and sequencing.md), and TESTING.md lists what I did not test.

  • Source and media are mine or properly licensed, with authors and full licence texts kept. Nothing comes from Elektron firmware: no extracted code or tables, upgrade files or factory content, and nothing is modelled on another current Elektron product.

  • Screenshots are real captures of the current module UI (rytm-emu, labelled as such). Hardware results are the automated rig's on my unit, on the builds named above: this source on a development base, and the package's own image from RAM with notes and CCs only.

  • Automatically merge and publish my module update after checks pass.

  • I verified the source, licences, UI and qualification reports, including instance isolation and Part/project/reboot persistence where applicable; no required acceptance check is failed or untested.

Reviewer:

  • I checked the cycle and memory reports against the worst case, the attributed hardware evidence against the submitted source and build, and the screenshots, tutorial and access steps against the current UI.

Validation commands and results

  • npm run pr:ready: Ready (387 test files, 3154 tests pass; check passed), on the branch with main merged in.
  • npm run module:doctor -- improved-amp: every line green.
  • bash scripts/build-elemod-isolated.sh from a clean checkout of 94811633 (and again at ce302f36, after the last documentation commit: the same package), then node scripts/verify-elemod-release-exports.mjs: reproduced 62 current source-only release exports; package-elemod-recipe.mjs --check reproduces the committed package (b7d15e01…580a), which links alone to IA14 (c64b0477…cffe).
  • npm run elekloader:update -- --overlay sdk/imports/elekloader-improved-amp-2026-11-11.json: package fetched from 3895851c, hash checked, vendored.

🤖 Generated with Claude Code

npp1993 and others added 30 commits November 6, 2026 23:04
The AMP envelope reworked, with times on every envelope knob: AMP HLD from
no hold to AUTO without cutting the attack, fine ATK, DEC, REL and HLD steps
at short times (0.2 ms to 5 ms), FUNC jumps on HLD, and ENV RESET AMP
(Iced-Cream's Env Reset Amp, from MrScruff's rytm-mods) with a pre-fade.
Unit-tested on an MKII over USB (TESTING.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Compiled from a0aaa13 in the pinned toolchain (build-elemod-isolated,
image 39efd52a), exported with package-elemod-recipe.mjs; --check
reproduces it.

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

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>
…fication record

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mproved-envelopes

# Conflicts:
#	sdk/analog-rytm-mkii/modules/README.md
#	src/devices/library-parity.test.ts
…ote and thumbnail

ENV RESET AMP and its pre-fade go back to Env Reset Amp, now in the
library on its own: the two byte sites at 0x400bcf8a and 0x400ef8d6,
pre-fade.c, the ENV RESET claim and its docs and release-note lines.
The writer keeps only the idle skip (envelopes_gate moves to
envelopes.c, still-mask at [0]). Beside Env Reset Amp the HOLD rule
holds from the next block's attack record (stock's state 0 at
0x40109b5a, read in OS 1.74; upstream/README.md), so no conflict.
upstream/README.md and media/thumbnail.svg are Envelopes' own; TESTING
says the author where it said the owner, and drops the empty EV04 head.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mproved-envelopes

# Conflicts:
#	sdk/analog-rytm-mkii/modules/README.md
#	src/devices/library-parity.test.ts
Built by build-elemod-isolated.sh in modwerk-source-tools (39efd52a)
from ed0cac2; package-elemod-recipe.mjs --check reproduces it and
verify-elemod-release-exports.mjs reproduces all 49 exports. Linked on
the plain base ba530f45: ramSpare 113,776 alone (EN02) and beside
Env Reset Amp 1.0.0 (EN03).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ptures on EN02

The rytm-emu captures retaken on EN02 (plain base + this package) are
pixel-identical to EN01's. Verification record updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mproved-envelopes

# Conflicts:
#	sdk/analog-rytm-mkii/modules/README.md
#	src/devices/library-parity.test.ts
…mproved-envelopes

# Conflicts:
#	sdk/analog-rytm-mkii/modules/README.md
#	src/devices/library-parity.test.ts
…mproved-envelopes

# Conflicts:
#	src/devices/library-parity.test.ts
…mproved-envelopes

# Conflicts:
#	sdk/analog-rytm-mkii/modules/README.md
#	src/devices/library-parity.test.ts
…for the publication gate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ange (package bytes unchanged)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…_record (order 50)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…D in steps into one module

Renames the module envelopes -> improved-amp. Adds the Env Reset Amp 1.1 pre-fade (order 20 on
ev_amp_record) with the queued trig's sound lock deciding ENV RESET, a THD-linear AMP OVR CV table
and the AMP HLD readout in steps at the track's tempo and speed. Always on, no per-sound switch.

Co-Authored-By: Claude <noreply@anthropic.com>
…ks and the kit's sound

The pre-fade's scan reads all three event slots of a track, fires one queued
event a block (lowest due slot first), follows a lock trig's RTRG rate, ends a
retrig series where stock does and judges a trig by the sound it will play: a
sound lock's pool sound, the kit's sound, or the track's sound as it stands when
stock would not load one. Five independent reviews; findings checked in the
OS 1.74 code. Docs, captures and release notes are for build IA08 (rytm-emu
only, not yet on a unit). The old envelopes records are removed with the rename.

Co-Authored-By: Claude <noreply@anthropic.com>
…tion note

Built in the pinned toolchain from 632676a; linked on the plain base it
gives IA08 byte for byte.

Co-Authored-By: Claude <noreply@anthropic.com>
… tier author-hardware

TESTING.md records the 25 cases the author's automated USB test rig ran on
their Analog Rytm MKII on 9 and 10 November 2026, as its run record reports
them, on IL02 (this source on a development base with a USB test link, loaded
to RAM), with what was not run and the quiet first note after a RAM load, which
also shows without the module.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Measure definitions as the rig computes them, the boot counts' condition, the
runs that did not pass, the note lengths the HLD case plays, and pool sounds
played through sound locks.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…source record

The package export is unchanged (76fb70ef); the source tree fingerprint covers
the module's documents, which changed with the unit results.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Lengths as ranges over the six runs, the HLD case's note lengths, and the quiet
first note after a RAM load counted for one case: with the module 7 of 12 boots,
without it 3 of 11, never after a 3 s wait.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
npp1993 and others added 2 commits November 10, 2026 19:14
…40767f

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ication record

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@repeat98

Copy link
Copy Markdown
Owner

Thanks Nathaniel, the pre-fade work and the measurements are really thorough. Before I can take this, three things:

  1. On Analog Rytm MKII: Improved Envelopes 0.1.0-experimental #1291 we agreed that ENV RESET stays out so each module does one job. This brings it back in and conflicts with Env Reset Amp. Now that ev_amp_record exists, the pre-fade could go to Env Reset Amp as an update (with Iced-Cream's yes) or into a module of its own, and OVR could be separate too. Your EN05 run already shows the pair working as two modules. If there's a reason it has to be one module, tell me.
  2. I still need your reasons for having no per-sound switch: once installed, every saved project plays its HLD, ATK, DEC, REL and now OVR differently, and removing the module is the only way back.
  3. The manifest says the pre-fade skips its scan when no track has AMP in ENV RESET, but amp_prefade_scan runs it every block. Please fix the text or the code, and do one short run of the package's own image on your unit, since the runs so far used a development base.

npp1993 and others added 3 commits November 11, 2026 08:16
The manifest said the scan is skipped while no track has AMP in ENV RESET. The
code runs it every block on purpose: a sound lock can bring AMP to a track
whose own sound has it off. Text only.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…135652

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@npp1993

npp1993 commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for the review. On the three points:

1. One module. Everything in it changes how one page behaves: the AMP envelope's shape (HLD order, ATK/DEC/REL curves), its drive (OVR) and when it restarts (ENV RESET AMP). For a musician that is one install and one README for a better AMP page, not three modules to find and combine.

The pre-fade and the envelope rewriter both rewrite the same amp record and depend on each other's order: the fade at order 20 passes through the rewriter at order 50 untouched, and the rewriter's level follower reads the fade as a fall to silence so the hold counts from the trig. EN05 passed with them as two modules, but there that ordering is an unwritten contract between two packages. In one module it is tested together, and the 25 unit cases cover the pair.

The pre-fade is new code, not Env Reset Amp's: it replaces 1.0's drop to silence, reads all three event slots and follows sound locks and retrig series. Putting it into Iced-Cream's module would change their module's behaviour under their name, so I maintain it myself. The conflict with Env Reset Amp is declared, and the configurator offers one or the other.

OVR is one table and one 10-byte reader on the same page. On its own it would be a module with a single curve.

2. No per-sound switch. I built the switch first and dropped it. It needs a stored bit, a SOUND SETTINGS row, a default for new sounds and a per-voice lookup in the audio code: three new base hooks that every unit would carry, for a compatibility path I found no use for.

  • The module writes nothing into a project. Saved HLD, ATK, DEC, REL and OVR bytes stay as they are, so removing the module plays every project exactly as before.
  • ENV RESET AMP, the part that changes what a trig does, is already opt-in per sound, and no old save can have it set.
  • The change is stated up front: "Changes to stock flows" in the README lists each one (HLD 0 is no hold instead of AUTO, 127 is AUTO instead of 16 s, the new curves, OVR 1 to 126 giving less drive with both ends unchanged), and the release notes say saved projects play on the new curves.
  • OVR's ends and the envelopes' longest times are stock's. What moves is the low end of each knob, which is the point of the module.

3. Load text and the package's own image. You're right about the text. The scan runs every block on purpose: a sound lock can bring AMP to a track whose own sound has it off, so skipping on the tracks' own ENV RESET bytes would miss those trigs. The manifest now says so (81356520).

I'll do a short run of the package's own image (IA08, plain base, no test link) on my unit and add it to TESTING.md.

npp1993 and others added 15 commits November 11, 2026 13:16
…o DDR

The two amp record entries ran for every voice every block and the trig scan
read 60 scattered DDR lines a block even with the sequencer stopped, since
the musical clock keeps running. Behaviour is unchanged:

- The words both entries read every block share one 16-byte line (hot.h); an
  idle voice's 0/0 record is told from GATE_ZERO alone, without the stored
  records, and an unmarked voice leaves the pre-fade entry after 16 bytes of code.
- The scan first reads the 36 queued-event times and the 12 ENV RESET bytes,
  all in the on-chip RAM, and returns when no time is inside its window and
  no track has AMP. In the per-track loop a slot's time is tested before its
  state, the held word only for a slot that counts, and a track's own AMP
  before its retrig series.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…s quick exit covers kits with AMP

Measured on the unit, the first idle-path change saved nothing in a kit with
tracks on ENV RESET AMP: there the per-track scan still ran every block.
Behaviour is unchanged:

- The scan returns early when no queued event's time is inside its window and
  no track has both AMP in its own ENV RESET and a retrig series running, the
  only two ways a voice can be marked.
- The OVR reader's CV depends on the live word alone, so a voice whose word has
  not moved takes the CV worked out last time: no table read and no multiply.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…captures on IA12

TESTING.md: the 25 rig cases on IL04 (this source), the package's own image
IA12 from RAM with notes and CCs, the idle load by a meter on the unit's
timer (the module about 1.8 points of the audio block before, 0.4 to 0.6
less now), the checks made before the unit, and the runs that did not pass
with their causes. README and manifest carry the measured load and 8,220
bytes of memory; the screenshots' record names IA12, whose frames are the
same bytes. Two source comments corrected.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…import record and verification note

Package 92f1e883 from a clean checkout of 5763962; it links alone to IA12
(e28ebdd4), the image that ran in the emulator and from RAM on the unit.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ackage

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…clock; FUNC + turn stops on the step grid

The hold was a fixed time, shown in steps of the tempo it was drawn at. It is now counted on the
musical clock, in steps of the voice's track: it follows the tempo, the track's speed and an
external clock, and falls back to time at the last tempo when a master's clock stands. Thirteen
knob values sit exactly on 0.125, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4, 8, 16, 32 and 64 steps, and
FUNC + turn stops on them between 0 and AUTO. At 120 BPM and 1x every other value holds as long
as before.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
… hold in steps

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…rrected

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ad), memory and load figures

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…rt record and verification note

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…ackage

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…al clock result

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
…print

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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