The instrument
last keystroke
- interval
- —ms —
- pitch
- —Hz
- dwell
- —ms
- cutoff
- —Hz
Interval sets pitch
log-mapped, then snapped to the same 10 lines · 40–900ms
Dwell sets loudness & brightness
30–250ms → gain 0.35–1.00, cutoff 900–4200Hz
Provenance
How the zero-request claim is enforced
$ node verify.mjs .
verify: OK — no network calls, external resources, or analytics identifiers found in .
That checks the source. This checks the running page, live in your browser right now, by reading its own Performance timeline:
measuring…
verify.mjs scans what ships — index.html plus everything
under src/ — and exits non-zero on any of the three request-issuing
browser APIs, an http(s) resource, a CDN script tag, or a
telemetry-shaped identifier. It runs on every npm test. That is also
why this page carries no webfont: one would be a request, and the check would fail.
It is strict enough to have caught this very paragraph naming one of those APIs
out loud, which is the correct behaviour for a checker whose subject is the page's
own bytes.
What happens to your keystrokes
Two numbers per key — time since the last key, and how long you held this one —
are read with performance.now() in this tab's memory, turned into a
pitch and a tone, and thrown away. Reload and every timing is gone. There is no
server, no storage, and no copy of what you typed anywhere but your own screen.
What this does not claim
- It is an instrument, not a biometric: nothing here identifies who is typing.
- Tuned by ear against one person on one keyboard. No claim it suits everyone.
- Physical keyboards only — on-screen keyboards do not produce comparable timing.
performance.now()inside the event loop is not a real-time clock; under load, timing jitters by a few milliseconds.
Full method, limitations and the mapping's reasoning: README.md.