| deploy.sh | ||
| index.html | ||
| LICENSE | ||
| README.md | ||
| release.sh | ||
| VERSION | ||
Stackable Metronome
A browser polymetric groove trainer / metronome — and the design mockup for a Raspberry Pi Pico hardware build. Stack as many "meter lanes" as you like; each is its own little metronome with a grouping, subdivision, drum voice and a per-step pattern with accents. Layering lanes produces polymeter and true ratio polyrhythm.
Live: https://metronome.varasys.io · Source: https://codeberg.org/VARASYS/metronome
It's a single, self‑contained index.html — zero dependencies: no framework,
no build step, no bundled or CDN libraries, and nothing fetched at runtime. State
(set lists, the practice log, theme and UI preferences) lives in localStorage.
Because nothing loads from the network, you can save the page (Ctrl/⌘+S) and
open it straight from disk to run fully offline. One catch from a local file://:
the browser may not persist localStorage between sessions, so use Export all
(set‑list ⋯ menu) to back up your work.
Features
- Meter lanes — grouping (odd meters), subdivision (incl. swing), a drum/percussion voice, per‑step dynamics (accent / normal / ghost / mute), mute, live measure counter.
- Sounds — a sampled acoustic kit plus synthesized 808 / 909 and electronic voices; click each pad to set its dynamics; pick a swing subdivision for a triplet feel.
- Polyrhythm — a per‑lane poly toggle fits a lane's beats evenly into lane 1's bar (e.g. 5‑over‑4, 3‑over‑2).
- Practice — gap/mute trainer (play N / mute M bars) and a tempo ramp with a start BPM and signed step.
- Set lists — named, ordered lists of saved setups; cue across lists and commit on a bar/beat boundary with no audible gap (see Live performance); each play is logged for cross‑day comparison.
- Sharing — copy a link to your current settings or a whole set list.
- Theming — System / Light / Dark.
The share language
A compact, human‑readable text encodes a full configuration (a patch). It's what goes in a share link, and you can hand‑write or edit it.
Patch grammar
v1 ; t<bpm> [; vol<pct>] [; cd<sec>] [; b<bars>] ; <lane> … [; tr<play>/<mute>] [; rmp<start>/<step>/<every>]
| Token | Meaning | Example |
|---|---|---|
v1 |
format version (always first) | v1 |
t<bpm> |
tempo | t120 |
vol<pct> |
master volume 0–100 | vol70 |
cd<sec> |
time countdown, seconds (auto-advance with Continue) | cd60 |
b<bars> |
segment length in bars (auto-advance with Continue) | b16 |
tr<play>/<mute> |
gap trainer: play N bars, mute M | tr2/2 |
rmp<start>/<step>/<every> |
tempo ramp: start BPM, ±step, every N bars | rmp80/5/4 |
<lane> |
a meter lane (see below) | kick:4 |
Tokens are joined with ;. tr and rmp are omitted when off.
Lane grammar
<sound> : <grouping> [ / <sub> ] [ = <pattern> ] [ ~ ] [ ! ]
- sound — the acoustic kit:
beep,kick,snare,rim,clap,hatClosed,hatOpen,ride,crash,tomLow,tomMid,tomHigh,tambourine,cowbell,woodblock,claves,jamblock(kick, snare, closed‑hat, crash, toms, tambourine, cowbell, woodblock and claves play embedded CC0 samples;beep,clap,rim,hatOpenandridestay synthesized — VCSL has no clean source for those); plus synthesized drum machines —kick808 snare808 clap808 hat808 openHat808 cowbell808 tom808andkick909 snare909 clap909 hat909 ride909 crash909. Unknown →beep. - grouping — beats per bar, optionally grouped for odd meters:
4,3,2+2+3. Groups get a visual divider; accents are per‑step (see=pattern). /sub— subdivision:1quarter (default),2eighth,3triplet,4sixteenth,6sextuplet. This also sets how many pads each beat splits into. Appendsfor swing on even subdivisions —2s(swung eighths) or4s(swung sixteenths) delay the off‑beats to a triplet (2:1) feel. Omit for quarter.=pattern— per‑step dynamics, one char per pad:Xaccent,xnormal,gghost (soft),.mute (rest). Length = beats per bar ×sub. Omit to get the default — the first step of each beat accented, the rest normal (click a pad in the UI to cycle accent → normal → ghost → mute). e.g.4=.X.Xaccents the backbeat (2 & 4);4/2sis swung eighths with the default accents. (Legacyx/.on/off patterns and short beat‑count patterns still parse.)~— polyrhythm: fit this lane's beats evenly into lane 1's bar.!— mute the lane.
Examples
| Patch / lane | What it is |
|---|---|
kick:4 |
kick on 4 quarter beats |
snare:4=.X.X |
accented snare backbeat (2 & 4) |
hatClosed:4/2 |
eighth‑note hi‑hats (downbeat of each beat accented) |
ride:4/2s |
swung eighth‑note ride |
claves:5~ |
5 evenly across lane 1's bar (5‑over‑4 if lane 1 is 4) |
kick:2+2+3=x..x..x |
7/8, kick on each group start |
cowbell:3+2/2 |
5/4 grouped 3+2, eighth subdivision |
Full: v1;t120;kick:4;snare:4=.x.x;hatClosed:4/2;tr2/2 |
backbeat groove with gap trainer |
In URLs
- Settings:
…/#p=<patch>— readable, e.g.…/#p=v1;t120;kick:4;claves:5~ - Set list:
…/#sl=<base64url>— a JSON{title, description, items[]}where each item's config is a patch string. Used because titles/notes are free text.
Opening such a link applies the settings (or imports the set list) on load, then clears the hash so a refresh won't re‑import.
Sharing
In the set‑list panel's ⋯ menu:
- Share settings link / Share set‑list link open a dialog with the link to Copy or Open. The link encodes everything in the URL — nothing is uploaded.
- Export all / Import file back up your set lists and practice log as a JSON
file (a legacy
presetsfield is included for backward compatibility).
Keyboard shortcuts
| Key | Action |
|---|---|
Space |
play / stop (works everywhere except while typing in a text field) |
T |
tap tempo |
← / → |
tempo ±1 (Shift = ±10) |
A |
add meter lane |
↑ / ↓ / Home / End |
move the cue cursor (crosses set lists) |
PgUp / PgDn |
cue the previous / next set list |
Enter |
commit the cued item — switches on the next bar (smooth) |
Shift+Enter |
commit now — switches on the next beat (rude) |
N / P |
load next / previous immediately (rude quick‑step) |
Alt+↑ / Alt+↓ |
reorder the cued item |
1–9 |
enable / silence lane 1–9 |
? |
shortcuts help |
Esc |
close the help / share dialog · cancel an armed switch |
(Arrow / navigation keys are left alone while a slider or dropdown is focused, so they still adjust it.)
Live performance
The set list is performance-ready: you can line up where you're going next without disturbing what's playing, then commit on a musical boundary — no audible gap.
- Cue, then commit. The arrows /
Home/End/PgUp/PgDnmove a cue cursor (amber outline) through items — across set lists, without loading anything.Entercommits the cued item with a smooth cutover at the next bar;Shift+Enteris a rude cutover at the next beat ("wrong thing playing, fix it now").N/Pare immediate rude quick‑steps.Esccancels an armed switch. - Bar‑length segments. Give an item a bar count (Timers box, or the
b<n>patch token) and a bar countdown (▦) shows bars remaining. With Continue on, it auto‑advances to the next item at the bar boundary — so a song is just a set list of segments (each with its own tempo, ramp and bar length) that hand off seamlessly. - All transitions — manual or auto, beat or bar — keep the clock continuous; the loaded item can even live in a set list you're not currently viewing (the player names it).
Versioning
VERSION holds the formal version. deploy.sh stamps the served page:
- Formal — a clean commit tagged
v<VERSION>→X.Y.Z. - Dev — anything else →
X.Y.Z-dev.<utc-timestamp>.<short-sha>[.dirty].
Cut a release with ./release.sh [X.Y.Z] — the optional arg bumps & commits
VERSION; it then tags the current commit v<VERSION> (requires a clean tree).
Push the tag, then deploy.
Files
| File | Purpose |
|---|---|
index.html |
the whole app |
deploy.sh |
publish to the Caddy web root |
release.sh |
tag a formal version |
VERSION |
formal version string |
LICENSE |
GNU AGPL v3 license text |
License
Copyright (C) 2026 Varasys.
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version. See LICENSE for the full text.
Because the app is served over a network, the AGPL's §13 applies: anyone interacting with a hosted instance must be able to get its source — the public repository is https://codeberg.org/VARASYS/metronome (also linked from the in‑app ? help).
Credits
Acoustic drum one‑shots are from the Versilian Community Sample Library (VCSL), released under CC0 (public domain) — trimmed and downsampled, embedded inline. The 808/909 voices and the electronic/percussion sounds are synthesized in Web Audio (no samples).