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
11 changes: 10 additions & 1 deletion book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@
- [A gate for every bin](nr.md)
- [The spectrum, re-plumbed](spectra.md)

# Part V — The machine, file by file
# Part V — The rhythm section

- [The acid machine](acid.md)
- [The drum machine](drums.md)

# Part VI — The machine, file by file

- [Solving the filter on paper: svf.h](machine/svf.md)
- [The nonlinear loop: ladder.h](machine/ladder.md)
Expand All @@ -35,3 +40,7 @@
- [Grains that sum to one: grm_pitchaccum.h](machine/pitchaccum.md)
- [Two banks and a multiplier: vocoder.h](machine/vocoder.md)
- [One STFT, three effects: fft.h, stft.h, nr.h, spectra.h](machine/spectral.md)
- [Seventeen, not four: diode_ladder.h](machine/diode.md)
- [The couplings are the instrument: tb303_voice.h](machine/tb303.md)
- [One network, eight voices: the tr808 headers](machine/tr808.md)
- [Time as a function of phase: step_seq.h](machine/seq.md)
161 changes: 161 additions & 0 deletions book/src/acid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# The acid machine

The Roland TB-303 was designed to imitate a bass guitar, failed completely,
and accidentally defined thirty years of dance music. What makes it
unmistakable is not any one block — a saw into a lowpass is every synth ever
made — but the *coupling*: accent drives the filter and the amplifier through
shared circuitry with memory across notes, slide is a gate that refuses to
let go, and the envelopes are fixed RC discharge curves with exactly one knob
between them. `tap.303~` is a circuit-informed model of that whole tangle;
`tap.diode~` is its filter as a standalone object; `tap.303.seq~` is the
other half of the instrument. This chapter is what each control trades, and
what the measurements say the model actually delivers.

Companion material: the reference pages and help patchers in the TapTools-Max
package, and two executed verification notebooks —
[`tb303.ipynb`](https://github.com/tap/TapTools/blob/main/notebooks/tb303.ipynb)
for the voice and
[`step_seq.ipynb`](https://github.com/tap/TapTools/blob/main/notebooks/step_seq.ipynb)
for the sequencer — every number below is a measurement from one of them or
from the kernel test suite. Provenance runs through Tim Stinchcombe's filter
analysis, Robin Whittle's Devil Fish documentation, the x0xb0x schematics,
and Robin Schmidt's Open303, whose measured calibrations several constants
adopt verbatim.

## What the hardware is, in one paragraph

One saw-core oscillator (the "square" is the saw through a transistor
shaper, not a clean pulse), into a four-stage **diode**-ladder filter — not
the Moog transistor ladder; the diode ladder's stages load each other, which
is why its resonance is broader, less pure, and entirely its own — then a
one-transistor amplifier. Two envelopes, both decay-only RC discharges: the
Main Envelope sweeps the cutoff (the `envmod` knob decides how much), the
VCA envelope is fixed. Accent makes the Main Envelope hotter *and* faster,
routes it into the VCA, and charges a capacitor (C13) through the resonance
pot — and because C13 doesn't fully discharge between closely spaced accents,
**runs of accented notes bloom**, the famous wow. Slide holds the gate across
the step boundary while the pitch CV glides through a ~60 ms RC. Everything
about a note — pitch, gate, accent, slide — comes from the sequencer, not
the panel. That is why this is three objects, not one.

## The filter first: `tap.diode~`

The panel says "18 dB/oct"; the circuit is four poles whose asymptotic slope
is 24 dB/oct with a shallower region near cutoff — Stinchcombe untangled
this, and the kernel reproduces his published transfer function to
**0.028 dB**. Two behaviors are load-bearing and easy to get wrong:

- **The resonance feedback runs through a 150 Hz high-pass**, so resonance
thins as the cutoff drops — low notes squelch, they don't ring. Pinned by
test: the ring-down Q falls with cutoff.
- **A stock 303 never quite self-oscillates**, and neither does this filter
at stock settings. That emerged from the modeled feedback high-pass rather
than being programmed in, and it's documented as a trait, not a defect.
(Push `resonance` past 1.0 — the bend range runs to 1.5 — and it will sing
for you anyway.)

Like `tap.ladder~` it has a `solver` choice: `fast` (default) or `exact`,
which iterates the re-linearized solve to convergence on the true nonlinear
loop. Measured across a matrix out to
resonance 1.4 and +24 dB drive — beyond anything the hardware can reach —
the two differ by at most **−44.9 dBr**, at 1.6–3.3× the CPU. The exact
solver is there for the suspicious; the fast one is there for the patch.
`oversample` (1/2/4, default 2) and a signal-rate cutoff in the right inlet
round out the `tap.ladder~` surface.

## The voice: `tap.303~`, knob by knob

The attributes mirror the seven-knob panel; the calibrations are Open303's
measured laws.

- **`waveform`** — `saw` or `square`. The square is the hardware's shaped
saw: `−tanh(10^(36.9/20)·saw + 4.37)`, Open303's measured constants
verbatim — rounded and notched, audibly not a 50 % pulse.
- **`cutoff`** — the knob in Hz. Stock travel is the measured 302–2394 Hz;
the attribute range (100–5000) is a flagged bend beyond the panel.
- **`resonance`** — 0..1 is stock; up to 1.5 is the bend.
- **`envmod`** — how much Main Envelope reaches the cutoff, with the
hardware's measured law: 2/3 of the sweep goes above the knob position,
1/3 below, and the "gimmick" offset shifts the resting point down as you
turn it up. The knobs *feel* right because the interaction is modeled, not
just the ranges.
- **`decay`** — Main Envelope decay, 200 ms–2 s. On an accented note the
hardware ignores this knob and runs at ~200 ms; so does the model
(adjustable via the `accdecay` bend, 50–2000 ms).
- **`accent`** — how hard accented notes hit: louder *and* punchier (the
envelope routing), and quackier (the C13 sweep, scaled by the resonance
knob). The wow is measured: over a run of closely spaced accents the
cutoff peak builds by **×1.94**, and decays back within ×0.998 once the
accents stop. Consecutive accents at high resonance are the entire genre.
- **`tuning`**, **`gain`** — cents and dB. Plumbing.

The envelopes carry the schematic's fixed interrelations: MEG attack ~3 ms,
VCA attack ~3 ms with a measured ~1.23 s decay chopped at gate-off, 50 ms when accented.
None of these have knobs on the hardware, so none of them have knobs here —
except through the documented Devil-Fish-style bends (`slide` 10–500 ms,
`attack` 0.3–30 ms, `accdecay`, and `drive` ±24 dB into the ladder, where
the diodes compress: +24 dB of gain buys only 9.2× of RMS). All stock at
their defaults.

Phase 2 added **`vca clean|warm`**: the one-transistor class-A stage as a
slope-normalized biased saturator, in the hardware's signal order. The
distortion tracks the envelope — measured 5.4 % difference signal on quiet
notes, 11.5 % on hot accents — so `warm` thickens exactly where the hardware
does. `clean` (default) is bit-identical to phase 1.

House machinery throughout: `seed`/`tolerance` per-unit component spread (an
`mc.` stack of 303s with different seeds detunes and drifts like a wall of
real units), 16 preset-morph slots with factory acid in 1–8
(squelch, sub, screamer, rubber, knock, bloom, overdriven, glass), and
per-sample ramps on every parameter.

## The note interface, and why slide is free

`tap.303~` is TapTools' first pitched instrument, and its inlets are the
package-wide melodic contract: **pitch as a MIDI note number signal** in the
left inlet, **gate with amplitude-as-accent** in the right — 1.0 is a plain
note, 2.0 fully accented (depth = amplitude − 1). Slide needs no input at
all: *a pitch change while the gate is held is a slide* — legato, no
envelope retrigger, the ~60 ms RC glide — which is exactly the hardware's
own definition. A `note <pitch> [accent] [slide]` message covers patching
without signals.

## The other half: `tap.303.seq~`

Half the 303's sound is sequencer behavior, so the sequencer emits the
voice's contract verbatim: a pitch signal and a gate signal, clocked by a
phase ramp (0..1 per pattern, a `phasor~`). Per step: pitch, gate/rest,
accent, slide. The measured facts, from the sequencer notebook:

- Steps land on the analytic grid within **one sample**; the gate opens at
the step start and closes at **0.5** of the step (Open303's
`stepLength`).
- A slid step is approached with the gate *held*: 16 gated steps with 3
slide flags produce exactly **13 note-ons** — the other three arrive
legato, pitch stepping on the boundary sample, and the voice glides.
- Accented steps gate at 2.0; `transpose` shifts live, like the hardware's
transpose mode without the mode; `swing` and pattern slots with
cycle-quantized `recall` are shared with the drum rows (next chapter).

The 1981 pitch-mode/time-mode data entry is deliberately not recreated. You
keep the data model; you lose the part everyone hated.

## When it is not the right tool

- **You want a generic bass synth.** `tap.vco~` + `tap.svf~` +
`tap.adsr~` give you ADSRs, waveform variety, and a filter that behaves.
This object's value *is* its refusal to decouple.
- **You want the filter without the biography** — `tap.diode~` alone, or
`tap.ladder~` if you want the Moog character instead of the 303's.
- **You want polyphony.** It's a monosynth; `mc.` gives you many monosynths,
which is not the same thing as a polysynth and shouldn't be.

## Checkpoint

A diode ladder that matches the published analysis to 0.028 dB and won't
self-oscillate until you bend it; a voice whose envelopes, accent path, and
C13 memory come from the schematic, with the wow measured at ×1.94 across an
accent run; slide as pure gate-hold, so legato falls out of the note
contract; and a sequencer that emits that contract sample-accurately. The
coupling is the instrument — and every claim above has an executed notebook
cell behind it.
145 changes: 145 additions & 0 deletions book/src/drums.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# The drum machine

The Roland TR-808 is the most thoroughly analyzed drum machine in the
academic literature, and the reason is charming: the whole instrument is
analog synthesis. No samples anywhere — every sound is a small circuit, and
most of them are variations on about four ideas. The `tap.808.*` family
recreates the eight voice channels circuit block by circuit block, one
external per channel, and `tap.808.seq~` supplies the machine's other half
as one sequencer row per patch cord. This chapter is the family tour: the
shared trigger contract, each voice's character and knobs, and the
calibration pass against a real unit that the numbers come from.

Companion material: each voice's reference page and help patcher, the family
overview patcher (`tap.808.maxhelp` — all eight voices sequenced off one
`phasor~`), the
[`tr808_calibration.ipynb`](https://github.com/tap/TapTools/blob/main/notebooks/tr808_calibration.ipynb)
notebook, and the
[`step_seq.ipynb`](https://github.com/tap/TapTools/blob/main/notebooks/step_seq.ipynb)
sequencer notebook. Provenance runs through the Werner–Abel–Smith papers
(DAFx-14 and companions) and the TR-808 Service Notes, read component by
component; every magic constant in the kernel headers carries its schematic
designator.

## One trigger to rule them all

On the hardware, every voice hangs off a common trigger bus: the CPU's 1 ms
pulse rides a voltage between 4 and 14 V depending on the accent circuit,
and a hotter pulse excites each circuit *harder* — more punch, slightly
different timbre — not merely louder. The family keeps that literally:
**every voice fires on a signal rising edge, and the edge's amplitude
(0..1) is the accent**, mapped onto the 4–14 V bus. `bang` and
`trigger 0.7` messages cover the scheduler side. Filter states persist
across triggers, so fast rolls interfere with the ringing tail like the
hardware — no machine-gun effect. And because the excitation is a voltage,
anything that makes an edge can play the kit: a `click~`, an envelope, a
`tap.303.seq~` gate, or the row object built for the job.

## The voices

### `tap.808.kick~` — the bridged-T with a biography

The bass drum is a damped bridged-T resonator (~49.4 Hz from the modeled
component values; Roland's chart optimistically says 56, real units measure
as low as 48) with three behaviors that make it *the* kick, all emergent
from the modeled schematic: for the first ~6 ms the envelope saturates Q43
and the resonator sits near ~129 Hz — the attack punch, which is a
*different mechanism* from the famous downward pitch "sigh" (leakage through
R161, the paper's fitted nonlinearity); and a retriggering pulse re-excites
the center node as the envelope collapses so the note doesn't step down.
Panel knobs: `decay` (seconds of ring at the top), `tone` (click at ~7 kHz
down to ~300 Hz), `level`. Paper-documented bends, stock by default:
`tuning`, `pulse`, `sigh`, `attack` — turn `sigh 0` and the pitch relaxation
disconnects, exactly as the bend does on the bench.

Calibration: against a real unit's knob-gridded sample set, the fundamental
sat within **2.4 %** at every tone/decay position and the −40 dB decay
endpoints within 6 % (72 ms → 2.36 s measured, 69 ms → 2.42 s modeled) —
**no constant needed changing**.

### `tap.808.snare~` and `tap.808.clap~` — resonators plus noise

The snare is two bridged-Ts (the late-revision ~173/336 Hz pair) with a
trigger divider and the "snappy" path — enveloped noise, band-limited around
4 kHz to the measured unit. Fundamentals calibrated within 1.2 %, including
the mode flip at tone-max. The clap channel (`@model clap|maracas`) is the
Service Notes' Figure-13 circuit: band-passed noise near 2 kHz through a VCA
driven by a three-teeth sawtooth retrigger — the "multiple hands" transient —
plus the Q70 reverberation tail. The maracas mode is the same noise voiced
short and bright.

### `tap.808.hat~` and `tap.808.cymbal~` — the metal bank

Six Schmitt-trigger square oscillators (205.3, 369.6, 304.4, 522.7 Hz plus
the two trimmer-tuned at 800 and 540, duty 47.98 %) feed two bandpass
voicings near 3.4 and 7.1 kHz. Werner et al. measured that resistor variance
puts any given unit **up to ~20 % off** those frequencies — which is why no
two 808s' cymbals sound alike, and why `seed`/`tolerance` exists: every seed
is a different unit off the line, and an `mc.` stack of cymbals decorrelates
like real hardware. The hats are **one object with two trigger inlets**
because on hardware they are one circuit with two envelope paths and a
choke — closed chokes open (the Q23/R173 path), pinned by test, and
unimplementable as separate externals. Open-hat decay spans the chart's
90–600 ms; the cymbal's two separately enveloped bands cover its 350–1200 ms
"sizzle" span. `tap.808.cowbell~` taps just the 540/800 pair into the ~860 Hz
voicing with a two-slope envelope; more cowbell is a patching decision.

### `tap.808.tom~` and `tap.808.rim~` — the resonator variations

Six sounds on two objects, as the hardware switches them: `@size low|mid|high`
× `@model tom|conga`. Congas are the tom circuit without its noise layer,
tuned differently; the toms add the D80/D81 attack pitch fall and a pink
noise layer. The rim channel is `@model rimshot|claves`: the rimshot's
~1667 + 455 Hz crack with the swing-VCA's harmonics, versus the claves' pure
~2500 Hz tick. Tunings sit within ~4 % of the measured unit.

## The calibration pass, honestly

The §7.2 calibration ran against a real TR-808 (s/n 103852) recorded from
the individual outs with **knob positions encoded in the filenames** — a
0/2.5/5/7.5/10 dial grid, 116 samples — which upgraded "sounds right" to a
quantitative per-knob-cell comparison. Identical measurements (spectral-peak
fundamental, −40 dB decay, power centroid) ran on both sides. The pitches
were already right nearly everywhere; what the pass actually changed was
*time*: tom, conga, cowbell, and clap tails roughly doubled to match the
unit, the snappy was band-limited and re-enveloped, the rimshot re-voiced
low-dominant, the cymbal's decay span corrected. Each kernel header carries
its residuals. The lesson generalizes: schematics get you the frequencies;
recordings get you the envelopes.

## The other half: `tap.808.seq~`

One row of the 16-step sequencer, as an object: feed it a phase ramp (0..1
per pattern, a `phasor~`) and it emits trigger impulses whose amplitude is
the step's accent — the family contract, straight into any voice. Twelve
rows off one phasor are the hardware's panel, sample-locked forever; the
accent row falls out of giving every row the same `accents` list. The
measured facts, from the sequencer notebook: steps land on the analytic grid
within one sample; the pinned levels are **plain 0.01** (the 4 V base — an
un-accented hit still strikes the circuit) and **accented 0.5** (the accent
knob at noon; 1.0 is the full 14 V); `swing` delays the off-16ths by exactly
swing/2 of a step; a `length 12` row against 16s is the triplet pre-scale
generalized to polymeter; and pattern slots with cycle-quantized `recall`
are the A/B-half and fill switching as one message. `pulse` widens the
impulse into a held gate when you'd rather drive `tap.adsr~` than a drum.

## When it is not the right tool

- **You want *a* kick, not *the* kick.** A sine with an envelope is cheaper
and takes EQ more politely. This family's value is the circuit behavior —
the attack jump, the choke, the accent-as-voltage.
- **You want your own drum sounds.** These circuits are what they are;
`seed`, the documented bends, and the panel knobs bend them, but a
sampler is a sampler.
- **You want 909 hats.** The 909's metal is sampled; this machine's is six
square waves. Different instrument, different chapter, maybe someday.

## Checkpoint

Eight channels, four circuit ideas — bridged-T resonators, a shared metal
bank, noise paths, swing-VCAs — under one amplitude-as-accent trigger bus,
calibrated per knob cell against a real unit and honest about what changed
(the tails) and what didn't (the tunings). The hats choke because they share
a circuit; the cymbals decorrelate because resistors do; and the sequencer
row emits the same voltage idea the voices drink, so the whole kit runs off
one phasor ramp. The machine's two halves, both measured.
6 changes: 5 additions & 1 deletion book/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ The book is organized the way a patch is:
(`tap.5comb~`) and the pitch-accumulating shimmer loop (`tap.pitchaccum~`).
- **Part IV — The spectral set**: the 24-band vocoder (`tap.vocoder~`), the
per-bin spectral gate (`tap.nr~`), and the bin remapper (`tap.spectra~`).
- **Part V — The machine, file by file**: the SampleRateTap-style deep dives —
- **Part V — The rhythm section**: the Roland recreations — the TB-303 voice,
its diode-ladder filter, and its sequencer (`tap.303~`, `tap.diode~`,
`tap.303.seq~`), and the eight TR-808 voice channels with their row
sequencer (`tap.808.*`, `tap.808.seq~`).
- **Part VI — The machine, file by file**: the SampleRateTap-style deep dives —
one chapter per kernel header, deriving the math, reviewing the code, and
recording *why* each algorithm is written the way it is, alternatives and
all. Parts I–IV are for driving the objects; Part V is for trusting them —
Expand Down
Loading
Loading