Skip to content
rootnine
Work

Syncronome

In development

A metronome that keeps every device on the same beat within ±10 ms

iOS app · 2026 — Present

Overview

Instead of everyone in a band starting their own metronome, one host sets the BPM, time signature, and setlist, and every member in the room hears the same click. It moves the hardware click-track rig a touring band would use onto phones. For loud rehearsal rooms, the beat also arrives as a full-screen flash.

The core of the design is splitting synchronization into two layers. Realtime messaging propagates state well, but arrival time swings between 50 and 500 ms, so a "start now" signal can never be beat-accurate. State sync (BPM, playing or not, start time) is therefore separated from time sync (an NTP-style offset), and each client computes beat times locally from the two.

Engineering highlights

NTP-style clock synchronization

Server time is sampled five to seven times to derive a per-sample offset, and the three with the shortest round trip are averaged. Half the smallest round trip becomes the uncertainty figure. Drift is re-measured every 30 seconds, with an immediate resync after returning from background.

Look-ahead beat scheduler

A loop wakes every 25 ms and pre-books every beat falling in the next 100 ms into the native audio scheduler, so garbage collection and event-loop jitter cannot shift a beat.

Phase-preserving tempo changes

A BPM-only change is applied at the next beat boundary with the start time recomputed to preserve phase. A song change is scheduled 200 ms out so every client can pre-book beat one.

Per-device audio latency calibration

Bluetooth can drift as much as 200 ms, so there is a −300 to +300 ms offset, estimated automatically by a tap-sync test.

A flash designed around photosensitivity

Measured against WCAG 2.3.1: above three flashes per second it attenuates automatically, brightness halves above 180 BPM, only white is used, and the whole feature is off by default.

Design decisions with reasons attached

A light background kills the flash contrast and disables the feature outright, so the app is dark-only and the choice was removed from settings. Every changing number is set in a monospaced face, and stage-mode button sizes are specified for a one-metre viewing distance.