ChessJammer
A chess game, scored. Every musical decision is caused by something on the board — and the app will name the move that caused it. These are the notes for a jury: what the machinery is, and how to check that the claim is true rather than decorative.
01The claim
Plenty of things turn data into sound. The bar ChessJammer sets itself is higher and much easier to fail: a listener who does not play chess should be able to hear what happened, and a listener who does should be able to point at the move that did it.
So the mapping is not a sonification of coordinates. It is an arrangement decision per chess fact, chosen because that is what the fact means. A knight is a horn; when the knight is captured the horn stops for the rest of the game. Nothing re-instantiates it, because the piece is not coming back. That single rule does more work than any pitch mapping: the orchestra thins as the board thins, and an endgame is audibly a smaller ensemble.
The two-minute test. Open the app, choose Classical, press Play and let the Botez game run. Around the middle you will hear parts stop appearing. Those are the captures. Nobody told you that in words — and the move list on the right will confirm it move for move.
02How a move becomes music
A game arrives as PGN, ideally with clock comments. It is then processed once, ahead of playback, and once per ply during it.
PGN → timeline legal moves, captures, checks, castling,
promotions, a per-ply piece census, and the
real think time between moves
→ analysis Stockfish 18 (WASM, shipped locally) scores
each position: evaluation, forced mates,
blunders and their severity
→ arrangement the whole game is planned before a note
sounds — recognised opening, intro length,
section arc, where the climax belongs
→ per ply six signals update, the bar is composed,
and the ply's chess events fire their voices
The number of musical bars a ply occupies is derived from how long the player actually thought, relative to their own median for that game. A long think is a long bar. This is why replaying a real blitz game feels hurried and a classical game breathes: the tempo of the music is the tempo of the thinking, not a setting.
03The six signals
Everything continuous about the music is driven by six numbers, each owned by exactly one place in the code. They are the only channel between the chess and the arrangement.
| Signal | What the chess is | What it controls |
|---|---|---|
| pace | how fast they are moving, relative to their own median think | note density and diminution |
| tension | the geometry of the position — not what recently happened to it | filter opening and dynamic |
| scramble | clock pressure: below a fifth of the starting clock | surface agitation, tremolo |
| danger | a low clock and an unresolved position at once | detune and bite |
| pressW / pressB | each player's own clock, separately | that side's phrases compress |
| adv | the engine's evaluation, smoothed | which side leads the texture |
They are deliberately not independent of the chess and deliberately
independent of each other. tension reads the position, so it stays
high while a loaded position sits still; an event accumulator would have
decayed. scramble reads only the clock, so a game with no clock
record reports zero and is unaffected rather than guessing.
04Pieces as instruments
In the orchestral family each piece type owns a part. The assignment is by register and behaviour, not by material value.
| Piece | Instrument | Why |
|---|---|---|
| Pawns | pizzicato strings (bowed swells in Symphonic) | many, short, and the texture underneath everything |
| Knights | horn | brass speaks with an attack; a knight arrives rather than slides |
| Bishops | clarinet and oboe — one per colour complex | two bishops that never share a square never share a timbre |
| Rooks | low brass | weight along a line |
| Queen | solo violin (piano in Chamber) | the one voice that can go anywhere |
| Kings | organ pedal | always present, rarely moves, holds the bottom |
A capture is scored by what was taken, in four brackets — a pawn gets a triangle and a short note with nothing underneath; a minor piece a damped stroke with a bassoon on the chord; a rook low brass; the queen the full stroke. The losing side's instrument then goes silent permanently.
Chess the music actually reacts to
- Recognised openings set how long the introduction holds — a King's Indian coils for a quarter of the game, a King's Gambit is alight by move three.
- Castling on opposite wings changes the character: both kings are targets and the arrangement stops being symmetrical.
- Tactics each have a figure — fork, absolute and relative pin, skewer, discovered check, double check, battery. A fork holds rather than restating itself; a double check strikes in two voices at once.
- A forced mate floors the tension and starts a clock figure whose rate accelerates as the distance closes.
- Blunders are graded by the engine's severity, not flagged as a binary.
05The nineteen modes
Three families. They are not presets over one engine: the orchestral and film-score families run a different scheduler from the club family.
Classical — four modes
| Mode | BPM | What separates it |
|---|---|---|
| Orchestral | 108–122 | the mapping at its most legible — one piece, one instrument, one-shot per event |
| Symphonic | 88–104 | the orchestra playing a piece rather than a groove: pawns bow long overlapping swells, so the pulse becomes a bed |
| Symphony-Astra | 72–92 | plans a bar at a time, ties notes across bar lines, schedules real rests, no percussion at all |
| Chamber | 96–112 | the smaller room — piano for the queen, no timpani |
Soundtrack — three modes
| Mode | BPM | What separates it |
|---|---|---|
| Underscore | 60–84 | natural minor with one chord held two bars — the mechanism, not a reverb setting. Brass carries the bed with strings on top, the reverse of every other mode |
| Main Title | 88–104 | dorian, and it moves. The theme is on the trumpet; a title cue is not an underscore |
| Cinema | 54–76 | the only mode where a piece's instrument moves with the story: the section arc picks the family — strings, then winds, then brass — and each piece keeps its tier within it, so the rook is the heavy one throughout rather than being a trombone throughout. Carries a pressure line that moves and lands off the chord without ever getting louder, and a harp and celesta that play only when almost nothing else does |
Club — twelve modes
Detroit, Bleep, Dub Techno, Minimal, Melodic, Hardgroove, Acid, Industrial, Hard Techno, Schranz, Dark Techno and Peak Time, 120–165 BPM. Each names its own hats, reverb send, delay and drive — the hats alone distinguish most techno subgenres before anything else happens. Here the pieces are stems: the kick, the bassline, the acid riff, the pad. Losing a piece removes its stem from the arrangement, so the mix thins toward the endgame.
The phrase composer. In the composed modes the music is written in eight-bar sentences — state, move, move, lean open; state, move, move, close. The mover owns the phrase, so the two players' lines are drawn differently: one rounded, one angular, disjoint by construction. When a position repeats, the opening motto returns. When a piece is lost, the part that carried it is remembered once — the fallen instrument's colour and register appear in the next phrase and are then spent.
06Synthesis
Every sound is generated at runtime through the Web Audio API. There are no samples anywhere in the application: 74 voice functions build their own oscillators, noise buffers, filters and envelopes. A triangle is three inharmonic sine partials through a bandpass; a kick is one oscillator swept in frequency with the attack coming from saturation downstream rather than a separate click layer.
Two of those voices are newer than the rest and exist for the gaps rather than the texture: a harp — a plucked string with a long resonance — and a celesta, an inharmonic struck-metal model. Cinema uses them where almost nothing else is playing, which is the one job the twelve orchestral desks could not do.
The instruments are level-matched by measurement, not by ear. An offline render of each voice is A-weighted through a biquad cascade and compared, because A-weighting is where the ear actually is — a bright voice at the same nominal gain is not the same loudness. The same bench measures decay time, which is how a triangle that read as quiet but rang for 1.8 seconds was found and shortened.
Determinism, and why it matters twice
Given the same game and the same seed, ChessJammer produces the same audio, sample for sample, on any machine. That buys two things at once: the offline WAV render calls the same scheduler as live playback, so the exported file is the track rather than a re-performance of it — and two players in a live match stay in sync without streaming any audio, because each end renders the same thing from the same moves.
07The ledger
The failure mode for a system like this is not a bad sound. It is two chess facts quietly driving the same musical parameter, so neither is legible and the arrangement turns to mush. ChessJammer carries an allocation ledger: 74 rows, one per musical sub-parameter, each naming the single signal that owns it and the function that writes it.
It is enforced rather than aspirational. A checker parses the source, matches it against the ledger, and fails if a shared audio node has two owners or if a documented row has drifted from the code. Twenty-six test suites sit behind that, and the assertions are mutation-tested — an assertion that still passes when the behaviour it guards is reverted is deleted and rewritten.
08The music log
The explainability claim is testable, which is the point of making it. Menu → Copy music log — or the copy icon on the panel — exports one entry per ply: the move in algebraic notation, the mover's clock, the chess evidence, what was captured and which instrument that cost, the recognised opening and the tactics, and every signal that moved by more than a threshold — with what that signal controls written next to it.
9. Qxb5 white 0:42 [capture]
queen takes bishop — black loses Bass · light-sq bishop, for good
minor piece (330) → a damped stroke, bassoon on the chord
FORK — the fork figure, which HOLDS rather than restating itself
tension 0.12→0.71 ↑ filter and dynamic · pace 0.36→0.54 ↑ note density
> section ROLL → BUILD (4-bar window; motto opens the next period)
A judge can therefore check the central claim directly rather than taking it on trust: play a passage, notice something, and read what the board did.
09Ways to play
| Mode | What it is |
|---|---|
| Replay | curated famous games with real clock data, or paste any PGN |
| vs Bot | Stockfish at a chosen clock, scored live as you play, with premoves and resign |
| 2-Player | a live match; only the move travels — 27 bytes a ply — because both ends render identically |
| Party | phones join by room code as silent controllers; one screen renders all the audio and streams it over WebRTC, so five phones cannot flam against each other |
| Deck | a DJ rack over the top: stems, filter, rolls, risers, recorded slots |
| Export | offline WAV render of the whole game, and PGN out |
10Stack & footprint
- One HTML file, ~1.1 MB. No framework, no build step, no bundler, no dependencies at runtime.
- Web Audio API for all synthesis;
OfflineAudioContextfor rendering and for the measurement benches. - Stockfish 18 lite (7.3 MB WASM) shipped locally, not called out to a service. GPL text travels with it.
- WebSocket relay for room signalling, WebRTC for party audio.
- No account, no telemetry, no third-party requests in normal play.
- Desktop and mobile; the interface folds its entry points into one control once a game is running so the deck is not pushed off a phone screen.
11What it does not do
Stated plainly, because a jury will find these anyway.
- Cinema is the newest mode and is a first stage, not a finished one. Its orchestration, its pressure line and its harp and celesta are built; the scene director that would give it real silence is designed and not written. Underscore and Main Title are older and steadier. All three are included because the film-score family is the strongest demonstration of the phrase composer, not because any of them is done.
- 2-player is same-machine today. The wire protocol is written and measured — 326-byte handshake, 27-byte move — and party mode already runs over a real relay, but the internet transport is not yet wired to the 2-player button.
- Party mode fails on symmetric NAT. A relay is a different feature with a different bill, and it is not pretended otherwise.
- It is not a chess trainer. The engine is there to hear the game, not to coach it.
12What the architecture implies
Stated as what is already true rather than as a roadmap, because it changes how the rest of this page reads. Nothing in the engine below the chess layer knows it is scoring chess. It consumes a stream of game state — events, a few continuous signals, a clock — and emits a score: no samples, no pre-rendered stems, deterministic from a seed, inside a browser tab, at a latency low enough that the music answers a move rather than following it.
Those are the properties a real-time score for any game needs, and they are not properties a sample-and-crossfade system has. Chess is the demonstration, and a demanding one: it is adversarial, it has a clock, its drama is positional rather than scripted, and a listener who plays can check the result move by move. It is not the limit of the idea.