From ff5bdd964c4917b079b5a730d4f1d0a5598e5fea Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 3 Aug 2026 11:55:17 +0000 Subject: [PATCH] Fix missing choruses/refrains in Singalong and World songs; dedupe Nursery Rhymes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same class of bug as the Folk/Christmas fixes: the pub()/world() helpers loop a single melody, which drops any distinct chorus or refrain. - Molly Malone: added the "Alive, alive-o!" hook, previously missing - Whiskey in the Jar: added the "Musha ring dum-a-doo-dum-a-da / Whack for the daddy-o" chorus, previously missing - Cielito Lindo: added the iconic "Ay, ay, ay, ay, canta y no llores" refrain (arguably the most recognizable part of the song), previously missing Also removed a dead duplicate block in NURSERY_PIECES where twinkle, mary, birthday, chopsticks, lavender, and shortnin were each declared twice with byte-identical content — harmless (the second assignment always won) but pure waste. Verified other Singalong/Spirituals/World songs and left them as-is: their chorus/refrain reuses the same melody as the verse in the real song, so the single-loop structure is already correct. Ragtime pieces are honestly labeled "A section" only in their comments — a known, intentional simplification rather than a bug, since accurately transcribing the additional strains of Joplin's multi-strain piano rags is a materially different and much higher-risk undertaking than a folk-song verse/chorus fix. --- index.html | 138 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 92 insertions(+), 46 deletions(-) diff --git a/index.html b/index.html index 06424c5..e02794a 100644 --- a/index.html +++ b/index.html @@ -3935,16 +3935,67 @@ const SINGALONG_PIECES=(function(){ bg.push({t:t,f:A3/2,d:2.0,i:'timpani',v:0.6});mel.push({t:t,l:4}); return {n:"Drunken Sailor",composer:"Sea Shanty (Trad.)",bpm:140,duration:Math.ceil(t+3),isClassical:true,isSingalong:true,timeSig:[4,4],bg:bg,melody:mel}; })(); - var molly=pub("Molly Malone","Irish (1880s)",100, - [C4,E4,E4,E4,F4,G4,G4,G4,A4,G4,F4,E4,D4,E4,F4,G4,A4,C5,C5,B4,A4,G4,F4,E4,D4,C4,E4,G4,C5,C5,B4,A4,G4,F4,E4,D4,C4], - [0,2,2,2,1,3,3,3,0,3,1,2,1,2,1,3,0,0,0,3,0,3,1,2,1,0,2,3,0,0,3,0,3,1,2,1,0], - [2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,4,2,4,2,2,2,2,2,2,2,4,2,2,4,2,2,2,2,2,2,2,6], - 4,C4); - var whiskey=pub("Whiskey in the Jar","Irish (Trad.)",125, - [G4,G4,A4,B4,B4,A4,G4,E4,D4,E4,G4,G4,A4,B4,D5,B4,A4,G4,E4,D4,E4,G4,A4,B4,A4,G4,E4,D4,E4,G4], - [3,3,0,3,3,0,3,2,1,2,3,3,0,3,1,3,0,3,2,1,2,3,0,3,0,3,2,1,2,3], - [2,2,2,4,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,6], - 5,G4); + // Verse + the DISTINCT repeated "Alive, alive-o!" hook, which was previously missing. + var molly=(function(){ + var bg=[],mel=[],t=0,u=30/100; // u = one eighth-note unit + function seq(theme,lanes,durs,inst,v,rep){ + theme.forEach(function(f,i){ + var d=durs[i]*u; + bg.push({t:t,f:f,d:d*0.85,i:inst,v:v}); + if(rep>1)bg.push({t:t,f:f/2,d:d*0.85,i:'bass',v:v*0.35}); + mel.push({t:t,l:lanes[i],d:d,f:f}); + t+=d; + }); + } + var verseTheme=[C4,E4,E4,E4,F4,G4,G4,G4,A4,G4,F4,E4,D4,E4,F4,G4,A4,C5,C5,B4,A4,G4,F4,E4,D4,C4,E4,G4,C5,C5,B4,A4,G4,F4,E4,D4,C4]; + var verseLanes=[0,2,2,2,1,3,3,3,0,3,1,2,1,2,1,3,0,0,0,3,0,3,1,2,1,0,2,3,0,0,3,0,3,1,2,1,0]; + var verseDurs=[2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,4,2,4,2,2,2,2,2,2,2,4,2,2,4,2,2,2,2,2,2,2,6]; + // "Alive, alive-o! Alive, alive-o! Crying cockles and mussels, alive, alive-o!" + var hookTheme=[C5,C5,B4,A4,G4, C5,C5,B4,A4,G4, F4,E4,D4,E4,F4,G4,A4, G4,F4,E4,D4,C4]; + var hookLanes=[0,0,3,0,3, 0,0,3,0,3, 1,2,1,2,1,3,0, 3,1,2,1,0]; + var hookDurs=[1,1,1,1,4, 1,1,1,1,4, 2,2,2,2,2,2,4, 2,2,2,2,8]; + for(var rep=0;rep<4;rep++){ + var v=0.2+rep*0.08; + var inst=rep===0?'woodwind':rep===1?'strings':'brass'; + seq(verseTheme,verseLanes,verseDurs,inst,v,rep); + seq(hookTheme,hookLanes,hookDurs,inst,v*1.1,rep); + t+=0.4; + } + [C4,C4*5/4,C4*3/2,C4*2].forEach(function(f){bg.push({t:t,f:f,d:2.0,i:'strings',v:0.5});bg.push({t:t,f:f,d:2.0,i:'brass',v:0.4});}); + bg.push({t:t,f:C4/2,d:1.5,i:'timpani',v:0.55});mel.push({t:t,l:4}); + return {n:"Molly Malone",composer:"Irish (1880s)",bpm:100,duration:Math.ceil(t+2.5),isClassical:true,isSingalong:true,timeSig:[4,4],bg:bg,melody:mel}; + })(); + // Verse + the DISTINCT "Musha ring dum-a-doo-dum-a-da / Whack for the daddy-o" + // chorus, which was previously missing entirely. + var whiskey=(function(){ + var bg=[],mel=[],t=0,u=30/125; // u = one eighth-note unit + function seq(theme,lanes,durs,inst,v,rep){ + theme.forEach(function(f,i){ + var d=durs[i]*u; + bg.push({t:t,f:f,d:d*0.85,i:inst,v:v}); + if(rep>1)bg.push({t:t,f:f/2,d:d*0.85,i:'bass',v:v*0.35}); + mel.push({t:t,l:lanes[i],d:d,f:f}); + t+=d; + }); + } + var verseTheme=[G4,G4,A4,B4,B4,A4,G4,E4,D4,E4,G4,G4,A4,B4,D5,B4,A4,G4,E4,D4,E4,G4,A4,B4,A4,G4,E4,D4,E4,G4]; + var verseLanes=[3,3,0,3,3,0,3,2,1,2,3,3,0,3,1,3,0,3,2,1,2,3,0,3,0,3,2,1,2,3]; + var verseDurs=[2,2,2,4,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,6]; + // "Musha ring dum-a-doo-dum-a-da, / Whack for the daddy-o, / Whack for the daddy-o, / There's whiskey in the jar." + var chorusTheme=[G4,G4,A4,B4,B4,A4,G4,E4,D4, D4,E4,G4,A4,B4, D4,E4,G4,A4,B4, D5,B4,A4,G4,E4,D4]; + var chorusLanes=[3,3,0,3,3,0,3,2,1, 1,2,3,0,3, 1,2,3,0,3, 1,3,0,3,2,1]; + var chorusDurs=[1,1,1,1,1,1,1,1,2, 2,1,1,1,4, 2,1,1,1,4, 1,1,1,1,1,8]; + for(var rep=0;rep<5;rep++){ + var v=0.22+rep*0.06; + var inst=rep<2?'woodwind':rep<4?'strings':'brass'; + seq(verseTheme,verseLanes,verseDurs,inst,v,rep); + seq(chorusTheme,chorusLanes,chorusDurs,inst,v*1.1,rep); + t+=0.4; + } + [G4,G4*5/4,G4*3/2,G4*2].forEach(function(f){bg.push({t:t,f:f,d:2.0,i:'strings',v:0.5});bg.push({t:t,f:f,d:2.0,i:'brass',v:0.4});}); + bg.push({t:t,f:G4/2,d:1.5,i:'timpani',v:0.55});mel.push({t:t,l:4}); + return {n:"Whiskey in the Jar",composer:"Irish (Trad.)",bpm:125,duration:Math.ceil(t+2.5),isClassical:true,isSingalong:true,timeSig:[4,4],bg:bg,melody:mel}; + })(); var parting=pub("The Parting Glass","Irish/Scots (Trad.)",80, [E4,G4,A4,B4,A4,G4,E4,D4,E4,G4,A4,B4,D5,B4,A4,G4,E4,G4,A4,B4,A4,G4,E4,D4,E4,G4,A4,B4,D5,B4,A4,G4], [2,3,0,3,0,3,2,1,2,3,0,3,1,3,0,3,2,3,0,3,0,3,2,1,2,3,0,3,1,3,0,3], @@ -4216,11 +4267,37 @@ const WORLD_PIECES=(function(){ [0,1,2,0,0,1,2,0,2,1,3,2,1,3,3,0,3,1,2,0,3,0,3,1,2,0,0,3,0,0,3,0], [2,2,2,2,2,2,2,2,2,2,4,2,2,4,2,2,2,2,2,4,2,2,2,2,2,4,2,2,4,2,2,8], 4,C4); - var cielito=world("Cielito Lindo","Mexican (1882)",120, - [E4,E4,F4,G4,A4,G4,F4,E4,D4,E4,F4,E4,D4,C4,E4,G4,C5,C5,B4,A4,G4,F4,E4,D4,C4,E4,G4,C5], - [2,2,1,3,0,3,1,2,1,2,1,2,1,0,2,3,0,0,3,0,3,1,2,1,0,2,3,0], - [2,2,2,2,4,2,2,2,2,2,2,2,2,6,2,2,4,2,2,2,2,2,2,2,4,2,2,8], - 4,C4); + // Verse + the iconic "Ay, ay, ay, ay, canta y no llores..." refrain, which was + // previously missing entirely (this refrain is the most recognizable part of the song). + var cielito=(function(){ + var bg=[],mel=[],t=0,u=30/120; // u = one eighth-note unit + function seq(theme,lanes,durs,inst,v,rep){ + theme.forEach(function(f,i){ + var d=durs[i]*u; + bg.push({t:t,f:f,d:d*0.85,i:inst,v:v}); + if(rep>1)bg.push({t:t,f:f/2,d:d*0.85,i:'bass',v:v*0.35}); + mel.push({t:t,l:lanes[i],d:d,f:f}); + t+=d; + }); + } + var verseTheme=[E4,E4,F4,G4,A4,G4,F4,E4,D4,E4,F4,E4,D4,C4,E4,G4,C5,C5,B4,A4,G4,F4,E4,D4,C4,E4,G4,C5]; + var verseLanes=[2,2,1,3,0,3,1,2,1,2,1,2,1,0,2,3,0,0,3,0,3,1,2,1,0,2,3,0]; + var verseDurs=[2,2,2,2,4,2,2,2,2,2,2,2,2,6,2,2,4,2,2,2,2,2,2,2,4,2,2,8]; + // "Ay, ay, ay, ay, / canta y no llores, / porque cantando se alegran, / cielito lindo, los corazones." + var refTheme=[G4,F4,E4,D4, C4,D4,E4,F4,G4,F4, F4,G4,F4,E4,D4,C4,D4,E4,F4, F4,G4,F4,E4,D4,C4,D4,C4]; + var refLanes=[3,1,2,1, 0,1,2,1,3,1, 1,3,1,2,1,0,1,2,1, 1,3,1,2,1,0,1,0]; + var refDurs=[2,2,2,4, 1,1,1,1,2,4, 1,1,1,1,1,1,1,1,4, 1,1,1,1,1,1,1,8]; + for(var rep=0;rep<4;rep++){ + var v=0.2+rep*0.08; + var inst=rep<1?'woodwind':rep<3?'strings':'brass'; + seq(verseTheme,verseLanes,verseDurs,inst,v,rep); + seq(refTheme,refLanes,refDurs,inst,v*1.15,rep); + t+=0.4; + } + [C4,C4*5/4,C4*3/2,C4*2].forEach(function(f){bg.push({t:t,f:f,d:2.0,i:'brass',v:0.5});bg.push({t:t,f:f,d:2.0,i:'strings',v:0.4});}); + bg.push({t:t,f:C4/2,d:1.5,i:'timpani',v:0.55});mel.push({t:t,l:4}); + return {n:"Cielito Lindo",composer:"Mexican (1882)",bpm:120,duration:Math.ceil(t+2.5),isClassical:true,bg:bg,melody:mel}; + })(); var waltzing=world("Waltzing Matilda","Australian (1895)",110, [G4,G4,A4,B4,D5,B4,A4,G4,E4,G4,A4,B4,A4,G4,E4,D4,G4,G4,A4,B4,D5,B4,A4,G4,E4,D4,G4], [3,3,0,3,1,3,0,3,2,3,0,3,0,3,2,1,3,3,0,3,1,3,0,3,2,1,3], @@ -4362,37 +4439,6 @@ const NURSERY_PIECES=(function(){ [0,0,3,3,0,0,0,3,1,1,2,2,1,1,0,3,3,3,1,1,1,2,2,2,1,1,1,0], [2,2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,6], 3,C4); - // ── Classics (from Prime, simple versions) ── - var twinkle=rhyme("Twinkle Twinkle Little Star","Traditional (1760s)",75, - [C4,C4,G4,G4,A4,A4,G4,F4,F4,E4,E4,D4,D4,C4,G4,G4,F4,F4,E4,E4,D4,C4,C4,G4,G4,A4,A4,G4,F4,F4,E4,E4,D4,D4,C4], - [0,0,3,3,0,0,3,1,1,2,2,1,1,0,3,3,1,1,2,2,1,0,0,3,3,0,0,3,1,1,2,2,1,1,0], - [2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,2,2,2,6], - 3,C4); - var mary=rhyme("Mary Had a Little Lamb","S.J. Hale (1830)",80, - [E4,D4,C4,D4,E4,E4,E4,D4,D4,D4,E4,G4,G4,E4,D4,C4,D4,E4,E4,E4,D4,D4,E4,D4,C4], - [2,1,0,1,2,2,2,1,1,1,2,3,3,2,1,0,1,2,2,2,1,1,2,1,0], - [2,2,2,2,2,2,4,2,2,4,2,2,4,2,2,2,2,2,2,2,2,2,2,2,6], - 3,C4); - var birthday=rhyme("Happy Birthday","P.S. Hill (1893)",75, - [C4,C4,D4,C4,F4,E4,C4,C4,D4,C4,G4,F4,C4,C4,C5,A4,F4,E4,D4,Bb4,Bb4,A4,F4,G4,F4], - [0,0,1,0,1,2,0,0,1,0,3,1,0,0,0,0,1,2,1,2,2,0,1,3,1], - [1,1,2,2,2,4,1,1,2,2,2,4,1,1,2,2,2,2,4,1,1,2,2,2,6], - 3,C4); - var chopsticks=rhyme("Chopsticks","Euphemia Allen (1877)",95, - [F4,G4,F4,G4,F4,G4,E4,G4,E4,G4,E4,G4,D4,F4,D4,F4,C4,E4,C4,E4,F4,G4,F4,G4,E4,G4,E4,G4,D4,F4,D4,F4,C4,E4,C4,E4], - [1,3,1,3,1,3,2,3,2,3,2,3,1,1,1,1,0,2,0,2,1,3,1,3,2,3,2,3,1,1,1,1,0,2,0,2], - [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,8], - 3,C4); - var lavender=rhyme("Lavender's Blue","English Traditional (1670s)",80, - [E4,E4,D4,E4,F4,G4,G4,A4,G4,F4,F4,E4,D4,E4,E4,E4,D4,E4,F4,G4,G4,A4,G4,F4,E4], - [2,2,1,2,1,3,3,0,3,1,1,2,1,2,2,2,1,2,1,3,3,0,3,1,2], - [2,2,2,2,2,2,2,2,2,4,2,2,2,4,2,2,2,2,2,2,2,2,2,2,6], - 3,C4); - var shortnin=rhyme("Shortnin' Bread","Traditional (1900s)",95, - [E5,E5,D5,C5,D5,C5,A4,G4,A4,G4,A4,G4,E5,E5,D5,C5,D5,C5,A4,G4,A4,G4,C5], - [2,2,1,0,1,0,0,3,0,3,0,3,2,2,1,0,1,0,0,3,0,3,0], - [2,2,2,2,2,2,4,2,2,2,2,4,2,2,2,2,2,2,4,2,2,2,8], - 3,C4); return [baa,london,macdonald,row,mice,spider,weasel,hotcross,jack,humpty,twinkle,mary,birthday,chopsticks,lavender,shortnin]; })();