Skip to content

More modules - #61

Merged
danigb merged 3 commits into
mainfrom
feat/learn-modules
Sep 13, 2026
Merged

danigb merged 3 commits into
mainfrom
feat/learn-modules

Conversation

@danigb

@danigb danigb commented Sep 13, 2026

Copy link
Copy Markdown
Owner

Made with Claude

A sample-and-hold clocked fast, followed by a quantiser - which is what
Synth Secrets Part 17 says an analogue-to-digital converter is, and the
one thing Web Audio cannot build. A BaseAudioContext has one rate, fixed
at construction; a WaveShaperNode with a staircase curve reduces bit
depth but has no notion of time; no node holds a sample.

The anti-alias and reconstruction filters are switches rather than baked
in, because two of Part 17's three claims are claims about the filters:
at rate 13333 a 10 kHz sine reads 3.33 kHz (Figure 17) and antialias: 1
takes it 44.5 dB down; at rate 22050 a 1 kHz sine is a staircase with
images at 21 kHz, and reconstruct: 1 makes it a sine again with its RMS
within 0.03 dB. Both default to off, since aliasing is what the module
is for. Every figure is measured on the real processor at 44.1 and
48 kHz.

One 8th-order Butterworth at 0.45 x rate serves both, four cascaded
biquads whose coefficients are recomputed only when rate changes. Three
exact short-circuits make the default a bit-identical wire: rate at or
above the context's skips the hold, bits: 24 skips the quantiser, and
each switch off skips its cascade.

The cascades flush their state to zero rather than using the library's
alternating DENORMAL constant. That constant is right in digital-delay
and chorus and wrong here - a +/-1e-20 injection is not silence, and
this module has to be silent on silence, asserted as equality with zero
over 60 s with both filters running.

Two things documented rather than hidden: the hold clock is free-running
so a rate that divides nothing jitters the period by a sample, and
mid-tread quantisation puts a level on zero, so bits: 1 has three levels
and bits: 6 has 65 rather than Reid's 64.

decimator joins scripts/_spectrum.ts's copy list, the first package
whose subject is aliasing rather than one that has to avoid it, and its
parameter table joins docs.test.ts in both documents and both
directions.

Claude-Session: https://claude.ai/code/session_01XGpZZMUoV3b3V9bFYW9PMm
New @synthlet/quantizer: a fractional MIDI note on an a-rate input, snapped
to the nearest note of a 12-bit scale mask (ties up, Braids-style hysteresis)
and emitted as Hz or as the note. Synth Secrets Part 16's programmable scale
generator: noise -> SampleHold -> Quantizer is the random arpeggiator.

The scale masks move from arp to scripts/_scales.ts, shared by arp and
quantizer and guarded by worklet-copies.test.ts; arp still exports ArpScale.

Claude-Session: https://claude.ai/code/session_016QJ1tGQ3sfkRd8BRyzb2kc
New @synthlet/modal-resonator: a pool of tuned, decaying resonators played
from a { ratio, level, decay } table via setModes(), with the book's tables
as ModalResonator.modes (kettleDrum, membrane, bell, cowbell, harmonic,
stiffString). Parts 31-41 as one node each.

Each mode is a rotating, decaying phasor rather than a direct-form two-pole:
its envelope is exactly level * r^n at every frequency, and pitch sweeps and
table swaps keep their loudness (the direct form measured +12.9 dB on a
2000 -> 100 Hz sweep). k-rate frequency/decay interpolated per sample, modes
past 0.45 * sampleRate silenced, state flushed to exact zero, mono.

Claude-Session: https://claude.ai/code/session_016QJ1tGQ3sfkRd8BRyzb2kc
@danigb
danigb merged commit 39263aa into main Sep 13, 2026
9 of 12 checks passed
@danigb
danigb deleted the feat/learn-modules branch September 13, 2026 14:36
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.

1 participant