Welcome to Mankunku

Jazz ear training — call and response. Pick your instrument to get started.

Browser Compatibility

Mankunku relies on modern Web APIs. This page documents compatibility requirements and known limitations.

Required APIs

APIUsed ForChromeFirefoxSafariEdge
Web Audio APIAll audio processing35+25+14.1+79+
getUserMediaMicrophone capture53+36+14.1+79+
AudioWorkletOnset detection66+76+14.1+79+
Permissions.queryMic permission check43+46+16+79+
localStorageSettings, progressAllAllAllAll
CacheStorageSoundFont caching40+41+11.1+79+
requestAnimationFramePitch detection loop10+23+6.1+12+
CSS Custom PropertiesTheming49+31+9.1+15+
ES2022+Async/await, modules89+89+15+89+

Minimum Browser Versions

BrowserMinimum VersionLimiting Factor
Chrome66+AudioWorklet
Firefox76+AudioWorklet
Safari14.1+AudioWorklet, getUserMedia
Edge79+Chromium-based

Not supported: Internet Explorer, Opera Mini, older mobile browsers without AudioWorklet.

Mobile Considerations

iOS Safari

  • AudioContext resume — iOS Safari suspends the AudioContext until a user gesture. Mankunku handles this via Tone.start() called from the first tap.
  • getUserMedia — Requires HTTPS. Works on iOS 14.3+ for Safari.
  • Screen lock — Audio may stop when the screen locks. Users should keep the screen active during practice.
  • Low-latency mode — iOS Safari has higher audio latency than desktop browsers. The latency correction in the scorer absorbs most of this.

Android Chrome

  • AutoPlay policy — Same as desktop Chrome: user gesture required to start AudioContext.
  • getUserMedia — Works reliably on Chrome for Android.
  • Performance — Lower-end devices may struggle with 60fps pitch detection. The requestAnimationFrame loop naturally adapts to device capability.

PWA Support

Mankunku is configured as a Progressive Web App via @vite-pwa/sveltekit:

  • Installable — Can be added to home screen on mobile and desktop
  • Offline-capable — Static assets are cached via service worker
  • Icons — App icons in static/icons/
  • Manifest — Auto-generated by the PWA plugin

Note: Microphone access requires HTTPS in all browsers. Development via localhost is exempt.

Known Limitations

Permissions API

The navigator.permissions.query({ name: 'microphone' }) API:

  • Not supported in all browsers (gracefully falls back to 'prompt')
  • On macOS, may report 'denied' even when the user hasn't been prompted (browser-level permission not yet granted). Mankunku treats 'denied' as 'prompt' conservatively.

AudioWorklet Module Loading

The onset detector loads its worklet via:

const workletUrl = new URL('./onset-worklet.ts', import.meta.url);
await context.audioWorklet.addModule(workletUrl);

This relies on Vite transforming the TypeScript worklet file into a loadable module. In production builds, Vite handles this correctly. In some development configurations with HMR, the worklet URL may need special handling.

SoundFont Loading

First instrument load requires downloading a ~2MB SoundFont file. This is cached via CacheStorage (not localStorage) for subsequent visits. A loading indicator shows during this process.

Pitch Detection Accuracy

  • Polyphonic signals — The McLeod Pitch Method is designed for monophonic instruments. Background noise, multiple instruments, or harmonics from certain embouchures may cause detection errors.
  • Low notes — Notes below ~80Hz require longer analysis windows and may have lower clarity scores.
  • Very high notes — Above ~1200Hz, harmonics and overtones can cause octave errors.

Audio Latency

Total system latency (mic → detection → display) is typically 50–150ms, depending on:

  • AudioContext buffer size (4096 samples ≈ 85ms at 48kHz)
  • requestAnimationFrame interval (~16ms)
  • Browser audio pipeline latency

The scoring system's latency correction absorbs constant delays, so latency primarily affects real-time visual feedback rather than scoring accuracy.

HTTPS Requirement

Microphone access (getUserMedia) requires a secure context:

  • https:// in production
  • http://localhost in development (exempt)
  • http://127.0.0.1 in development (exempt)

Deploy behind HTTPS for production use.