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
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# TapTools kernel

[![build](https://github.com/tap/TapTools/actions/workflows/build.yml/badge.svg)](https://github.com/tap/TapTools/actions/workflows/build.yml)
[![Tap House Style](https://github.com/tap/TapTools/actions/workflows/style.yml/badge.svg)](https://github.com/tap/TapTools/actions/workflows/style.yml)
[![Docs](https://github.com/tap/TapTools/actions/workflows/docs.yml/badge.svg)](https://github.com/tap/TapTools/actions/workflows/docs.yml)

The portable DSP library behind the TapTools Max package: header-only, plain C++20, **no Max SDK,
no min-api, no Jamoma**. One self-contained header per object under `include/taptools/`, each in
its own `tap::tools::<family>` namespace. The TapTools Max externals are thin
Expand Down Expand Up @@ -28,6 +32,7 @@ header adds no nested namespace, the class) the kernel lives in.
| `autowah.h` | `tap.autowah~` | Snow White-style envelope filter (`tap::tools::autowah`) |
| `overdrive.h` | `tap.overdrive~` | LGW-voiced feedback overdrive (`tap::tools::od`) |
| `vca.h` | `tap.vca~` | Voltage-controlled amplifier (`tap::tools::vca`) |
| `adsr.h` | `tap.adsr~` | Virtual-analog ADSR envelope, legacy Jamoma curves as modes (`tap::tools::adsr`) |

**Voices, drums, and sequencing**

Expand Down Expand Up @@ -62,12 +67,13 @@ header adds no nested namespace, the class) the kernel lives in.
| Kernel | Max object | Contents |
|---|---|---|
| `tune.h` | `tap.tune~` | Monophonic pitch correction (`tap::tools::tune`) |
| `harmonizer.h` | `tap.harmony~` | Formant-preserving multi-voice harmonizer (`tap::tools::harmony`) |
| `grm_comb.h` | `tap.5comb~` | GRM comb-bank recreation (`tap::tools::fivecomb`) |
| `grm_pitchaccum.h` | `tap.pitchaccum~` | GRM PitchAccum recreation (`tap::tools::pitchaccum`) |

`taptools.h` is the umbrella header that pulls in every kernel above. `stft.h`, `tune.h` and
`conv_engine.h` reach into `tap::dsp` (the pinned DspTap submodule) for the real FFT and the pitch
primitives; every other kernel is standard library only.
`taptools.h` is the umbrella header that pulls in every kernel above. `stft.h`, `tune.h`,
`harmonizer.h` and `conv_engine.h` reach into `tap::dsp` (the pinned DspTap submodule) for the
real FFT and the pitch primitives; every other kernel is standard library only.

Plus, all Max-free:

Expand Down
140 changes: 140 additions & 0 deletions book/PLAN-recipes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Plan — the Recipes part

> **Status: drafted.** The part opener and all ten recipes are written and live in
> `src/recipes/` per the placement below (2026-08-05). This file remains as the drafting
> record, the plans-directory way. The improvement findings the drafting surfaced live in
> `plans/recipes-improvements.md` in the TapTools-Max repo (the design-of-record for object
> changes); new recipes now wait on new objects.

Planning document for Part IX of *Tools on Tap*: **Recipes** — the book's third kind of
chapter. Parts I–VII say what each object is for; Part VIII says why to trust it; a recipe
puts several objects on one patch cord and chases a specific, named sound.

## Placement in SUMMARY.md

A new part after the machine part:

```md
# Part IX — Recipes

- [How to read a recipe](recipes/cookbook.md)
- [One machine, four decades](recipes/808-classics.md)
- [Three oscillators into a ladder](recipes/minimoog.md)
- [The patches with names on them](recipes/moog-classics.md)
- [Move a knob while it loops](recipes/acid-line.md)
- [The ostinato machine](recipes/sequenced-modular.md)
- [The robot on the radio](recipes/robot-voice.md)
- [The staircase and the wash](recipes/shimmer.md)
- [Sixteenths into a listening filter](recipes/funk-filter.md)
- [A field guide to rooms](recipes/rooms.md)
- [Chords with no keyboard](recipes/comb-drones.md)
```

The introduction's organization list gains a matching Part IX bullet.

## The rules a recipe is held to

Stated in the part opener (`recipes/cookbook.md`), enforced in drafting:

1. **Every knob named exists, spelled as the attribute is spelled.** Recipes were drafted
against the wrapper sources in TapTools-Max (`source/projects/`), not from memory — that
pass is what caught, e.g., that the snare has no `decay` (its tail rides `tone`), the
clap's tail knob is `tail`, the sequencer programs via `hits`/`accents`/`velocities`/
`step` (there is no `steps` message), `tap.ladder~`'s `mode`/`solver` are numeric
indices at the Max layer, and `tap.adsr~` gates on signal level > 0.5 (so a
`tap.808.seq~` impulse at the default levels will not open it).
2. **Settings are starting points; measurements are citations.** A recipe's knob values are
ears' work and say so. Any *measured* number a recipe leans on (the kick's ~49 Hz
fundamental, the ladder's THD-vs-drive walk, sequencer polymeter) is borrowed from an
executed notebook or pinned test and cited, never re-derived — the "measured, not
remembered" promise unchanged.
3. **Provenance stays honest.** Documented production history (who used the machine) is
stated as such; pattern grids are labeled starting points, not transcriptions; and no
recipe claims to *be* a record — mix, room, tape, and hands are out of the box.
4. **Ingredients are ranked.** Every recipe ends with the vco-chapter-style ordered list of
what each element buys, so cutting from the bottom is a stated option.

## Shipped recipes

- **`recipes/808-classics.md` — One machine, four decades.** Four kits off one
`phasor~`/`tap.808.seq~` scaffold: "Planet Rock" electro (1982), "Sexual Healing" slow
soul (1982), Miami bass (the tuned long-decay kick as bassline), trap (half-time,
polymeter hat-roll rows via `length 24`/`length 32`). Evidence borrowed:
`tr808_calibration.ipynb` (kick fundamental, calibration residuals), `step_seq.ipynb`
(grid accuracy, polymeter), the drums chapter's pinned roll/choke behavior.
- **`recipes/minimoog.md` — Three oscillators into a ladder.** Completes the oscillator
chapter's Moog recipe into a playable monosynth voice: stack → ladder → `tap.vca~`, two
`tap.adsr~` contours (with the period-correct release-switch note), gate/pitch plumbing,
and bass + lead settings tables. Evidence borrowed: `vco.ipynb` and `ladder.ipynb` via
their chapters.
- **`recipes/moog-classics.md` — The patches with names on them.** The voice above driven
at four records as deltas from its bass/lead tables: Winwood's "While You See a Chance"
hook, Worrell's "Flash Light" stacked-Minimoog bass, Wright's "Shine On" lead, and
Emerson's "Lucky Man" modular solo. Carries the answer to "do we need a Moog modular
object?" — no: a modular is routing freedom, and Max is the patch panel; the modules
already ship (`tap.vco~`/`tap.ladder~`/`tap.adsr~`/`tap.vca~`/`tap.noise~` + the
sequencer pair). Gear provenance is stated per patch (documented vs. reconstruction).

## The second wave (shipped 2026-08-05)

All seven backlog recipes landed in one pass, each drafted against a fresh wrapper-source
sweep (the audit found and fixed a shipped-chapter drift along the way: the pitchaccum
chapter's `pitch1`/`feedback1` spellings are actually `trans1`/`fb1`, feedback on a 0–99
scale — corrected in `src/pitchaccum.md`):

- **`recipes/acid-line.md` — Move a knob while it loops.** The Phuture method: a 16-step
line (grids + the `pitches`/`gates`/`accents`/`slides` lane messages), the knob rides,
accent runs into the measured ×1.94 C13 bloom, `tap.overdrive~` after.
- **`recipes/sequenced-modular.md` — The ostinato machine.** Berlin school / "I Feel
Love": `tap.303.seq~` → `mtof~` → external slew → the Moog voice; transpose as harmony;
the honest wrinkle that the vco's signal inlet bypasses `smooth` (→ improvements plan).
- **`recipes/robot-voice.md` — The robot on the radio.** Carrier casting (saw pair + 10 %
noise as the sibilance budget), the three settings rows (talk/choir/rhythm-transfer),
the left-inlet-is-modulator debugging fact. Extended with the songbook: "In the Air
Tonight"'s VP-330 ghost choir, the front-and-center robots (ELO/Styx/Beasties/
Kraftwerk), the talkbox distinction, "Hide and Seek" honestly labeled a harmonizer
(with the `tap.shift~` + `tap.semitone2ratio` stack as the closer route), and an
Orange-school plugin-era carrier — built as our own VA voicing, with the house rule
against reverse-engineering shipping products stated in print.
- **`recipes/shimmer.md` — The staircase and the wash.** The full Eno-school chain:
pitchaccum spiral (+12/+7) into `tap.verb~` or a convolved church; damping as the
make-or-break; descent, micro-halo, and morph-gesture variants.
- **`recipes/funk-filter.md` — Sixteenths into a listening filter.** Clav chop, bass
quack (factory slot 2), cocked wah (slot 4), the sidechain and envelope-outlet patch
points; honest Mu-Tron distancing per the autowah chapter.
- **`recipes/rooms.md` — A field guide to rooms.** IR curation for `tap.convolve~`:
shopping list, sixty-second audition drill, placement (`predelay` first, `blocksize` by
role, `set` for performance swaps).
- **`recipes/comb-drones.md` — Chords with no keyboard.** Five `tap.5comb~` voicings as a
keepable table (factory, open fifth, just major, dark cluster, √2 bell plate), ringing
techniques, the eight-second morph gesture.

**The audit's first shipped object (2026-08-05):** the songbook's "Hide and Seek" finding
("the mechanism is a formant-corrected harmonizer and no object provides it") became
`tap.harmony~` — kernel `taptools/harmonizer.h` on the DspTap pvoc/LPC substrate, seven
oracle-based test scenarios, capi + bridge, wrapper with reference page and help patcher —
and **`recipes/choir-of-one.md`** documents it: the instrument (corrector → harmonizer),
the Bon Iver worked examples ("Woods" as stacked chapel with the overdub-honesty note;
"715 - CRΞΞKS" as the Messina-school live stack), craft notes, and the robot-vs-choir fork
back to the vocoder chapter. The executed verification notebook shipped the same day
(`notebooks/harmonizer.ipynb` — 0.04-cent interval accuracy, 3.7e-8 dry-alignment
residual, the formant-centroid measurement — cited by the recipe). A proper object
chapter (Part VI territory) remains future work.

Other new recipes wait on new objects (or on the improvements plan landing — e.g. the vco
performance section would simplify the Moog chapters' vibrato plumbing).

## Notes for drafting

- Titles follow the book's voice: image first, no object name in the title.
- Pattern grids are `text` code blocks, 16 columns with a step-number header; `X` accented,
`x` plain, `.` rest — the two-level scheme matches the sequencer's `plain`/`accented`
hardware model, which is the idiom recipes should teach first (per-step `velocities` is
the documented escape hatch).
- Tempo math is stated once in the scaffold section (`phasor~` frequency = BPM ÷ 240 for a
16-step bar) and reused.
- Figure candidates (not yet drawn): the shared drum-kit scaffold as a proper signal-flow
SVG; the Moog voice wiring diagram in the house block-diagram style (`book/figures/`).
- If a wrapper surface changes (e.g. `tap.ladder~` ever grows symbolic `mode` values), the
recipes are the pages most likely to silently rot — re-check them against the wrappers
when bumping the TapTools-Max side.
15 changes: 15 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,18 @@
- [Three ways to move a pitch: yin.h, psola.h, pvoc.h](machine/pitch.md)
- [The nearest allowed note: tune.h](machine/tune.md)
- [The clipper in the loop: overdrive.h](machine/overdrive.md)

# Part IX — Recipes

- [How to read a recipe](recipes/cookbook.md)
- [One machine, four decades](recipes/808-classics.md)
- [Three oscillators into a ladder](recipes/minimoog.md)
- [The patches with names on them](recipes/moog-classics.md)
- [Move a knob while it loops](recipes/acid-line.md)
- [The ostinato machine](recipes/sequenced-modular.md)
- [The robot on the radio](recipes/robot-voice.md)
- [A choir of one](recipes/choir-of-one.md)
- [The staircase and the wash](recipes/shimmer.md)
- [Sixteenths into a listening filter](recipes/funk-filter.md)
- [A field guide to rooms](recipes/rooms.md)
- [Chords with no keyboard](recipes/comb-drones.md)
4 changes: 4 additions & 0 deletions book/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ The book is organized the way a patch is:
recording *why* each algorithm is written the way it is, alternatives and
all. Parts I–VII are for driving the objects; Part VIII is for trusting them —
or changing them.
- **Part IX — Recipes**: whole patches chasing specific sounds — the TR-808
kits behind four decades of records, the three-oscillator Moog voice —
with settings you can check against the reference pages and the honest
accounting of what each ingredient buys.

More chapters land as objects mature; the utility and Jitter objects live in
their reference pages, where they belong.
26 changes: 13 additions & 13 deletions book/src/pitchaccum.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ staircase climbs; in the ordinary patch every echo is the same interval.*

## The knobs, one by one (per shadow, ×2)

### `pitch1` / `pitch2` — the step of the staircase
### `trans1` / `trans2` — the step of the staircase

±24 semitones, continuous. Musical intervals (+7, +12, +5) make harmony;
small offsets (±0.1–0.3 st) make lush detune-echo instead of a spiral;
Expand All @@ -55,12 +55,12 @@ negative values descend into the dark version nobody expects.
Up to 3 s per shadow. Short (50–150 ms) blurs the passes into a texture;
long (0.5–2 s) articulates each step of the climb as an audible echo.

### `feedback1` / `feedback2` — how many steps
### `fb1` / `fb2` — how many steps

How much survives each trip. 0.3 gives two or three audible generations; 0.7
a long climb; 0.9+ a texture that essentially sustains until the transposition
walks it out of range (energy shifted past the audible band is the spiral's
natural exit).
How much survives each trip, 0–99. 30 gives two or three audible
generations; 70 a long climb; 90+ a texture that essentially sustains until
the transposition walks it out of range (energy shifted past the audible
band is the spiral's natural exit).

### `xfade` — the grain crossfade

Expand All @@ -87,23 +87,23 @@ spirals and a timed `recall` between them is a gesture in itself.

## Recipes

- **Shimmer, the classic:** shadow 1 at +12, delay ~400 ms, feedback 0.75;
shadow 2 at +7, delay ~650 ms, feedback 0.6; both into a reverb
- **Shimmer, the classic:** shadow 1 at +12, delay ~400 ms, `fb1 75`;
shadow 2 at +7, delay ~650 ms, `fb2 60`; both into a reverb
(`tap.convolve~` with a long church, or `tap.verb~`). The reverb is
load-bearing — shimmer is spiral *plus* wash.
load-bearing — shimmer is spiral *plus* wash. The full patch has its own
recipe in Part IX.
- **The descent:** −5 and −12, long delays, moderate feedback — a staircase
into the basement, much rarer and much creepier.
- **Micro-thickener:** ±0.15 st, 60/90 ms delays, feedback 0.5, `xfade`
- **Micro-thickener:** ±0.15 st, 60/90 ms delays, feedback 50, `xfade`
wide — not a spiral at all, just an expensive-sounding widener.

## When it is not the right tool

- **One clean transposition, no loop:** `tap.shift~` is the plain shifter —
same modernized engine, none of the plumbing.
- **Formant-true vocal shifting:** granular transposition shifts formants
with the pitch; chipmunks live this way. A vocoder-based resynthesis
(`tap.vocoder~` has other talents) or a dedicated formant tool is the
answer there.
with the pitch; chipmunks live this way. `tap.harmony~` is the dedicated
tool — formant-preserving voices at fixed intervals, chords included.
- **Rhythmically exact multi-tap echoes:** the delays here serve the loop;
`tap.multitap~` serves the grid.

Expand Down
Loading
Loading