drwu ยท stem players ยท rebuilt engine

Stem Sync, Fixed

Click solo and mute as much as you want. The stems hold together now.

Reported on Fugazi ยท The Argument  |  15 players rebuilt  |  2026-06-22

The short version, plain

A song player splits a song into separate tracks, the drums, the bass, the guitar, the singing. Before, each track was its own little player with its own stopwatch, and the stopwatches slowly stopped agreeing. On a phone it was worse, because the phone freezes the stopwatch of any track you cannot hear, so a muted track fell behind and showed up late when you turned it back on.

Now the player loads the whole of every track first, then starts all of them on one single clock at the exact same instant. Because they ride the same clock, they can never slide apart. Solo and mute only change how loud a track is, so pressing buttons can do nothing to the timing.

What you saw

the bug, in one breath

Open a player, hit play, and start tapping solo and mute to move between parts. After a while the parts slid apart. The drums sat a hair ahead of the bass, the vocal leaned late, and the longer the song ran the wider the gap grew. Soloing a stem that had been quiet for a minute was where it showed worst.

Why it drifted

six clocks, and a phone that freezes the quiet ones

Each stem played as its own audio element, and every audio element keeps its own clock. Six stems meant six clocks running free. The first repair tried to herd those clocks by nudging their speed, and on a laptop that helped. On a phone it could not win. iOS stops feeding any audio element it judges inaudible, so the moment you mute a stem its clock freezes, and no amount of nudging can move a clock the system has parked. Un-mute it and it is seconds behind. The architecture itself was the problem.

The fix

load once, start on one clock, never drift

decode

Loaded up front

Every stem is fetched and decoded into memory before playback, so nothing has to stream or buffer mid-song.

one clock

Started together

All stems start on a single Web Audio clock at the same instant, which makes them sample-locked. Drift is not corrected, it is impossible.

gain

Clicks are volume

Solo and mute change a gain value. They never start, stop, or move a stem, so clicking cannot reach the timing.

This is the same engine a browser DAW uses. The six stems are not six players chasing each other anymore. They are one locked group of voices on one timeline. A muted stem keeps its exact place because the clock belongs to the audio engine, not to any element the phone can park.

Verified in a real browser

loaded the live Fugazi player and watched it run

DECODEAll 6 stems fetched and decoded, 0 missing. Status read "ready, 6 stems locked to one clock."
CLOCKPressed play, the position ran 1.23 s then 1.94 s over a 0.70 s wait, exactly real time.
SOLO MID-PLAYSoloed a stem while playing. All 6 sources stayed live and the clock kept advancing smoothly, no restart.
CLEANZero console errors. AudioContext running. Duration read straight from the decoded buffer.

Every player, rebuilt

the one-clock engine now rides all fifteen

FugaziThe Argument/fugazi-the-argument A Perfect CircleThirteenth Step & Mer de Noms/apc-stems The Appleseed CastIllumination Ritual/appleseed-stems Beach HouseOnce Twice Melody/beachhouse-stems ShinerBELIEVEYOUME/believeyoume-stems Tame ImpalaCurrents/currents-stems Dream TheaterSix Degrees of Inner Turbulence/dream-theater-stems Hooray For Earthstem mixer/hfe-stems RadioheadIn Rainbows/in-rainbows-stems The Life and TimesTragic Boogie/lifeandtimes-stems The Mars VoltaDe-Loused in the Comatorium/mars-volta-stems RushA Farewell to Kings/rush-stems Smashing PumpkinsSiamese Dream/smashing-pumpkins-stems Tame ImpalaThe Slow Rush/tameimpala-stems Beach HouseOnce Twice Melody (mirror)/beachhouse-otm-stems
๐Ÿ›๏ธ Get the printable