Skip to main content

Albert's Tuner (2025)

Chromatic tuner for string instruments with voice-activated chord finder (Catalan/Spanish), 100% in the browser and packaged as an Android app.

Albert's Tuner (2025)

Albert's Tuner (2025)

A chromatic tuner for string instruments with an integrated voice-activated chord finder. Everything runs in the browser: no backend, no API keys, no audio data leaves your device.

Deployed as an installable PWA at afinador.albertsarle.com and also packaged as a native Android app (not published on Google Play yet).

What does it do?

Two things:

  • Tune your instrument: like any tuning app but without ads, registration, or clutter.
  • Find chords by speaking: can't remember a chord? Say it out loud and get the fingering diagram and variations. Much faster than scrolling through chord apps.

🎸 Chromatic Tuner

  • Real-time pitch detection using the YIN algorithm, running in a Web Worker so audio processing doesn't block the UI or animations.
  • Supports guitar (standard and Drop D tunings), bass, and ukulele.
  • Visual precision dial with per-string indicator: tap a string to hear its reference note.
  • Adjustable A4 reference frequency (432–445 Hz).
  • Optional spectrum analyzer and light/dark mode.
  • Success notification (sound + modal) when all strings are in tune.

Tuner in dark mode tuning the F stringPrecision dial tuning the F string

Tuner in dark mode tuning the D stringThe same dial responding to the D string

All strings in tune, dark modeVisual feedback when all strings are in tune

Tuner in light mode tuning C noteSame tuner in light mode

🎤 Chord Finder by Voice

  • Press-and-speak button: say a chord name aloud (e.g., "D minor seven" or "D minor seventh") to see the guitar fingering diagram.
  • Recognizes Catalan and Spanish in the same voice dictionary.
  • Multiple positions per chord (open, barre, etc.) that you can navigate through.
  • Recent chord history, persistent between sessions (localStorage).
  • Requires a browser with SpeechRecognition support (Chrome, Edge, Opera, Samsung Internet, Safari 14.1+/14.5+); unsupported browsers like Firefox show a clear notice instead of failing silently.

B minor seventh chord diagram, dark modeFingering diagram generated by saying "B minor seventh"

Technical Architecture

Pitch Detection: YIN in a Web Worker

The tuner's core is an implementation of the YIN algorithm (autocorrelation with accumulated error correction), processing 4096-sample blocks at 44.1 kHz to estimate the fundamental frequency of sound from the microphone. This computation runs inside a Web Worker (workers/pitchWorker.ts) so that audio analysis, which runs multiple times per second, doesn't compete with the main thread rendering the dial and animations.

Voice → Chord: Custom Linguistic Parser

services/chordParser.ts converts Web Speech API transcription into a structured chord ({root, quality}) without relying on any NLP or external service — it's a pure function, testable without a microphone. The first word must be a valid note (C, D, E, F, G, A, B), which elegantly resolves the ambiguity of certain words like "si" (note vs. affirmation). Quality phrases ("minor seven", "minor seventh", "diminished"...) are matched ordered by word count, longest-first, so "minor seven" is recognized before "minor" leaves "seven" hanging. The same dictionary covers Catalan and Spanish simultaneously.

Music Theory Engine and Fingering Database

services/chordTheory.ts defines 9 basic qualities (major, minor, 7, m7, maj7, dim, aug, sus2, sus4) as interval tables and derives each chord's notes. data/chordFingerings.ts is a static database of 108 combinations (12 roots × 9 qualities), each with one or two positions (open and, when applicable, barre), adapted from @tombatossals/chords-db.

Clean Separation of Concerns

The codebase follows strict separation: services/ contains only pure logic (pitch detection, audio engine, parser, music theory) with no React or DOM dependencies, making it easy to test in isolation; hooks/ (useTuner, useVoiceChord, useModalA11y, useOnline) encapsulate lifecycle and state, reusing a ref pattern to avoid stale closures inside single-registered listeners; components/ just renders.

Settings panel, dark modeSettings: instrument selection, reference frequency, and visual preferences

From PWA to Native Android App

The app is built as a Progressive Web App with vite-plugin-pwa (manifest, icons, and service worker with automatic background updates), installable directly from the browser. On top of that foundation, it's also packaged as a native Android app via a Trusted Web Activity (TWA) generated with Bubblewrap: signed with its own keystore, verified with an assetlinks.json file confirming to the OS that the app and the domain afinador.albertsarle.com belong to the same owner, and accompanied by its own privacy policy page (a Google Play publication requirement).

Quality, Accessibility, and Resilience

  • Tests (Vitest): 5 test files cover pitch detection, audio engine, voice parser, and music theory — all sensitive logic lives in pure functions easy to test without mocking the DOM or microphone.
  • Accessibility: useModalA11y implements focus trapping in modals; the mic button also responds to spacebar for keyboard users.
  • Resilience: retry button when audio access fails, error messages in Catalan and Spanish over DOMException codes, connectivity detection (useOnline) with UI indicators when offline, and a clear message (not silent failure) on browsers without SpeechRecognition support.

Tech Stack

  • React 19 & TypeScript
  • Vite 6
  • Tailwind CSS
  • Web Audio API
  • Web Speech API
  • vite-plugin-pwa
  • Vitest
  • Docker & Nginx
  • TWA / Bubblewrap (Android)

Deployment

Multi-stage Docker image, served with Nginx:

  1. Stage 1: builds the React/Vite app with Node.
  2. Stage 2: copies only the resulting static assets and serves them with Nginx, with cache headers tuned for a SPA and service worker.

Try it yourself: https://afinador.albertsarle.com

Chord fingerings adapted from @tombatossals/chords-db 0.5.1, Copyright (c) 2016 David Rubert, licensed under the MIT License.

Technologies

React 19 & TypeScriptVite 6Tailwind CSSWeb Audio API (YIN pitch detection)Web Speech APIvite-plugin-pwaVitestDocker & NginxTWA (Bubblewrap) for Android

Achievements

  • Real-time pitch detection using the YIN algorithm inside a Web Worker
  • Voice-activated chord finder in Catalan and Spanish (Web Speech API)
  • Custom database of 108 chord fingerings (12 roots × 9 qualities)
  • Packaged as a native Android app via Trusted Web Activity
  • Full test suite (Vitest) for audio, voice, and music theory logic

Key Metrics

108
Chord Fingerings
3
Instruments
432–445 Hz
A4 Reference Range
CA / ES
Voice Languages