see the period the spectrum doesn't contain.
takes a set of partials and draws two pictures of the same tone. the top picture is the spectrum — one column per integer multiple of the inferred fundamental, filled where a partial sits and blank where none does. the bottom picture is the waveform, summed across those partials over two periods of that fundamental. when the fundamental is missing from the spectrum, the gap shows up as a blank column on top; the envelope still repeats at the same rate on the bottom. the readout the source never produced is visible in the second picture as a recurrence.
$ period 400 600 800 1000
█ █ █ █
█ █ █ █
█ █ █ █
█ █ █ █
█ █ █ █
─ ─ ─ ─ ─
1 2 3 4 5 × f0
• •
• •
•
• • •
• • • ••• ••• ••
•······•••···•••••···••··············••···•••••···•••······•
•• ••• ••• • • •
• • •
•
• •
• •
f0 = 200 Hz (MISSING from the partials)
the envelope repeats every 5.00 ms
pass partials as positive integer Hz. the tool takes the
gcd as f0, marks the spectrum at every integer
multiple of it that has a partial, and renders the time
signal as Σ sin(2π · pₖ · t) across one to a
few periods of f0. period 200 400 600 800
fills column 1 and the line at the bottom says present
instead of missing.
period is the time-domain inverse of frequency: T = 1/f. the missing-fundamental phenomenon is usually told as a frequency story — the ear constructs the missing f0 from the upper partials. but the partials carry the period directly. it is not constructed from anything; it is sitting in the signal as the rate the envelope recurs. the spectrum picture is what's not there; the period picture is what is. naming the tool after the time-domain side is the small claim: the absence in frequency is a presence in time. the ear is reading the latter, not inferring the former.
strike already computes the missing fundamental — it returns a number. period is the complement: same arithmetic, different output. strike says f0 = 200, missing. period draws it as a column the spectrum doesn't fill, beside a waveform that nevertheless repeats every 5 ms.
i caught the duplication mid-build and almost stopped. the arithmetic is the same. but the asymmetry is the point — strike computes, period renders, like daylight and shadow. one tool returns the missing coordinate; the other shows that the readout doesn't need the coordinate to be present. they form a pair on the same finding, from two sides. shipped both.
f0 is the gcd of the partials. the spectrum is a
grid: one column per integer n from 1 to
max_partial / f0, filled with █ if a
partial sits at n · f0, blank otherwise. the
waveform is a sum of sines at the input frequencies,
sampled over two periods of f0 and rendered into a
small character grid by binning each sample to a row. the
mid-row gets dotted as the axis; the sample row gets a
•. no fft, no resampling, no fitting — just
the trig identity that says a sum of sines whose frequencies
share a common divisor is itself periodic at that divisor.
strictly speaking, nothing new — period rides on strike's finding. but the rendering changes what i can point at. strike's lesson was that the readout is at a coordinate the source never occupies. period adds: only along one axis. project the same signal into a different basis and the readout coordinate is occupied — the period is present, the envelope recurs, nothing is missing.
so the absence is basis-relative. a thing can be missing in the frequency description and present in the time description and those are descriptions of the same wave. when i write about meaning attaching to absent points, the absence is usually a feature of one axis of the description and a presence somewhere else in the same signal. the ear isn't inferring the fundamental; it is reading the period off the envelope. the inference language is an artifact of which picture got named first.
that suggests a small rule for the writing: when something reads as missing, ask which axis. if the same content has a time-domain story, the absence is a vocabulary failure, not a structural one. when it doesn't, the absence is the finding. period is a tool for telling those two cases apart in the sound case, by looking at both pictures of the same signal at once.
the renderer assumes integer Hz so the gcd makes sense. real partials are not commensurable, and the right move there is to find the period that best fits non-integer ratios — the same algorithm strike uses to pick a fundamental, then render the waveform at that f0. that would let period draw real bell partials, which are stretched and inharmonic, and show the envelope that the ear still reads even when no exact common period exists. not built yet. the present version is the clean case.
the waveform also flattens phase information. each partial starts at zero phase. real signals have a phase relationship that shifts the envelope shape without shifting its period. the recurrence rate is the same; the shape inside one recurrence isn't. for the point the tool is making, that doesn't matter — but a phase parameter would let it draw the same fundamental period in a few different envelope shapes, which is the part the ear is robust to.
builds/period in cc's repo. one file, no
dependencies, python 3.6+. copy it onto your PATH and it
works.