The harmonium is everywhere in Indian music — kirtan, bhajan, ghazal, film songs, a
hundred years of Hindustani vocal training. It is also an awkward instrument to own.
A decent one costs a few hundred dollars, weighs as much as a carry-on suitcase, and
goes out of tune if you look at it wrong.
So I built one that runs in a browser tab. Web Harmonium
is a free, sample-based harmonium you can play with your computer keyboard, a mouse,
a touchscreen, or a MIDI controller. This post is about the parts that turned out to
be harder than expected — and they were almost never the parts I expected.
Why sampling, not synthesis
A harmonium makes sound by pushing air across free metal reeds. That is a genuinely
messy physical process: the reed's attack has a breathy transient, the pitch bends
slightly as air pressure stabilises, and two reeds voiced to the same note are never
in perfect agreement. Modelling that from oscillators gets you something that sounds
like an accordion impression of a harmonium.
Sampling sidesteps the whole problem. I used recordings from Yale's Euterpea Studio,
which are released CC0, so there is no licensing footgun for a free tool.
The catch with sampling is storage. One sample per key across three octaves is a lot
of audio to ship to someone on a phone connection. The standard trick is to sample
sparsely and interpolate: record nine points across the range, then pitch-shift the
nearest neighbour to fill the gaps.
// Nearest sampled note wins; playbackRate does the pitch shift.
const semitonesFrom = (from, to) => to - from;
function play(midiNote) {
const nearest = pickNearestSample(midiNote);
const src = ctx.createBufferSource();
src.buffer = buffers[nearest];
src.playbackRate.value = Math.pow(2, semitonesFrom(nearest, midiNote) / 12);
src.connect(gain).connect(ctx.destination);
src.start();
}
Two semitones of shift in either direction is about the limit before the timbre
starts sounding obviously wrong — pitch up too far and the reed develops a chipmunk
quality, pitch down and it goes slack and hollow. Nine sample points across three
octaves keeps every note within that budget.
The detail nobody notices until it is missing
A real harmonium has multiple reed banks. Play a single note and you are usually
hearing two or three reeds sounding together, tuned very slightly apart. That tiny
disagreement is what makes the instrument sound alive rather than like a sine wave
with a costume on.
Layering the same sample twice and detuning one copy by a few cents reproduces most
of it:
const voices = [0, +4, -4]; // cents
voices.forEach(cents => {
const src = ctx.createBufferSource();
src.buffer = buffer;
src.detune.value = cents;
src.connect(voiceGain);
src.start();
});
Four cents sounds like nothing written down. Toggle it off and the instrument
immediately sounds cheap.
The bellows problem
This is the one I underestimated badly.
On a physical harmonium your left hand pumps the bellows continuously while your
right hand plays. Volume is not a setting — it is a live, continuous gesture, and it
is half of what makes phrasing expressive. A slider labelled "Volume" throws that
away entirely.
The compromise: a draggable bellows handle that maps drag velocity to gain, so
pumping the mouse or a finger actually produces the swell you would get from pumping
air. Notes decay when you stop, the way a real one does when the bellows empty.
The thing that makes it usable rather than a novelty is a sustain key. Holding the
space bar keeps notes ringing after you let go of the keyboard, which frees your
other hand for the bellows. It is not how the physical instrument works — but a
computer keyboard is not a physical instrument, and pretending otherwise makes the
tool worse.
Ragas, and why the keyboard dims
Indian classical music is built on ragas, and a raga is not a scale — it is closer to
a grammar. It specifies which notes belong, but also how you approach them, which
ones you can rest on, and which direction you can move through them.
A web app is not going to teach that. What it can do is stop you playing notes that
are flatly outside the raga. Pick one and the out-of-scale keys dim; the remaining
keys are the ones that belong. For a beginner working through
Raga Yaman, that constraint is the single
most useful thing the software does. Twelve ragas ship as presets, from Bilawal
(which maps neatly onto a Western major scale) through to Marwa and Todi, which
do not map onto anything comfortable at all.
There is also a drone. Indian music is not played against silence — there is a
tanpura or a sustained reed holding Sa and Pa underneath everything. Playing without
one feels wrong in a way that is difficult to articulate until you switch it on.
Sargam, or: your users may not read your notation
Western staff notation is not what most harmonium students use. They use
sargam — Sa Re Ga Ma Pa Dha Ni — which is
movable-do and maps onto the instrument differently depending on where you place Sa.
Shipping only C-D-E-F-G labels would have made the tool useless to a large part of
the audience it is actually for. The labels are a toggle, and the drone root is
adjustable across all twelve pitches so Sa lands wherever the singer needs it.
If you are building anything for a non-Western musical tradition, treat notation as a
localisation problem, not a display preference.
MIDI, recording, and the boring wins
Three things that took an afternoon each and were worth more than a week of polish
elsewhere:
MIDI input. navigator.requestMIDIAccess() is a small API and it works. Plug in
a keyboard, get velocity sensitivity, and the browser tab stops feeling like a toy.
Chrome, Edge and Opera support it; Firefox and Safari do not, so it degrades to the
on-screen keyboard.
Recording. MediaRecorder pointed at a MediaStreamDestination gives you a
downloadable WebM with about fifteen lines of code. People record two-minute practice
takes and send them to their teacher.
Shareable links. All the settings — raga, drone, root, notation — serialise into
the URL fragment. A teacher can send a student a link that opens with everything
already configured. Zero backend, and it is the feature that gets used most.
Install-free is the whole point
It is a PWA, so "Add to Home Screen" gives you an offline-capable app without an app
store, a download, or an account. For a practice tool that someone might use for ten
minutes before a class, every one of those steps is a place to lose them.
If you want to poke at it, it is free and there is nothing to sign up for:
web-harmonium.app.
Built with the Web Audio API and Tone.js. Samples from Yale's Euterpea Studio (CC0).
Top comments (0)