Skip to content

How it works

wiki-sync edited this page Aug 19, 2026 · 1 revision

How it works

Pitch

AudioWorklet (js/pitch-worklet.js). The main thread never runs NSDF.

  1. High-pass ~52 Hz, low-pass ~5 kHz (F2 has to survive the low-pass).
  2. 4096-sample window, pair-averaged to 2048, 55–1350 Hz.
  3. McLeod NSDF with parabolic interpolation on the peak.
  4. Harmonic product spectrum snaps a clean octave. It does not veto the frame (that made singing unusable).
  5. Octave hysteresis so the displayed note does not flip every frame.
  6. Hold ~420 ms within ±2.4 semitones to auto-save, or tap Save this note. Clarity gate 0.68.

No CREPE / FCPE / ONNX. A neural F0 model is the research SOTA; it is the wrong fit for a CSP-locked GitHub Pages page with no network after first load.

Tessitura and range

  • Range = min and max of saved MIDI notes, not the live needle.
  • Tessitura = time-weighted median of those holds.
  • Stability = MAD of the holds, in semitones.

Score (semitone distances to each Fach band):

score = 1.3*|rangeLow − f.low|
      + 0.9*|rangeHigh − f.high|
      + 1.1*|tessitura − mid(f)|

Closest type wins. If range and tessitura disagree, the copy says so and follows tessitura. Runners-up are distances plus a relative softmax — not a calibrated probability.

Formants and passaggio

On the same hop, LPC (order 14) estimates F1/F2 and a spectral centroid. A climb of ≥ 8 semitones with a centroid (or H1−H2) jump is the estimated passaggio. Those features tint the score. Vowel still outweighs Fach.

Profile

Name, gender, and age are required before the mic. Gender defaults the type filter (male → lower, female → upper). Age changes the explanation (a changing voice is not a finished Fach). Nothing is uploaded.

Clone this wiki locally