Split demo seed into Styles + Practice; add shuffle/samba/nañigo
Two seed set lists instead of one mixed "Demos": - 🥁 Styles — grooves/feels: four-on-the-floor, swing ride, Purdie half-time shuffle (triplet grid, backbeat on 3, snare ghosts), Samba (2/4, surdo on 2), Nañigo (6/8 bembé bell), 6/8, 7/8, 5/4. - 🎯 Practice — polyrhythms, triplet hats, accent demo, tempo builder, gap trainer. Seed is now versioned + additive: a bumped SEED_VERSION adds any seed list whose title isn't already present, without clobbering or re-adding the user's lists. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
766d5d40ae
commit
8171b37e72
1 changed files with 35 additions and 19 deletions
38
index.html
38
index.html
|
|
@ -1184,19 +1184,29 @@ function applyHashShare() {
|
|||
}
|
||||
|
||||
// Demo set list (each item authored in the share language — also exercises the parser).
|
||||
const DEMOS = [
|
||||
const SEED_SETLISTS = [
|
||||
{ title: "🥁 Styles", description: "Grooves & feels — load one, press Space, and click pads to shape the accents.", items: [
|
||||
["Four-on-the-floor", "t120;kick:4;snare:4=.x.x;hatClosed:4/2"],
|
||||
["Swing ride", "t150;ride:4/2s;kick:4=X..x;snare:4=.x.x"],
|
||||
["Accents (click a pad to cycle)", "t92;kick:4=X..X;snare:4=.X.X;hatClosed:4/2"],
|
||||
// Purdie half-time shuffle: triplet grid, backbeat on 3, snare ghosts (normal) around it
|
||||
["Purdie half-time shuffle", "t92;kick:4/3=X....x...x..;snare:4/3=..xx.xX.xx.x;hatClosed:4/3=X.xX.xX.xX.x"],
|
||||
// Samba in 2/4 (16ths): surdo strong on beat 2, steady ganzá, tamborim teleco-teco
|
||||
["Samba (2/4)", "t104;tomLow:2/4=x...X...;hatClosed:2/4;woodblock:2/4=X.xx.xX."],
|
||||
// Nañigo / 6/8 bembé bell over a 12/8 grid, low drum on the two main pulses
|
||||
["Nañigo (6/8 bembé)", "t130;cowbell:4/3=X.xx.x.xx.x.;kick:4/3=X.....X.....;hatClosed:4/3=..x..x..x..x"],
|
||||
["6/8 groove", "t100;kick:3+3=x..x..;snare:3+3=...x..;hatClosed:3+3/2"],
|
||||
["7/8 (2+2+3)", "t130;kick:2+2+3=x..x..x;hatClosed:2+2+3/2"],
|
||||
["5/4 (3+2)", "t112;kick:3+2=x..x.;snare:3+2=..x..;hatClosed:3+2/2"],
|
||||
] },
|
||||
{ title: "🎯 Practice", description: "Polyrhythms, independence and tempo / gap tools.", items: [
|
||||
["5 over 4 polyrhythm", "t100;kick:4;claves:5~"],
|
||||
["3 over 2 hemiola", "t96;woodblock:2;cowbell:3~"],
|
||||
["2 & 4 & 3 over one bar", "t100;kick:3;cowbell:2~;claves:4~"],
|
||||
["7/8 (2+2+3)", "t130;kick:2+2+3=x..x..x;hatClosed:2+2+3/2"],
|
||||
["6/8 groove", "t100;kick:3+3=x..x..;snare:3+3=...x..;hatClosed:3+3/2"],
|
||||
["5/4 (3+2)", "t112;kick:3+2=x..x.;snare:3+2=..x..;hatClosed:3+2/2"],
|
||||
["Triplet hats", "t100;kick:4;snare:4=.x.x;hatClosed:4/3"],
|
||||
["Accents — cycle the pads", "t92;kick:4=X..X;snare:4=.X.X;hatClosed:4/2"],
|
||||
["Tempo builder 80↑", "t80;woodblock:4;rmp80/4/4"],
|
||||
["Gap trainer (play 2 / rest 2)", "t100;kick:4;hatClosed:4/2;tr2/2"],
|
||||
] },
|
||||
];
|
||||
|
||||
/* =========================================================================
|
||||
|
|
@ -1427,13 +1437,19 @@ window.addEventListener("keydown", (e) => {
|
|||
});
|
||||
|
||||
/* init */
|
||||
// seed the demo set list once (first run only; not re-added if the user deletes it)
|
||||
if (!lsGet(LS.seeded, false)) {
|
||||
if (!setlists.length) {
|
||||
setlists.push({ title: "✨ Demos", description: "Click an item to load it, then press Space — meters, polyrhythms, odd time, subdivisions & practice tools.", items: DEMOS.map(([n, p]) => ({ name: n, ...patchToSetup(p) })) });
|
||||
activeSL = 0; saveSetlists();
|
||||
// Seed the demo set lists. Versioned + additive: a newer SEED_VERSION adds any
|
||||
// seed list whose title isn't already present, without clobbering the user's lists
|
||||
// (and won't re-add one they've deleted at the same version).
|
||||
const SEED_VERSION = 2;
|
||||
if ((lsGet(LS.seeded, 0) | 0) < SEED_VERSION) {
|
||||
for (const s of SEED_SETLISTS) {
|
||||
if (!setlists.some((x) => x.title === s.title)) {
|
||||
setlists.push({ title: s.title, description: s.description, items: s.items.map(([n, p]) => ({ name: n, ...patchToSetup(p) })) });
|
||||
}
|
||||
lsSet(LS.seeded, true);
|
||||
}
|
||||
if (activeSL >= setlists.length) activeSL = Math.max(0, setlists.length - 1);
|
||||
saveSetlists();
|
||||
lsSet(LS.seeded, SEED_VERSION);
|
||||
}
|
||||
// a shared link (#p=… settings / #sl=… set list) sets the state; otherwise default lanes
|
||||
if (!applyHashShare()) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue