Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 61 additions & 8 deletions REVIVAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,57 @@ GitHub Actions CI.
Phase 2 of `plans/tap.303.md` is **complete**; what remains for the 303 program is runtime
validation in Max and the deferred phase-3 sequencer.

- ✅ **The sequencers — `tap.808.seq~` + `tap.303.seq~` (2026-07-18).** The coordinated
phase 3 both family plans deferred, designed and author-approved same day as
**`plans/tap.seq.md`** and shipped end to end: **one shared kernel engine**
(`step_seq.h`, `taptools::seq`) — phase-clocked from a `phasor~` ramp
(floor(phase × length), swing warping the odd steps, sample-accurate entries,
stateless against phase), 16 slots with cycle/step/now-quantized recall — with two
thin emitters speaking the shipped voice contracts verbatim. **`tap.808.seq~`**: one
drum row, impulses whose amplitude 0..1 is the accent (plain 0.01 = the 4 V base bus,
accented 0.5 = the accent knob at noon; provenance `tr808_kick.h`'s 4–14 V mapping),
`hits`/`accents`/`velocities` surfaces, `pulse` widening for envelope consumers.
**`tap.303.seq~`**: the acid line emitting the `tap.303~` pitch + gate pair (1.0/2.0
accent amplitudes; gate duty 0.5 per Open303's `AcidPattern`), **slide as gate-hold**
across the boundary — chained slides and the across-the-wrap slide pinned by test —
with per-step pitch/gate/accent/slide, live `transpose`, and the slide flag on the
*target* step per the package `note` convention (hardware stores it on the source;
divergence documented in the kernel header). Both rows: `length` 1..64 (polymeter off
one phasor — the triplet pre-scale generalized), swing (beyond-hardware, default 0),
`store`/`recall`, `todict`/`fromdict` dictionary patterns, a 1-based step-index UI
outlet (coalescing audio→scheduler handoff, the `tap.sift~` idiom). Kernel: 19 new
scenarios (suite 129/129), including the tb303-voice pairing test asserting slid
steps glide without retrigger. Wrappers: min-api unittests (compiled and run against
the mock kernel), maxrefs, help patchers, maxtest starters — and
**`help/tap.808.maxhelp` rebuilt on real rows** (one phasor, nine rows, the old
metro/counter/sel pattern retired), with `help/tap.303.seq~.maxhelp` superseding the
`tap.303~-pattern.maxpat` dry run (which stays as the event-domain alternative).
**Runtime validation in Max still pending**, as everywhere.

- ✅ **The sequencer verification notebook (2026-07-18).** **`notebooks/step_seq.ipynb`**
(kernel repo), house pattern: the shipping `step_seq.h` driven through the C ABI
(extended with `taptools_seqtrig`/`taptools_seqnote` + a minimal `taptools_kick`).
Six executed, asserted sections: the analytic grid (≤ 1 sample; polymeter), the swing
warp (odd-step delay = swing/2), the trigger-bus levels (0.01/0.5/1.0) + `pulse_ms`,
the 303 line signals (duty 0.5, accent 2.0, gate-hold slide — including the
full-step hold on a slide *source* step, a case the Catch2 suite's isolated-step
scenario didn't exhibit), **four bars of acid + kick rendered from the real
`tb303_voice.h`/`tr808_kick.h` off one phasor ramp** (embedded audio), and
cycle-quantized recall swapping exactly on the wrap sample.

- ✅ **"Tools on Tap" Part V — The rhythm section (2026-07-18).** Two field-guide
chapters in the kernel repo's book: *The acid machine* (`tap.diode~`/`tap.303~`/
`tap.303.seq~`) and *The drum machine* (the eight `tap.808.*` channels +
`tap.808.seq~`), every number sourced from the executed notebooks or the kernel
suite per the book's own rules; the machine deep-dives renumber to Part VI —
which same-day gained its own four rhythm-section chapters: *Seventeen, not four*
(`diode_ladder.h` — the k = 17 threshold derived, the closed-form coupled ZDF solve,
the WDF no-go), *The couplings are the instrument* (`tb303_voice.h` — the C13 wow as
three lines, the measured envmod law, the documented Open303 divergence), *One
network, eight voices* (the `tr808_*` headers — the bridged-T solved on its states,
the calibration lesson), and *Time as a function of phase* (`step_seq.h` — the O(1)
derivation, gate-hold look-ahead, armed-recall re-derivation).

---

## 8. The `taptools-min` reconciliation (2026-06-17)
Expand Down Expand Up @@ -1149,11 +1200,12 @@ Roland TR-808's analog drum voices: the eight voice channels
shared kernel blocks: bridged-T resonator, metal bank, swing-VCA), the family accent-bus
contract (signal-edge amplitude = accent on the 4–14 V trigger bus), the family overview
patcher, and the kernel's `tr808_render` tool. Provenance: the Werner–Abel–Smith
DAFx-14/ICMC papers + the TR-808 Service Notes schematics, read directly. Flagged WDF
circuit-simulation upgrade path (`@circuit`, the `svf.h` two-circuit pattern) and a
potential later sequencer phase (`tap.808.seq~`) remain. See the §7 progress-log
entries (slices 1–5). Next: runtime validation in Max, §7.2 sample-pack calibration,
then the Phase 2 WDF go/no-go on the kick.
DAFx-14/ICMC papers + the TR-808 Service Notes schematics, read directly. **The phase-3
sequencer shipped 2026-07-18** as `tap.808.seq~` (see `plans/tap.seq.md` and the §7
entry — one row per voice, phase-clocked, sharing its engine with `tap.303.seq~`).
Flagged WDF circuit-simulation upgrade path (`@circuit`, the `svf.h` two-circuit
pattern) remains. See the §7 progress-log entries (slices 1–5, §7.2 calibration).
Next: runtime validation in Max, then the Phase 2 WDF go/no-go on the kick.

**11. Net-new object family — `tap.303.*` (2026-07-17).** 📋 **Plan approved; slices 1–2
shipped** — see **`plans/tap.303.md`**. The TB-303 recreation, companion to the `tap.808.*`
Expand All @@ -1166,9 +1218,10 @@ circuit documentation, Open303, x0xb0x schematics, Service Notes. **Phases 1 and
seed/tolerance + factory presets; phase 2: the `vca clean|warm` transistor stage, the
square shaper resolved via Open303's measured constants, and the author-approved WDF no-go
— grounded in the kernel repo's **`notebooks/tb303.ipynb`** verification notebook; see the
§7 entries). Remaining: the deferred sequencer phase (`tap.303.seq~`, coordinated with
`tap.808.seq~`) and **runtime validation in Max** for both objects (help patchers,
maxtests, the render WAVs, and the notebook as the evaluation material).
§7 entries). **The phase-3 sequencer shipped 2026-07-18** as `tap.303.seq~` (see
`plans/tap.seq.md` and the §7 entry — the acid line on the shared step engine, slide as
gate-hold). Remaining: **runtime validation in Max** for all three objects (help
patchers, maxtests, the render WAVs, and the notebook as the evaluation material).

Remaining (ongoing, now cross-repo — DSP lands in `tap/taptools`, then bump the submodule pin
here): lift the remaining simple inline-DSP objects' math into kernel headers opportunistically as
Expand Down
212 changes: 212 additions & 0 deletions docs/tap.303.seq~.maxref.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet href="./_c74_ref.xsl" type="text/xsl"?>

<c74object name="tap.303.seq~" module="msp" category="TapTools, MSP Sequencing">

<digest>
Phase-clocked acid-line sequencer for tap.303~
</digest>

<description>
The <o>tap.303.seq~</o> object is a step-sequenced bass line speaking exactly the
<o>tap.303~</o> note contract: feed it a phase ramp (0..1 per pattern cycle — a
<o>phasor~</o>) and it emits the voice's inlet pair, a pitch signal (MIDI note number,
held between notes) and a gate signal whose edge amplitude encodes accent (1.0 plain,
2.0 accented; the accent amount stays on the voice's knob, like the hardware). The gate
opens at the step start and closes halfway through the step (Open303's measured duty).
A step with the slide flag is approached legato: the gate holds through the boundary
while the pitch steps, and the voice's ~60 ms glide does the rest — no retrigger,
chained slides chain, and a slide across the pattern wrap works. Per-step data mirrors
the hardware pattern memory (pitch, gate/rest, accent, slide; pitch as a MIDI float
subsumes the octave up/down flags), without recreating the 1981 entry workflow:
patterns are lists, step messages, sixteen slots with boundary-quantized recall, and
dictionaries. Rows share the phase-clock idiom with <o>tap.808.seq~</o> — one phasor
runs a whole rhythm section in sample lock, and this row's gate edge also triggers any
tap.808.* voice directly. The design of record is plans/tap.seq.md.
</description>


<!--METADATA-->
<metadatalist>
<metadata name="author">74 Objects</metadata>
<metadata name="tag">TapTools</metadata>
<metadata name="tag">Audio</metadata>
<metadata name="tag">Sequencing</metadata>
<metadata name="tag">Synthesis</metadata>
</metadatalist>


<!--INLETS/OUTLETS-->
<inletlist>
<inlet id="0" type="signal">
<digest>Phase ramp: 0..1 per pattern cycle (connect phasor~)</digest>
</inlet>
</inletlist>
<outletlist>
<outlet id="0" type="signal">
<digest>Pitch as MIDI note number — to tap.303~'s left inlet</digest>
</outlet>
<outlet id="1" type="signal">
<digest>Gate; edge amplitude 1..2 encodes accent — to tap.303~'s right inlet</digest>
</outlet>
<outlet id="2" type="int">
<digest>Current step number (1-based), sent at each step change</digest>
</outlet>
</outletlist>


<!--MESSAGES-->
<methodlist>
<method name="signal">
<arglist/>
<description>
The phase ramp. The row derives the current step from the phase (swing warps the
odd-step starts) and plays the pattern sample-accurately. Stateless against
phase: jump, scrub, or reverse the ramp and the line follows.
</description>
</method>
<method name="step">
<arglist>
<arg name="step-number" type="int" optional="0"/>
<arg name="pitch" type="float" optional="0"/>
<arg name="accent" type="int" optional="1"/>
<arg name="slide" type="int" optional="1"/>
</arglist>
<description>
Set one step and gate it on: step number (1..64), pitch as a MIDI note number
(fractional = cents), then optional accent and slide flags (0/1). A slide flag
means the step is approached legato from the note before it.
</description>
</method>
<method name="rest">
<arglist>
<arg name="step-number" type="int" optional="0"/>
</arglist>
<description>
Silence one step (its pitch and flags are kept).
</description>
</method>
<method name="pitches">
<arglist>
<arg name="notes" type="list" optional="0"/>
</arglist>
<description>
Set per-step pitches as MIDI note numbers (fractional = cents).
</description>
</method>
<method name="gates">
<arglist>
<arg name="steps" type="list" optional="0"/>
</arglist>
<description>
Set which steps sound: one 0/1 per step (0 = rest).
</description>
</method>
<method name="accents">
<arglist>
<arg name="steps" type="list" optional="0"/>
</arglist>
<description>
Set per-step accent flags: accented steps gate at 2.0 (the voice reads accent
depth = amplitude - 1).
</description>
</method>
<method name="slides">
<arglist>
<arg name="steps" type="list" optional="0"/>
</arglist>
<description>
Set per-step slide flags. A flagged step is approached legato: the gate holds
through the boundary and the voice glides to it without retriggering.
</description>
</method>
<method name="store">
<arglist>
<arg name="slot" type="int" optional="0"/>
</arglist>
<description>
Store the pattern in a slot (1..16).
</description>
</method>
<method name="recall">
<arglist>
<arg name="slot" type="int" optional="0"/>
</arglist>
<description>
Recall a slot (1..16); it takes over at the quantize boundary (default: the next
pattern top).
</description>
</method>
<method name="todict">
<arglist>
<arg name="dictionary-name" type="symbol" optional="0"/>
</arglist>
<description>
Write the pattern (length, pitches, gates, accents, slides) into a named
dictionary, for saving with the patcher or passing around as data.
</description>
</method>
<method name="fromdict">
<arglist>
<arg name="dictionary-name" type="symbol" optional="0"/>
</arglist>
<description>
Restore a pattern previously written with todict.
</description>
</method>
<method name="clear">
<arglist/>
<description>
Empty the pattern (all rests) and reset the clock state.
</description>
</method>
</methodlist>


<!--ATTRIBUTES-->
<attributelist>
<attribute name="length" get="1" set="1" type="int" size="1">
<digest>Steps per pattern cycle (1..64, default 16)</digest>
<description>
Steps per pattern cycle. A different length than the other rows on the same
phasor is polymeter.
</description>
</attribute>
<attribute name="swing" get="1" set="1" type="float" size="1">
<digest>Swing 0..1 (0 = straight; 0.67 = triplet shuffle)</digest>
<description>
Odd-numbered steps play late by up to half a step. The hardware had no swing —
0 is stock.
</description>
</attribute>
<attribute name="transpose" get="1" set="1" type="float" size="1">
<digest>Live transposition in semitones (-48..48)</digest>
<description>
Applied as notes fire — what the hardware's transpose mode did, without the mode.
</description>
</attribute>
<attribute name="quantize" get="1" set="1" type="symbol" size="1">
<digest>When a recalled pattern takes over: cycle (default), step, or now</digest>
<description>
cycle swaps at the next pattern top, step at the next step boundary, now
immediately.
</description>
</attribute>
<attribute name="mute" get="1" set="1" type="int" size="1">
<digest>Force the gate low (the clock keeps running; pitch holds)</digest>
<description>
Mutes the gate without stopping the row, so unmuting re-enters in place.
</description>
</attribute>
</attributelist>


<!--SEEALSO-->
<seealsolist>
<seealso name="tap.303~"/>
<seealso name="tap.808.seq~"/>
<seealso name="tap.adsr~"/>
<seealso name="phasor~"/>
</seealsolist>

</c74object>
Loading
Loading