Skip to content

nikooo777/audiometry

Repository files navigation

Audiometer

A browser tool that maps your relative hearing sensitivity from 10 Hz to 25 kHz using pure sine tones and repeated blind threshold tests. Everything runs client-side — no server, no network, no account; your results live only in your browser's localStorage.

Example results: binaural, left, and right threshold curves with a frequency hover tooltip

Warning

Not a medical or diagnostic device. It measures your whole playback chain (DAC + transducer + ears), not your ears in isolation, and has no access to true sound pressure — results are a relative sensitivity map, not clinical dB HL. For best results use wired headphones in a quiet room. If you have hearing concerns, see an audiologist.

What it does

  • Sweeps 10 Hz – 25 kHz (capped to your hardware's Nyquist limit) with pure sine tones.
  • Uses an ascending method of limits with adaptive bracketing and repeated, blind trials to estimate a threshold per frequency, with a standard deviation per point.
  • Tests both ears together (binaural) and then each ear separately (monaural), so you can see interaural asymmetry.
  • Produces a relative threshold curve with confidence bands, censored markers, and an interactive chart — hover any frequency to read every channel's value at once.
  • Saves sessions locally and lets you overlay and compare past runs.
  • Exports results as JSON / CSV / PNG.

Getting started

Requires Bun (a recent Node.js + npm also works).

bun install
bun run dev       # http://localhost:5173
bun run build     # typecheck + production build into dist/
bun run preview   # serve the production build locally

With npm: npm install, npm run dev, npm run build, npm run preview.

The production build in dist/ is fully static and can be hosted on any static file host.

Browser requirements

A modern browser with the Web Audio API (Chrome, Firefox, Safari, Edge). The app requests a 96 kHz AudioContext and falls back gracefully, capping the top test frequency just under the device's Nyquist frequency when 25 kHz isn't reachable. Audio starts only after a click, per browser autoplay policy.

How it works

  1. Intro / environment — disclaimer, a setup checklist, sample-rate detection, an optional setup note (so comparisons can flag mismatched hardware), and a resolution choice (coarse / normal / fine = points per octave).
  2. Calibration — set a comfortable 1 kHz reference level, confirm the sensitive-band ceiling (ISO 226 attenuation applied so those bands aren't played painfully loud), and a reaction-time probe used to correct measured thresholds.
  3. Binaural scan — every frequency, both ears, in a shuffled and blind order. Press Space the moment you hear a tone.
  4. Monaural scan — every frequency on each ear, again shuffled and blind.
  5. Results — the relative threshold curve (binaural / left / right) with ±1 SD bands and censored markers; interaural asymmetry summary; reliability counters; JSON/CSV/PNG export.
  6. History — overlay and compare past sessions (one binaural line per session), or drill into a single session's three channels. Warns when comparing across different hardware/setup notes.

In-progress scans are checkpointed to localStorage after every trial, so you can pause, reload, or resume later without losing position.

Methodology

  • Pure tones from a Web Audio OscillatorNode, with anti-click attack/release envelopes.
  • True L/R isolation via a ChannelMergerNode (no inter-channel bleed), not a stereo panner.
  • ISO 226:2023 equal-loudness weighting (attenuation-only, at a nominal phon level) so perceptually sensitive bands are presented at sane levels — used for the EQ shape only, never as absolute SPL.
  • Ceiling escalation — a frequency you don't hear is retried louder on the next pass; if it's still unheard it's recorded as censored (▲), and if it is caught it gets tested more thoroughly.
  • Blinding & randomization — a materialized, shuffled test queue driven by a seeded PRNG, plus silent catch trials to measure your false-alarm rate and overall reliability.
  • Reaction-time correction and censored-data handling (▲ not heard at ceiling / ▼ heard at floor) so the curve reflects real thresholds rather than button-timing or range limits.

Project structure

src/
  audio/     AudioContext + sample-rate cap, anti-click sine generator with merger-based
             L/R routing, dBFS↔gain helpers, ISO 226 equal-loudness curve.
  engine/    Deterministic log-spaced frequency generator, seedable PRNG, calibration,
             single ascending run, censored-aware aggregation/stats, scan orchestration
             (materialized queue, adaptive bracketing, catch trials, checkpoint/resume).
  storage/   Versioned localStorage schema, quota / private-mode failure handling,
             JSON/CSV/PNG export.
  ui/        Wizard steps, the interactive results chart, history/compare, tone playground.

Tech stack: React 19 + TypeScript 5 (strict) on Vite 6, with no runtime dependencies beyond React.

ISO 226 data

The equal-loudness coefficients come from ISO 226:2023 and are used for the EQ shape only at a nominal phon level — never as absolute sound pressure. The standard's PDF is copyright-protected and is not included in this repository.

License

MIT © Niko Storni

About

A binaural + L + R hearing test

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors