ONEDRUM Field notes

Field notes · 13 Aug 2026

1,234 taps later: why Android drums early

We put a browser rhythm game in front of LinkedIn, logged every tap on the server, and found a platform-shaped hole in our timing model. Here's the data, the diagnosis, and the fix that shipped today.

ACCEPTED AT ±120MS · DASHED: OLD ±90 DESKTOP n=517 · median −7ms −230…−210ms: 0.4% (2 taps) −210…−190ms: 0.4% (2 taps) −190…−170ms: 0.6% (3 taps) −170…−150ms: 1.4% (7 taps) −150…−130ms: 2.5% (13 taps) −130…−110ms: 3.3% (17 taps) −110…−90ms: 2.9% (15 taps) −90…−70ms: 6.2% (32 taps) −70…−50ms: 7.4% (38 taps) −50…−30ms: 9.3% (48 taps) −30…−10ms: 12.6% (65 taps) −10…+10ms: 21.7% (112 taps) +10…+30ms: 11.8% (61 taps) +30…+50ms: 6.6% (34 taps) +50…+70ms: 4.1% (21 taps) +70…+90ms: 2.7% (14 taps) +90…+110ms: 1.7% (9 taps) +110…+130ms: 1.2% (6 taps) +130…+150ms: 1.2% (6 taps) +150…+170ms: 0.6% (3 taps) +170…+190ms: 0.4% (2 taps) +190…+210ms: 0.2% (1 taps) +210…+230ms: 0.4% (2 taps) +230…+250ms: 0.8% (4 taps) median −7ms IPHONE (SAFARI) n=407 · median −1ms −250…−230ms: 0.5% (2 taps) −230…−210ms: 0.2% (1 taps) −210…−190ms: 0.2% (1 taps) −190…−170ms: 1.0% (4 taps) −170…−150ms: 1.5% (6 taps) −150…−130ms: 2.9% (12 taps) −130…−110ms: 2.7% (11 taps) −110…−90ms: 2.9% (12 taps) −90…−70ms: 4.4% (18 taps) −70…−50ms: 5.9% (24 taps) −50…−30ms: 9.6% (39 taps) −30…−10ms: 13.5% (55 taps) −10…+10ms: 11.5% (47 taps) +10…+30ms: 12.5% (51 taps) +30…+50ms: 9.6% (39 taps) +50…+70ms: 8.6% (35 taps) +70…+90ms: 5.9% (24 taps) +90…+110ms: 2.2% (9 taps) +110…+130ms: 2.9% (12 taps) +130…+150ms: 0.5% (2 taps) +150…+170ms: 0.2% (1 taps) +170…+190ms: 0.5% (2 taps) median −1ms ANDROID (CHROME) n=310 · median −51ms −250…−230ms: 1.0% (3 taps) −230…−210ms: 2.6% (8 taps) −210…−190ms: 3.9% (12 taps) −190…−170ms: 4.5% (14 taps) −170…−150ms: 3.2% (10 taps) −150…−130ms: 8.4% (26 taps) −130…−110ms: 8.7% (27 taps) −110…−90ms: 6.1% (19 taps) −90…−70ms: 6.5% (20 taps) −70…−50ms: 5.5% (17 taps) −50…−30ms: 9.4% (29 taps) −30…−10ms: 11.6% (36 taps) −10…+10ms: 10.3% (32 taps) +10…+30ms: 10.0% (31 taps) +30…+50ms: 4.2% (13 taps) +50…+70ms: 1.3% (4 taps) +70…+90ms: 1.0% (3 taps) +90…+110ms: 0.6% (2 taps) +150…+170ms: 0.6% (2 taps) +170…+190ms: 0.3% (1 taps) +210…+230ms: 0.3% (1 taps) median −51ms −200 −100 0 +100 +200 ← early late → post-calibration delta, ms
All 1,234 genuine attempts from production, post-calibration, in 20ms bins (hover a bar for its share). Desktop and iPhone centre on zero; Android sits 51ms early — and almost all of its misses fall left of the window. Shaded: the ±120ms window now live. Dashed: the old ±90ms.

OneDrum is a certified-timing engine: it certifies synchronicity — did you answer a shared beat in time — server-side, against the clip's own timeline, and hands the result to anyone as a signed number. Viking Row is the first experience built on the engine: a call-and-response drum chant where the drum calls on beats one and two and you answer on three. Every answer lands in a database with its timing delta, because the spec made us a promise we intended to keep: start the acceptance window at ±90ms, then tune it from logged deltas, not vibes.

After we shared Viking Row on LinkedIn, real players gave us the dataset: 84 sessions and 146 runs across desktop, iPhone and Android — 1,234 genuine scoring attempts after we excluded warm-up bars, wrong-beat taps and our own test harness.

84sessions
1,234genuine attempts
−51msandroid median delta

What the deltas said

Each player self-calibrates in the first bar — their opening answer measures their device's audio-plus-touch latency, and every later tap is corrected by it. If that works, post-calibration deltas should centre on zero. On two platforms, they do. On one, they don't:

Post-calibration timing of genuine attempts, by platform. Negative = early.
Platform Median delta Accepted at ±90ms Misses early : late
Desktop −7ms 82% 59 : 33
iPhone (Safari) −1ms 82% 49 : 24
Android (Chrome) −51ms 60% 119 : 6

Desktop and iPhone are centred — calibration is doing its job. Android is another story: it missed nearly twice as often, and its misses are not noise. 119 early against 6 late is a signature, not a scatter.

The diagnosis

Our clock is the audible one: we derive clip time from the audio system's own report of what's currently leaving the speaker, so a player who taps with what they hear scores a delta near zero regardless of their hardware's latency. That report is the weak link. On Android Chrome, the reported output latency drifts after the first bar — the calibration offset, correct when it was measured, is stale five bars later. The derived clock falls behind the real sound, and every honest tap gets stamped a few dozen milliseconds early.

Our adaptive-calibration safety net couldn't catch it, for a reason that's obvious in hindsight: it only arms before a player is calibrated. These players calibrated perfectly. Then their device quietly moved the goalposts.

The fix that shipped

The durable fix is continuous drift re-centring in the scoring kernel, and it's on the roadmap. But the data also showed the window itself was tighter than it needed to be: widening ±90ms to ±120ms — exactly a sixteenth note at 120 BPM, a cleaner musical definition of "in sync" — lifts acceptance of genuine attempts from 76.5% to 84.1% overall, and Android from 60% to 71%, while staying tiny against the two seconds between scored answers. A random tap still fails ~88% of the time, and our variance-based bot detection doesn't care about window width at all.

That change is live now. Same game, same certification, fairer to a third of the planet's phones.

Why we're telling you this

Because the engine is the product. Anyone can render a beat in a browser; the hard part is certifying synchronicity across devices whose clocks lie in device-specific ways — and the only way to get that right is to instrument everything and let production data overrule your assumptions. Viking Row is the first experience on the engine, and its players are also its field study: one LinkedIn post bought us 1,234 attempts, and every certified score it issues is a number an operator can verify against the OneDrum API without trusting the device that produced it.

Try Viking Row — the drum calls, you answer: onedrum.io

Method notes: deltas are post-calibration, from the server-side taps log. "Genuine attempts" excludes warm-up-bar answers, taps more than 250ms from any cue (a wrong beat, not a timing miss), and scripted/QA traffic identified by device class. Acceptance percentages are of genuine attempts. · More field notes