Compare commits

..

No commits in common. "3213c6afe4e3fa822a18264643c0c18c5aa83287" and "61c933e44f6bf2303f971891fff37efc5dc53869" have entirely different histories.

2 changed files with 192 additions and 455 deletions

101
README.md
View file

@ -2,8 +2,8 @@
A browser **polymetric groove trainer / metronome** — and the design mockup for a 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 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 its own little metronome with a grouping, subdivision, drum voice and per-beat
pattern with accents. Layering lanes produces polymeter and true ratio polyrhythm. pattern. Layering lanes produces polymeter and true ratio polyrhythm.
**Live:** https://metronome.varasys.io **Live:** https://metronome.varasys.io
@ -18,18 +18,17 @@ the browser may not persist `localStorage` between sessions, so use **Export all
## Features ## Features
- **Meter lanes** — grouping (odd meters), subdivision (incl. swing), a drum/percussion - **Meter lanes** — grouping (odd meters), subdivision, a synthesized drum/percussion voice, perbeat
voice, per**step dynamics** (accent / normal / ghost / mute), mute, live measure counter. on/off pattern (rests), 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 perlane *poly* toggle fits a lane's beats evenly into lane 1's - **Polyrhythm** — a perlane *poly* toggle fits a lane's beats evenly into lane 1's
bar (e.g. 5over4, 3over2). bar (e.g. 5over4, 3over2).
- **Practice** — gap/mute trainer (play N / mute M bars) and a tempo ramp with a - **Practice** — gap/mute trainer (play N / mute M bars) and a tempo ramp with a
start BPM and signed step. start BPM and signed step.
- **Set lists** — named, ordered lists of saved setups; **cue** across lists and commit - **Set lists** — named, ordered lists of saved setups; click an item to load it
on a bar/beat boundary with no audible gap (see **Live performance**); each play is (it switches live if you're already playing), **N** loads the next; each play is
logged for crossday comparison. logged for crossday comparison.
- **Sharing** — copy a link to your current settings or a whole set list. - **Sharing** — copy a link to your current settings or a whole set list (with an
optional QR generated by an external service).
- **Theming** — System / Light / Dark. - **Theming** — System / Light / Dark.
## The share language ## The share language
@ -40,7 +39,7 @@ goes in a share link, and you can handwrite or edit it.
### Patch grammar ### Patch grammar
``` ```
v1 ; t<bpm> [; vol<pct>] [; cd<sec>] [; b<bars>] ; <lane> … [; tr<play>/<mute>] [; rmp<start>/<step>/<every>] v1 ; t<bpm> [; vol<pct>] ; <lane> ; <lane> … [; tr<play>/<mute>] [; rmp<start>/<step>/<every>]
``` ```
| Token | Meaning | Example | | Token | Meaning | Example |
@ -48,8 +47,6 @@ v1 ; t<bpm> [; vol<pct>] [; cd<sec>] [; b<bars>] ; <lane> … [; tr<play>/<mute>
| `v1` | format version (always first) | `v1` | | `v1` | format version (always first) | `v1` |
| `t<bpm>` | tempo | `t120` | | `t<bpm>` | tempo | `t120` |
| `vol<pct>` | master volume 0100 | `vol70` | | `vol<pct>` | master volume 0100 | `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` | | `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` | | `rmp<start>/<step>/<every>` | tempo ramp: start BPM, ±step, every N bars | `rmp80/5/4` |
| `<lane>` | a meter lane (see below) | `kick:4` | | `<lane>` | a meter lane (see below) | `kick:4` |
@ -62,24 +59,20 @@ Tokens are joined with `;`. `tr` and `rmp` are omitted when off.
<sound> : <grouping> [ / <sub> ] [ = <pattern> ] [ ~ ] [ ! ] <sound> : <grouping> [ / <sub> ] [ = <pattern> ] [ ~ ] [ ! ]
``` ```
- **sound** — the acoustic kit: `beep`, `kick`, `snare`, `rim`, `clap`, `hatClosed`, - **sound** — one of:
`hatOpen`, `ride`, `crash`, `tomLow`, `tomMid`, `tomHigh`, `tambourine`, `cowbell`, `beep`, `kick`, `snare`, `rim`, `clap`, `hatClosed`, `hatOpen`, `ride`, `crash`,
`woodblock`, `claves`, `jamblock` (kick / snare / closedhat / crash play embedded `tomLow`, `tomMid`, `tomHigh`, `tambourine`, `cowbell`, `woodblock`, `claves`,
CC0 samples, the rest are synthesized); plus synthesized drum machines — `jamblock` (unknown → `beep`).
`kick808 snare808 clap808 hat808 openHat808 cowbell808 tom808` and
`kick909 snare909 clap909 hat909 ride909 crash909`. Unknown → `beep`.
- **grouping** — beats per bar, optionally grouped for odd meters: `4`, `3`, - **grouping** — beats per bar, optionally grouped for odd meters: `4`, `3`,
`2+2+3`. Groups get a visual divider; accents are perstep (see `=pattern`). `2+2+3`. The first beat of each group is accented.
- **`/sub`** — subdivision: `1` quarter (default), `2` eighth, `3` triplet, - **`/sub`** — subdivision: `1` quarter (default), `2` eighth, `3` triplet,
`4` sixteenth, `6` sextuplet. This also sets how many **pads** each beat splits `4` sixteenth, `6` sextuplet. This also sets how many **pads** each beat splits
into. Append **`s`** for **swing** on even subdivisions — `2s` (swung eighths) or into (a beat becomes `sub` individuallytoggleable steps). Omit for quarter.
`4s` (swung sixteenths) delay the offbeats to a triplet (2:1) feel. Omit for quarter. - **`=pattern`** — per**step** on/off as `x`/`.`, length = beats per bar × `sub`
- **`=pattern`** — per**step dynamics**, one char per pad: **`X`** accent, **`x`** (one char per pad). Omit = all on. e.g. `4=.x.x` is a backbeat on 2 & 4;
normal, **`g`** ghost (soft), **`.`** mute (rest). Length = beats per bar × `sub`. Omit to get the `4/4=x..x..x.x...x...` is a sixteenthgrid pattern. A short pattern whose length
default — the first step of **each beat** accented, the rest normal (click a pad in equals just the beat count is still accepted and expanded across each beat's
the UI to cycle accent → normal → ghost → mute). e.g. `4=.X.X` accents the backbeat (2 & 4); subdivisions (backcompat).
`4/2s` is swung eighths with the default accents. (Legacy `x`/`.` on/off patterns and
short beatcount patterns still parse.)
- **`~`** — polyrhythm: fit this lane's beats evenly into **lane 1's** bar. - **`~`** — polyrhythm: fit this lane's beats evenly into **lane 1's** bar.
- **`!`** — mute the lane. - **`!`** — mute the lane.
@ -88,9 +81,8 @@ Tokens are joined with `;`. `tr` and `rmp` are omitted when off.
| Patch / lane | What it is | | Patch / lane | What it is |
|---|---| |---|---|
| `kick:4` | kick on 4 quarter beats | | `kick:4` | kick on 4 quarter beats |
| `snare:4=.X.X` | accented snare backbeat (2 & 4) | | `snare:4=.x.x` | snare backbeat (2 & 4) |
| `hatClosed:4/2` | eighthnote hihats (downbeat of each beat accented) | | `hatClosed:4/2` | eighthnote hihats |
| `ride:4/2s` | **swung** eighthnote ride |
| `claves:5~` | 5 evenly across lane 1's bar (5over4 if lane 1 is `4`) | | `claves:5~` | 5 evenly across lane 1's bar (5over4 if lane 1 is `4`) |
| `kick:2+2+3=x..x..x` | 7/8, kick on each group start | | `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 | | `cowbell:3+2/2` | 5/4 grouped 3+2, eighth subdivision |
@ -110,7 +102,10 @@ clears the hash so a refresh won't reimport.
In the setlist panel's **⋯** menu: In the setlist panel's **⋯** menu:
- **Share settings link** / **Share setlist link** open a dialog with the link to - **Share settings link** / **Share setlist link** open a dialog with the link to
**Copy** or **Open**. The link encodes everything in the URL — nothing is uploaded. **Copy** or **Open**.
- **QR ↗** opens a thirdparty QR service (api.qrserver.com) with the link in its
URL so you can scan it on a phone. A banner warns you it's external — confirm the
QR decodes to the shown link before trusting it. (No QR is generated locally.)
- **Export all / Import file** back up your set lists and practice log as a JSON - **Export all / Import file** back up your set lists and practice log as a JSON
file (a legacy `presets` field is included for backward compatibility). file (a legacy `presets` field is included for backward compatibility).
@ -120,36 +115,15 @@ In the setlist panel's **⋯** menu:
|-----|--------| |-----|--------|
| `Space` | play / stop (works everywhere except while typing in a text field) | | `Space` | play / stop (works everywhere except while typing in a text field) |
| `T` | tap tempo | | `T` | tap tempo |
| `←` / `→` | tempo ±1 (`Shift` = ±10) | | `↑` / `↓` | tempo ±1 (`Shift` = ±10) |
| `A` | add meter lane | | `A` | add meter lane |
| `↑` / `↓` / `Home` / `End` | move the **cue** cursor (crosses set lists) | | `N` | load next setlist item |
| `PgUp` / `PgDn` | cue the previous / next set list | | `Alt`+`↑` / `Alt`+`↓` | reorder the selected setlist item |
| `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 quickstep) |
| `Alt`+`↑` / `Alt`+`↓` | reorder the cued item |
| `1``9` | enable / silence lane 19 | | `1``9` | enable / silence lane 19 |
| `?` | shortcuts help | | `?` | shortcuts help |
| `Esc` | close the help / share dialog · cancel an armed switch | | `Esc` | close the help / share dialog |
(Arrow / navigation keys are left alone while a slider or dropdown is focused, so they still adjust it.) (Arrow 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` / `PgDn` move a *cue
cursor* (amber outline) through items — across set lists, without loading anything.
**`Enter`** commits the cued item with a **smooth** cutover at the next **bar**;
**`Shift`+`Enter`** is a **rude** cutover at the next **beat** ("wrong thing playing,
fix it now"). `N` / `P` are immediate rude quicksteps. `Esc` cancels an armed switch.
- **Barlength 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
autoadvances 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 ## Versioning
@ -162,6 +136,12 @@ 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). `VERSION`; it then tags the current commit `v<VERSION>` (requires a clean tree).
Push the tag, then deploy. Push the tag, then deploy.
## Deploy
`./deploy.sh` copies `index.html` (versionstamped) into the Caddy
web root and smoketests the live URL. No restart needed (`file_server` picks up
changes immediately).
## Files ## Files
| File | Purpose | | File | Purpose |
@ -184,10 +164,3 @@ later version. See [`LICENSE`](LICENSE) for the full text.
Because the app is served over a network, the AGPL's §13 applies: anyone 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 repo interacting with a hosted instance must be able to get its source. The repo
link in the inapp **?** help satisfies this. link in the inapp **?** help satisfies this.
### Credits
Acoustic drum oneshots are from the **[Versilian Community Sample Library
(VCSL)](https://github.com/sgossner/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).

File diff suppressed because one or more lines are too long