The master phase and its corrections: vco.h
The user-facing chapter promised an oscillator whose folded harmonics sit ~47 dB down, whose analog section is "exactly zero by default" with a seed that works like a serial number, and whose FM survives through zero. Each claim is a theorem about this file or a measurement of it. This appendix derives the corrections — polyBLEP, the leaky triangle, the sync patch — then the analog-character section, including the one place where honest analysis contradicted intuition and the tests were written to match.
One phase, many readings
There is a single accumulator, m_phase ∈ [0,1), advanced once per sample
in step:
f_eff = base_hz · 2^(cents/1200) + fm_hz (pitch is exponential,
dt = f_eff / m_sr, clamped to ±0.49 FM is linear, in Hz)
adt = max(|dt|, 1e-8)
cents collects detune, drift, jitter, the per-unit tolerance offset, and
track — everything musical multiplies; only FM adds. Every waveform is a
reading of the same phase: sine through sin, saw as 2p−1, pulse as a
comparison against pw, triangle as an integral. The shape morph
crossfades adjacent readings of one phase, so it can never produce a
discontinuity the phase itself doesn't have. The problem is entirely the
discontinuities.
The fan-out the chapter title promises: every waveform is a reading of the same φ.
The residual: deriving poly_blep
A naive saw jumps by −2 at the wrap; a step's spectrum falls at only 6 dB/oct, so its harmonics march past Nyquist and fold back inharmonic. The ideal fix is a band-limited step — the integral of a sinc. The polyBLEP observation: the band-limited step differs from the naive step only near the edge, so instead of storing sinc-integral tables (minBLEP), approximate the difference with a polynomial. Take the crudest kernel one sample wide per side — a unit-area triangle, b(τ) = 1 − |τ| on τ ∈ [−1, 1] with τ in samples from the discontinuity — integrate, subtract the step:
s_bl(τ) = (τ+1)²/2 τ ∈ [−1, 0]
s_bl(τ) = 1 − (1−τ)²/2 τ ∈ [0, 1]
r(τ) = s_bl − s_naive:
r(τ) = (τ+1)²/2 τ ∈ [−1, 0) (before the edge)
r(τ) = −(1−τ)²/2 τ ∈ [0, 1] (after the edge)
Scale by 2 — the saw's wrap step — and these are exactly the file's
poly_blep branches: just after the wrap (t < dt, normalized t/dt = τ),
t + t − t*t − 1 = −(1−τ)² = 2·r; just before it (t > 1.0 − dt,
normalized (t−1)/dt = τ ∈ [−1,0)), t*t + t + t + 1 = (τ+1)² = 2·r.
Three properties fall out of the derivation:
- Continuity at the window edges. r(−1) = r(1) = 0: the correction fades in and out without new discontinuities of its own.
- The midpoint property. r(0⁻) = +½, r(0⁺) = −½: the corrected edge passes through the middle of the jump, as a true band-limited step does.
- "±1 sample" precisely. A sample lands in a branch iff its phase is
within
dtof the wrap, and phase movesdtper sample — exactly the last sample before and the first after each edge are touched, ever; the scope trace still looks like a saw.
The triangle kernel approximates the sinc (its spectrum is sinc², not a brickwall), so suppression is finite and measurable: the notebook drives a 3951 Hz saw, whose 13th harmonic folds to 3364 Hz, and measures it at −26.7 dB naive versus −74.2 dB with polyBLEP — 47.5 dB of suppression. The notebook's sample-level zoom shows the mechanism: the corrected saw passes through +0.588 and −0.856 on its way down, where the naive saw jumps in a single step.
Saw, pulse, and the second BLEP
saw_at is the reading minus the residual: 2·bent(p,·) − 1 − poly_blep(p, dt) (subtracted: the wrap step is −2, poly_blep is
normalized for +2). pulse_at is ±1 with two edges: the rising edge at
the wrap (step +2, residual added) and the falling edge at p = pw
(step −2, residual subtracted) — the latter evaluated at wrap01(p − pw),
re-centering the phase coordinate so that edge sits at zero of its own
window and the same branches apply. Calibration is pinned by measurement:
a bipolar pulse at duty d must average 2d − 1, and the notebook measures
−0.800 / −0.500 / +0.000 at 10 / 25 / 50 %; the kernel test holds the 25 %
mean within ±0.03.
The triangle: integrate, but leak
A triangle is the integral of a square — the classic analog trick. A ±1
square at frequency f forces slope ±4f (2 units in half a period 1/(2f)),
so the per-sample increment is ±4·f/fs = ±4·dt, which is tri_tick's
scaling exactly:
m_tri_state = 0.999 · m_tri_state + 4.0 · adt · sq
giving peak ±1 with no post-normalization. The 0.999 is the honesty tax:
the BLEP-corrected square's samples do not sum to exactly zero per period
(the two edges land at different sub-sample positions, so their
corrections don't cancel — and tri_pw skew under imperfect makes the
imbalance deliberate), and a pure integrator would ramp that residue to
infinity. The leak turns the integrator into a one-pole highpass with
corner fs·(1 − 0.999)/2π ≈ 7.6 Hz at 48 kHz — far below any audible
fundamental, high enough to hold DC bounded.
Why the integrated square is correctly antialiased: integration multiplies the spectrum by 1/ω, −6 dB/oct. The square's already-suppressed alias residual was generated near Nyquist, where 1/ω is smallest, so integrating a BLEP square improves the alias-to-harmonic ratio — the correction gets cheaper exactly where the waveform gets harder, which is why this hardware trick survives digitally intact.
Through-zero FM
Because FM adds in Hz after the exponential pitch math, dt can go
negative and the phase genuinely runs backward — that is all "through
zero" means, and why the sidebands stay coherent when the modulation
swings past the carrier. Two guards make it safe. The BLEP windows use
adt = |dt|: a window is a duration, one sample each side of an edge,
whichever way the phase travels (with a 1e-8 floor so the t /= dt
normalization survives a frozen phase). And dt is clamped to ±0.49: at
|dt| ≥ 0.5 the window tests t < dt and t > 1 − dt would overlap and
every sample would be "at an edge" — the clamp keeps the effective
frequency below Nyquist, where the model means anything at all. Measured:
a 500 Hz sine under ±900 Hz of FM at a 100 Hz rate — depth past the
carrier, genuinely through zero — puts its sideband at −13.7 dB with
−158.3 dB between the lines (144.5 dB of contrast), bounded at |y| = 1.00.
Hard sync, one-sided
A rising zero crossing on the sync input (m_sync_prev ≤ 0, sync > 0)
resets the phase. Linear interpolation locates the crossing inside the
sample:
frac = m_sync_prev / (m_sync_prev − sync) ∈ [0, 1)
m_phase = wrap01((1.0 − frac) · dt)
— the phase restarts from zero at the crossing and accumulates only the
remaining fraction of the sample, so sync pitch is sub-sample accurate
(the notebook's synced slave measures periodic at 110.1 Hz against a
110 Hz master). The reset is still a discontinuity of size
d = waveform_out_peek(p_old, …) − waveform_out_peek(wrap01(p_new), …),
sized on the morphed waveform without advancing the triangle integrator:
x = 1.0 − frac correction += d · 0.5 · x²
This is a first-order polynomial BLEP, honestly cruder than the saw's:
one-sided, because the pre-reset sample is already output when the
edge arrives — a reset cannot be predicted — and a one-sided patch can
never reproduce the full band-limited edge (the midpoint property needed
both sides). d·½x² is the triangle-kernel residual for a step landing x
into a sample; the code feeds it x = 1 − frac, the elapsed fraction
since the crossing, so its weighting runs opposite to the two-point post
branch (½·frac²) — at the first-order accuracy a one-sided patch can
claim, both are O(d) click reducers vanishing at one end of the window.
The header flags minBLEP tables as the wholesale upgrade; a m_pending
slot, read and cleared each sample but never written, is scaffolding for
the second correction sample it would need.
The analog section, derived (2026-07)
Two time scales of pitch noise. tick_drift is sample-and-hold noise
redrawn every m_sr / 2 samples (~2 Hz) smoothed by a one-pole with
a = 1 − exp(−2π·0.5/m_sr) — the exact discrete step of a 0.5 Hz lowpass.
tick_jitter is the same structure at ~80 Hz through ~40 Hz: the fast
companion, trembling where drift strolls. Both are depth-scaled in cents
into the pitch path. Measured: relative period spread 2.01×10⁻⁷ at jitter
0 versus 2.74×10⁻³ at 10 cents — four orders of magnitude of
micro-instability, still under the test's 0.02 ceiling.
The bent ramp, honestly. imperfect bows the saw via
bent(p, bend) = p + bend·p·(1−p), bend = 0.35·imp·m_tol_curve. The
parabola vanishes at both endpoints, so the wrap step stays exactly 2 and
the BLEP stays correctly sized — why the bend lives inside the ramp
reading. Now the honest part. In x = p − ½ the saw 2p−1 = 2x is odd (a
sine series) while the parabola p(1−p) = ¼ − x² is even (a cosine series):
the bend's Fourier content is in quadrature with the saw's own
components. Harmonic k gains an orthogonal part of relative size bend/(πk)
that moves its magnitude only at second order — about 0.05 dB at k = 1
for the maximal bend of 0.35, per √(1 + (bend/πk)²): a scope-obvious shark
fin, almost no harmonic-magnitude shift. Discovered by measurement — and
the kernel test matches the truth: it asserts the waveform bow (interior
deviation > 0.03 at imperfect 1) and makes no harmonic-magnitude claim.
Where the spectral work is actually done. The reset corner rounds
through a one-pole whose cutoff closes from ~22 kHz toward ~8 kHz
(fc = min(22000 − 14000·imp, 0.45·m_sr), coefficient cached against
m_round_imp): measured, the saw's 40th harmonic (17.6 kHz) is 6.4 dB
quieter at imperfect 1; the test requires > 4 dB. The triangle skews via
tri_pw = clamp(0.5 + imp·m_tol_tri·0.01, 0.05, 0.95) — duty asymmetry in
the integrated square is even harmonics — measured: triangle h2 rises from
−185.5 dB (numerically absent) to −34.1 dB at imperfect 0.8. The sine
reads a mildly bent phase (bent(p, 0.5·bend)), the pulse width takes a
static offset up to ±1.5 %, the whole unit a pitch offset up to ±2 cents
(m_tol_cents).
Which unit you own. The tolerances come from a separate stream:
compute_tolerances hashes the seed (m_seed * 2654435761u + 12345u)
into its own local LCG, never touching the runtime m_rng. The contract:
clear() resets m_rng = m_seed and all noise state but does not re-roll
tolerances — resetting the oscillator must never change which unit off the
production line you own; only set_seed re-rolls, because changing the
serial number is changing the unit. Every tolerance is scaled by
imperfect at use, yielding the contract the section rests on: at
imperfect 0, every seed is bit-identical to the ideal oscillator. The
kernel test renders seeds 7 and 8 and requires ya == yb — exact equality
over 24000 samples — and the notebook confirms it; conversely, with
drift 20 seeds 7 and 8 diverge by up to 0.183 (measured) while the same
seed renders bit-identically, and the test pins that at imperfect 0.6
different seeds are audibly different units.
track.
cents += track · log₂(base_hz / 440.0)
A V/oct converter's calibration error grows linearly in octaves from its
trim point; this is that line, exact at 440 Hz by construction
(log₂ 1 = 0). Measured at track 5: −15.0 / −10.0 / −5.0 / +0.0 / +5.0 /
+10.0 / +15.0 cents across −3…+3 octaves; the test holds the trim point
under 1 cent, ±3 octaves within 2 cents of ±15.
The engineering ledger
- Determinism is structural. All randomness flows from one 32-bit LCG
(1664525 / 1013904223) seeded by
m_seed(0 remapped to 1); no wall clock, nostd::random— renders, tests, and mc. stacks reproduce bit-for-bit, and the jitter test pins same-seed bit-identity. - Off means exactly off.
tick_drift/tick_jitterreturn before consuming the RNG at zero depth — a default-configured oscillator never advancesm_rng, so different seeds render identically until a stochastic feature is engaged. The corner-rounding pole is gated onimp > 0.0, its state primed while bypassed (m_round_lp = y) so engagingimperfectmid-note is click-free. - The triangle integrator ticks only when the morph needs it.
waveform_outshort-circuits the crossfade endpoints (a <= 0.0), andtri_tickis stateful — skipping it when unused is a cost saving and a correctness rule (parking at pure saw must not silently integrate); sync sizing useswaveform_out_peekfor the same reason. - Clamps with reasons:
dtat ±0.49 (window overlap / Nyquist),adtfloored at 1e-8 (division inpoly_blep),tri_pwin [0.05, 0.95] andpwin [0.01, 0.99] (an edge pair must stay two distinct windows). - The house frame: per-sample linear ramps with an active-count fast
path, 16 preset slots morphable over time, allocation-free processing,
setters safe while audio runs — the same bones as
ladder.handsvf.h, so the wrapper stays a shim.
Checkpoint
One master phase; every waveform is a reading of it, and every reading's
discontinuity gets the residual of a triangle-kernel band-limited step —
two samples per edge, continuous at its window boundaries, a measured
47.5 dB of alias suppression at the folded 13th harmonic. The triangle
integrates the corrected square (slope ±4f, hence 4·adt) with a 0.999
leak; FM adds in Hz so the phase can run backward, adt keeping the
windows directionless; sync resets with sub-sample accuracy and patches
the step one-sidedly because resets can't be predicted — minBLEP is the
flagged upgrade. The analog section is derived noise at two time scales, a
quadrature-honest bent ramp, a rounding pole, a skewed duty, and a
calibration line exact at A440 — all drawn from a tolerance stream
clear() never touches, all scaled by imperfect, and all provably
absent at zero: the ideal oscillator is a test-pinned invariant, not a
default setting.