From 4e93a628e20fe259fcc4c5a75bc5f372228f1e16 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 02:30:30 +0000 Subject: [PATCH 01/22] Rewrite 10 classical pieces from template to conductor-style Replace generic tp() template implementations with musically accurate, section-by-section conductor-style arrangements for: - William Tell Overture (Gallop): trumpet fanfare + galloping theme - Bolero: snare drum rhythm + crescendo through 7 instrument statements - Barber of Seville Overture: pizzicato opening + Rossini crescendo - Sabre Dance: frantic D-D-D-Eb ostinato + contrasting lyrical middle - Sorcerer's Apprentice: creeping bassoon theme + magical march buildup - Morning Mood: gentle flute sunrise melody building to full orchestra - Flight of the Bumblebee: rapid chromatic scales up and down - Habanera (Carmen): descending chromatic melody + habanera bass rhythm - Spring (Four Seasons): joyful ritornello + birdsong trills - Ode to Joy: theme builds from solo cello to full orchestra + choir Each piece now has proper harmonic beds, section-by-section structure, instrument layering that builds over time, and accurate melody notes. https://claude.ai/code/session_016nhMjrAqwWXKKgBm6EQuX1 --- index.html | 1202 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 1152 insertions(+), 50 deletions(-) diff --git a/index.html b/index.html index f13de3a..7c47db5 100644 --- a/index.html +++ b/index.html @@ -1542,46 +1542,683 @@ const CLASSICAL_PIECES=(function(){ })(); // ── William Tell Overture (Gallop) ── - var tell=tp("William Tell Overture (Gallop)","Rossini",152, - [G4,G4,B4,G4,G4,B4,D5,D5,B4,G4,E4,G4,B4,D5,B4,G4,E4,D4,E4,G4], - [0,0,3,0,0,3,1,1,3,0,2,0,3,1,3,0,2,1,2,0], - [{d:0.28,v:0.22,i:'strings'},{d:0.25,v:0.28,i:'strings'},{d:0.22,v:0.35,i:'strings'},{d:0.20,v:0.42,i:'strings'},{d:0.18,v:0.48,i:'brass'},{d:0.16,v:0.54,i:'brass'},{d:0.14,v:0.58,i:'brass'},{d:0.12,v:0.62,i:'brass'}], - [G4,B4,D5,G5]); + // The famous finale gallop in G major, ~70s + // Trumpet fanfare → galloping theme → accelerating coda + var tell=(function(){ + var bg=[],mel=[],t=0,q=60/152; + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.4});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.4});} + function tutti(t,f,d,v){str(t,f,d,v);brs(t,f,d,(v||0.4)*0.7);bg.push({t:t,f:f/2,d:d,i:'bass',v:(v||0.4)*0.4});} + + // Harmonic bed + var harm=[ + [0,8,[G3,B3,D4],0.12],[8,20,[G3,B3,D4],0.15],[20,32,[G3,B3,D4],0.18], + [32,44,[C4,E4,G4],0.16],[44,56,[G3,B3,D4],0.2],[56,72,[G3,B3,D4],0.22] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht0)brs(t,n[0],n[1]*0.9,vl*0.5); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + + // === SECTION 4 (32-44s): Theme returns with full orchestra === + for(var rep2=0;rep2<3;rep2++){ + var v2=0.45+rep2*0.08; + gallop1.forEach(function(n){ + tutti(t,n[0],n[1]*0.85,v2); + if(rep2>0)bg.push({t:t,f:n[0],d:n[1]*0.85,i:'brass',v:v2*0.5}); + if(rep2>1&&n[2]===0)bg.push({t:t,f:G3,d:0.15,i:'timpani',v:v2*0.5}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q*0.5; + } + + // === SECTION 5 (44-56s): Ascending fanfare + gallop intensifies === + // Brass fanfare ascending + var fanfare=[[G4,0],[B4,3],[D5,1],[G5,3],[D5,1],[B4,3],[G4,0]]; + for(var ff=0;ff<2;ff++){ + fanfare.forEach(function(n){ + brs(t,n[0],q*0.85,0.55);str(t,n[0],q*0.85,0.45); + mel.push({t:t,l:n[1]});t+=q; + }); + bg.push({t:t,f:G3,d:0.4,i:'timpani',v:0.5});mel.push({t:t,l:4});t+=q*1.5; + } + // Double-time gallop + var dTrip=trip*0.8; + for(var dg=0;dg<4;dg++){ + var vd=0.5+dg*0.04; + gallop1.slice(0,10).forEach(function(n){ + tutti(t,n[0],n[1]*0.7,vd);mel.push({t:t,l:n[2]});t+=n[1]*0.8; + }); + t+=q*0.3; + } + + // === SECTION 6 (56-68s): Final gallop — full speed === + for(var fg=0;fg<4;fg++){ + var vf=0.55+fg*0.05; + gallop1.forEach(function(n){ + tutti(t,n[0],n[1]*0.7,vf); + brs(t,n[0],n[1]*0.7,vf*0.6); + if(fg>1)bg.push({t:t,f:n[0],d:n[1]*0.7,i:'choir',v:vf*0.25}); + mel.push({t:t,l:n[2]});t+=n[1]*0.75; + }); + bg.push({t:t,f:G3,d:0.3,i:'timpani',v:vf*0.7});mel.push({t:t,l:4});t+=q*0.5; + } + + // === FINALE: Big G major chords === + for(var c=0;c<6;c++){ + [G3,B3,D4,G4,B4,D5].forEach(function(f){brs(t,f,0.4,0.65);str(t,f,0.4,0.55);}); + bg.push({t:t,f:G3/2,d:0.4,i:'timpani',v:0.65});mel.push({t:t,l:4});t+=0.5; + } + [G3,B3,D4,G4,B4,D5].forEach(function(f){brs(t,f,3.0,0.7);str(t,f,3.0,0.6);}); + bg.push({t:t,f:G3/2,d:2.5,i:'timpani',v:0.7});mel.push({t:t,l:4}); + + return {n:"William Tell Overture (Gallop)",composer:"Rossini",bpm:152,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; + })(); // ── Bolero ── - var bolero=tp("Bolero","Ravel",72, - [C4,D4,E4,F4,E4,D4,C4,C4,D4,E4,F4,G4,F4,E4,D4,C4,E4,G4,E4,C4], - [0,1,2,3,2,1,0,0,1,2,3,0,3,2,1,0,2,0,2,0], - [{d:0.38,v:0.15,i:'woodwind'},{d:0.36,v:0.2,i:'woodwind'},{d:0.34,v:0.28,i:'strings'},{d:0.32,v:0.35,i:'strings'},{d:0.30,v:0.42,i:'strings'},{d:0.28,v:0.5,i:'brass'},{d:0.26,v:0.58,i:'brass'}], - [C4,E4,G4,C5]); + // Ravel's Bolero in C major, ~90s + // Built around an endlessly repeating snare drum rhythm that crescendos + // The melody is stated by different instruments, each time louder + var bolero=(function(){ + var bg=[],mel=[],t=0,q=60/72; + + // The iconic Bolero snare rhythm: 3+3+3+3+2+2 pattern per bar + // ta-ta-ta ta-ta-ta ta-ta-ta ta-ta-ta ta-ta ta-ta + function snareBar(time,v){ + var s=q/3; + for(var g=0;g<4;g++){ + for(var n=0;n<3;n++){bg.push({t:time+g*q+n*s,f:300,d:0.05,i:'woodwind',v:v*0.3});} + } + // The two duplets at end + bg.push({t:time+q*4,f:300,d:0.05,i:'woodwind',v:v*0.35}); + bg.push({t:time+q*4+q/2,f:300,d:0.05,i:'woodwind',v:v*0.35}); + bg.push({t:time+q*5,f:300,d:0.05,i:'woodwind',v:v*0.35}); + bg.push({t:time+q*5+q/2,f:300,d:0.05,i:'woodwind',v:v*0.35}); + } + + // Bolero Theme A (C major): C-D-E-F-E-D-E-C | E-C-D-C-B3-C-D-E-F-E-D-C + var themeA=[[C4,q,0],[D4,q,1],[E4,q*0.5,2],[F4,q*0.5,3],[E4,q*0.5,2],[D4,q*0.5,1], + [E4,q,2],[C4,q*2,0], + [E4,q*0.5,2],[C4,q*0.5,0],[D4,q*0.5,1],[C4,q*0.5,0],[B3,q*0.5,3], + [C4,q*0.5,0],[D4,q,1],[E4,q*0.5,2],[F4,q*0.5,3],[E4,q*0.5,2],[D4,q*0.5,1],[C4,q*2,0]]; + + // Bolero Theme B (chromatic inflection): C-D-Eb-D-C-D-Eb-F-Eb-D-C-Bb3-C + var themeB=[[C4,q,0],[D4,q*0.5,1],[Eb4,q*0.5,2],[D4,q*0.5,1],[C4,q*0.5,0], + [D4,q*0.5,1],[Eb4,q*0.5,2],[F4,q,3],[Eb4,q*0.5,2],[D4,q*0.5,1], + [C4,q,0],[Bb3,q,3],[C4,q*2,0]]; + + // Continuous harmonic bed — very sparse at first, grows + var harm=[ + [0,20,[C3,G3,C4],0.06],[20,40,[C3,G3,C4],0.1],[40,60,[C3,G3,C4],0.15], + [60,80,[C3,G3,C4],0.2],[80,95,[C3,G3,E4],0.25] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht=3)bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:st.v*0.4}); + if(si>=4)bg.push({t:t,f:n[0]*1.5,d:n[1]*0.9,i:'strings',v:st.v*0.3}); + if(si>=5){ + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'strings',v:st.v*0.5}); + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:st.v*0.25}); + } + if(si>=6&&n[2]===0)bg.push({t:t,f:C3,d:0.2,i:'timpani',v:st.v*0.5}); + mel.push({t:t,l:n[2]}); + t+=n[1]; + }); + // Kick hit at end of each statement + bg.push({t:t,f:C3,d:0.3,i:'timpani',v:0.15+si*0.06}); + mel.push({t:t,l:4}); + t+=q*2; + }); + + // === FINALE: Modulation up + massive crescendo === + // Theme in Db (up a half step) — the famous key change + var finaleTheme=[[Db4,q*0.8,0],[Eb4,q*0.4,1],[F4,q*0.4,3],[Eb4,q*0.4,1],[Db4,q*0.4,0], + [Eb4,q*0.8,1],[Db4,q*1.5,0]]; + for(var fc=0;fc<2;fc++){ + var fv=0.6+fc*0.08; + snareBar(t,0.4+fc*0.05); + finaleTheme.forEach(function(n){ + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'brass',v:fv}); + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'strings',v:fv*0.8}); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:fv*0.5}); + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:fv*0.3}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + bg.push({t:t,f:Db4/2,d:0.3,i:'timpani',v:fv*0.7});mel.push({t:t,l:4});t+=q; + } + + // Final massive C chord + t+=q; + [C3,G3,C4,E4,G4,C5].forEach(function(f){ + bg.push({t:t,f:f,d:3.5,i:'brass',v:0.7});bg.push({t:t,f:f,d:3.5,i:'strings',v:0.6}); + bg.push({t:t,f:f,d:3.5,i:'choir',v:0.35}); + }); + bg.push({t:t,f:C3/2,d:3.0,i:'timpani',v:0.75});mel.push({t:t,l:4}); + + return {n:"Bolero",composer:"Ravel",bpm:72,duration:Math.ceil(t+4),isClassical:true,bg:bg,melody:mel}; + })(); // ── Barber of Seville Overture ── - var barber=tp("Barber of Seville Overture","Rossini",144, - [G4,A4,B4,G4,E4,G4,A4,B4,C5,B4,A4,G4,E4,D4,E4,G4,B4,D5,C5,B4], - [0,1,3,0,2,0,1,3,0,3,1,0,2,1,2,0,3,1,0,3], - [{d:0.24,v:0.22,i:'strings'},{d:0.22,v:0.3,i:'strings'},{d:0.20,v:0.38,i:'strings'},{d:0.18,v:0.42,i:'strings'},{d:0.16,v:0.48,i:'brass'},{d:0.14,v:0.54,i:'brass'},{d:0.12,v:0.6,i:'brass'}], - [G4,B4,D5,G5]); + // Rossini's famous overture in E major, ~75s + // Quiet opening → crescendo string runs → the "Rossini crescendo" + var barber=(function(){ + var bg=[],mel=[],t=0,q=60/144; + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.4});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.4});} + + // Harmonic bed + var harm=[ + [0,12,[E3,G3,B3],0.08],[12,28,[E3,G3,B3],0.14],[28,44,[E3,G3,B3],0.18], + [44,56,[A3,C4,E4],0.16],[56,72,[E3,G3,B3],0.22],[72,80,[E3,G3,B3],0.25] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht=1)str(t,n[0],n[1]*0.85,cv*0.6); + if(cr>=2)bg.push({t:t,f:n[0]/2,d:n[1]*0.85,i:'bass',v:cv*0.4}); + if(cr>=3){brs(t,n[0],n[1]*0.85,cv*0.5);bg.push({t:t,f:n[0],d:n[1]*0.85,i:'choir',v:cv*0.2});} + mel.push({t:t,l:n[2]});t+=n[1]; + }); + // Punctuating chord + if(cr>=2){bg.push({t:t,f:E3,d:0.3,i:'timpani',v:cv*0.5});} + mel.push({t:t,l:4});t+=q*1.5; + } + + // === SECTION 3 (28-44s): Running string passages === + // Fast scalar runs — the hallmark of Rossini + var run1=[E4,G4,B4,E5,D5,B4,G4,E4,D4,E4,G4,B4,D5,E5,D5,B4]; + var r1Ln=[2,3,0,2,1,0,3,2,1,2,3,0,1,2,1,0]; + for(var rr=0;rr<3;rr++){ + var rv=0.4+rr*0.06; + var rq=q*(0.5-rr*0.05); // speeds up each time + run1.forEach(function(f,i){ + str(t,f,rq*0.85,rv); + if(rr>0)brs(t,f,rq*0.85,rv*0.4); + if(rr>1)bg.push({t:t,f:f/2,d:rq*0.85,i:'bass',v:rv*0.3}); + mel.push({t:t,l:r1Ln[i]});t+=rq; + }); + // Big chord punctuation + [E3,B3,E4,G4].forEach(function(f){brs(t,f,0.4,rv);str(t,f,0.4,rv*0.8);}); + bg.push({t:t,f:E3/2,d:0.3,i:'timpani',v:rv*0.6});mel.push({t:t,l:4});t+=q*2; + } + + // === SECTION 4 (44-56s): Lyrical contrasting theme === + var lyric=[[B4,q*1.5,0],[A4,q*0.5,1],[G4,q,3],[E4,q,2],[G4,q*1.5,3],[A4,q*0.5,1], + [B4,q*2,0],[E5,q*1.5,2],[D5,q*0.5,1],[B4,q,0],[G4,q,3],[E4,q*2,2]]; + for(var ll=0;ll<2;ll++){ + var lv=0.4+ll*0.1; + lyric.forEach(function(n){ + str(t,n[0],n[1]*0.9,lv);brs(t,n[0],n[1]*0.9,lv*0.5); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:lv*0.35}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + + // === SECTION 5 (56-72s): Final Rossini crescendo + runs === + for(var fc=0;fc<3;fc++){ + var fv=0.5+fc*0.06; + var fq=q*(0.45-fc*0.04); + run1.forEach(function(f,i){ + str(t,f,fq*0.85,fv);brs(t,f,fq*0.85,fv*0.6); + bg.push({t:t,f:f/2,d:fq*0.85,i:'bass',v:fv*0.4}); + if(fc>0&&i%4===0)bg.push({t:t,f:E3,d:0.15,i:'timpani',v:fv*0.5}); + mel.push({t:t,l:r1Ln[i]});t+=fq; + }); + t+=q*0.5; + } + + // === FINALE: Chords === + for(var c=0;c<6;c++){ + [E3,B3,E4,G4,B4].forEach(function(f){brs(t,f,0.35,0.65);str(t,f,0.35,0.55);}); + bg.push({t:t,f:E3/2,d:0.35,i:'timpani',v:0.6});mel.push({t:t,l:4});t+=0.45; + } + [E3,B3,E4,G4,B4,E5].forEach(function(f){brs(t,f,3.0,0.7);str(t,f,3.0,0.6);}); + bg.push({t:t,f:E3/2,d:2.5,i:'timpani',v:0.7});mel.push({t:t,l:4}); + + return {n:"Barber of Seville Overture",composer:"Rossini",bpm:144,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; + })(); // ── Sabre Dance ── - var sabre=tp("Sabre Dance","Khachaturian",168, - [D4,D4,D4,Eb4,D4,D4,D4,Eb4,D4,E4,F4,G4,A4,G4,F4,E4,D4,D4,D4,A3], - [0,0,0,1,0,0,0,1,0,2,3,0,1,0,3,2,0,0,0,4], - [{d:0.24,v:0.28,i:'strings'},{d:0.22,v:0.34,i:'strings'},{d:0.20,v:0.4,i:'strings'},{d:0.18,v:0.46,i:'brass'},{d:0.16,v:0.52,i:'brass'},{d:0.14,v:0.56,i:'brass'},{d:0.12,v:0.6,i:'brass'},{d:0.10,v:0.65,i:'brass'}], - [D4,F4,A4,D5]); + // Khachaturian's frenetic Sabre Dance in D minor, ~75s + // Famous for its relentless, driving ostinato + var sabre=(function(){ + var bg=[],mel=[],t=0,q=60/168; + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.4});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.4});} + function tutti(t,f,d,v){str(t,f,d,v);brs(t,f,d,(v||0.4)*0.6);bg.push({t:t,f:f/2,d:d,i:'bass',v:(v||0.4)*0.4});} + + // Harmonic bed + var harm=[ + [0,15,[D3,A3,D4],0.1],[15,30,[D3,A3,D4],0.15],[30,50,[D3,F3,A3],0.18], + [50,65,[D3,A3,D4],0.2],[65,80,[D3,A3,D4],0.25] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht=3)brs(t,n[0],n[1]*0.7,ov*0.5); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + // Ascending burst: D-E-F-G-A + [D4,E4,F4,G4,A4].forEach(function(f,i){ + str(t,f,q*0.4,ov);mel.push({t:t,l:[0,2,3,0,1][i]});t+=q*0.5; + }); + bg.push({t:t,f:D3,d:0.2,i:'timpani',v:ov*0.6});mel.push({t:t,l:4});t+=q; + } + + // === SECTION 2 (15-30s): Contrasting lyrical middle section === + // Slower, sweeping melody in strings over sustained chords + var lyric=[[A4,q*2,1],[G4,q,0],[F4,q,3],[E4,q*2,2],[D4,q,0], + [F4,q*2,3],[E4,q,2],[D4,q,0],[A3,q*2,1],[D4,q*3,0]]; + for(var lr=0;lr<3;lr++){ + var lv=0.35+lr*0.08; + lyric.forEach(function(n){ + str(t,n[0],n[1]*0.9,lv); + if(lr>0)brs(t,n[0],n[1]*0.9,lv*0.5); + if(lr>1)bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:lv*0.4}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + if(lr>0){bg.push({t:t,f:D3,d:0.3,i:'timpani',v:lv*0.5});mel.push({t:t,l:4});t+=q;} + t+=q; + } + + // === SECTION 3 (30-50s): Ostinato returns — faster, louder === + var fastOst=[[D4,q*0.4,0],[D4,q*0.4,0],[D4,q*0.4,0],[Eb4,q*0.4,1],[D4,q*0.4,0], + [D4,q*0.4,0],[Eb4,q*0.4,1],[F4,q*0.4,3]]; + for(var fo=0;fo<6;fo++){ + var fv=0.45+fo*0.04; + fastOst.forEach(function(n){ + tutti(t,n[0],n[1]*0.7,fv); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + // Ascending chromatic burst + [D4,Eb4,E4,F4,G4,Ab4,A4,Bb4].forEach(function(f,i){ + str(t,f,q*0.35,fv);brs(t,f,q*0.35,fv*0.5); + mel.push({t:t,l:[0,1,2,3,0,1,1,2][i]});t+=q*0.4; + }); + // Slam + [D4,A4,D5].forEach(function(f){brs(t,f,0.3,fv);}); + bg.push({t:t,f:D3,d:0.3,i:'timpani',v:fv*0.7});mel.push({t:t,l:4});t+=q; + } + + // === SECTION 4 (50-65s): Wild descending runs + ostinato === + var desc=[A4,G4,F4,E4,D4,E4,F4,G4,A4,Bb4,A4,G4,F4,E4,D4,A3]; + var dLn=[1,0,3,2,0,2,3,0,1,2,1,0,3,2,0,4]; + for(var dr=0;dr<3;dr++){ + var dv=0.55+dr*0.05; + var dq=q*(0.45-dr*0.04); + desc.forEach(function(f,i){ + tutti(t,f,dq*0.8,dv); + if(dr>0)bg.push({t:t,f:f,d:dq*0.8,i:'brass',v:dv*0.5}); + if(dr>1&&i%4===0)bg.push({t:t,f:D3,d:0.15,i:'timpani',v:dv*0.6}); + mel.push({t:t,l:dLn[i]});t+=dq; + }); + t+=q*0.5; + // Ostinato fragment + fastOst.forEach(function(n){ + tutti(t,n[0],n[1]*0.65,dv);mel.push({t:t,l:n[2]});t+=n[1]*0.85; + }); + t+=q*0.5; + } + + // === FINALE: Hammered D minor chords === + for(var c=0;c<8;c++){ + [D3,A3,D4,F4,A4].forEach(function(f){brs(t,f,0.3,0.65);str(t,f,0.3,0.55);}); + bg.push({t:t,f:D3/2,d:0.3,i:'timpani',v:0.65});mel.push({t:t,l:4});t+=0.38; + } + [D3,A3,D4,F4,A4,D5].forEach(function(f){brs(t,f,2.5,0.7);str(t,f,2.5,0.6);}); + bg.push({t:t,f:D3/2,d:2.0,i:'timpani',v:0.75});mel.push({t:t,l:4}); + + return {n:"Sabre Dance",composer:"Khachaturian",bpm:168,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; + })(); // ── Sorcerer's Apprentice ── - var sorcerer=tp("Sorcerer's Apprentice","Dukas",132, - [A3,E4,C4,E4,A3,E4,C4,E4,A3,B3,C4,D4,E4,D4,C4,B3,A3,C4,E4,A4], - [0,2,1,2,0,2,1,2,0,1,2,0,2,0,2,1,0,1,2,3], - [{d:0.28,v:0.2,i:'woodwind'},{d:0.26,v:0.28,i:'woodwind'},{d:0.24,v:0.35,i:'strings'},{d:0.22,v:0.42,i:'strings'},{d:0.20,v:0.5,i:'brass'},{d:0.18,v:0.58,i:'brass'}], - [A3,C4,E4,A4]); + // Dukas's magical march in F minor, ~80s + // Famous bassoon theme → march builds → magical chaos + var sorcerer=(function(){ + var bg=[],mel=[],t=0,q=60/132; + function ww(t,f,d,v){bg.push({t:t,f:f,d:d,i:'woodwind',v:v||0.3});} + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.4});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.4});} + + // Harmonic bed — mysterious + var harm=[ + [0,16,[F3,Ab3,C4],0.06],[16,32,[F3,Ab3,C4],0.1],[32,48,[F3,Ab3,C4],0.15], + [48,64,[Bb3,Db4,F4],0.18],[64,82,[F3,Ab3,C4],0.22] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht0)str(t,n[0]*2,n[1]*0.85,bv*0.3); // octave higher strings echo + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + + // === SECTION 2 (16-32s): March begins — walking brooms === + // Steady march rhythm with the theme on top + var march=[[C4,q,2],[C4,q*0.5,2],[Ab3,q*0.5,1],[F3,q,0],[Ab3,q*0.5,1],[C4,q*0.5,2], + [Eb4,q,3],[Db4,q*0.5,0],[C4,q*0.5,2],[Ab3,q,1],[F3,q*1.5,0]]; + for(var mr=0;mr<4;mr++){ + var mv=0.3+mr*0.06; + var mInst=mr<2?'woodwind':'strings'; + // March bass: oom-pah + for(var mb=0;mb<6;mb++){ + bg.push({t:t+mb*q*2,f:F3,d:q*0.8,i:'bass',v:mv*0.5}); + bg.push({t:t+mb*q*2+q,f:C3,d:q*0.8,i:'bass',v:mv*0.4}); + if(mr>=2)bg.push({t:t+mb*q*2,f:F3,d:0.15,i:'timpani',v:mv*0.4}); + } + march.forEach(function(n){ + bg.push({t:t,f:n[0],d:n[1]*0.85,i:mInst,v:mv}); + if(mr>=2)brs(t,n[0],n[1]*0.85,mv*0.4); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + + // === SECTION 3 (32-48s): Chaos builds — theme fragments overlap === + // Faster fragments of the theme, like multiple brooms marching + var frag1=[[F3,q*0.5,0],[Ab3,q*0.5,1],[C4,q*0.5,2],[Eb4,q*0.5,3],[C4,q*0.5,2],[Ab3,q*0.5,1]]; + var frag2=[[C4,q*0.5,2],[Db4,q*0.5,0],[C4,q*0.5,2],[Ab3,q*0.5,1],[F3,q*0.5,0],[Ab3,q*0.5,1]]; + for(var ch=0;ch<4;ch++){ + var cv=0.4+ch*0.05; + (ch%2===0?frag1:frag2).forEach(function(n){ + str(t,n[0],n[1]*0.8,cv);brs(t,n[0],n[1]*0.8,cv*0.5); + bg.push({t:t,f:n[0]/2,d:n[1]*0.8,i:'bass',v:cv*0.4}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + // Ascending rush + [F3,Ab3,C4,Eb4,F4,Ab4].forEach(function(f,i){ + str(t,f,q*0.35,cv);mel.push({t:t,l:[0,1,2,3,0,1][i]});t+=q*0.4; + }); + bg.push({t:t,f:F3,d:0.3,i:'timpani',v:cv*0.6});mel.push({t:t,l:4});t+=q; + } + + // === SECTION 4 (48-64s): Full orchestra — magical pandemonium === + // Full theme at double speed with brass + var fullTheme=[[F4,q*0.4,0],[Ab4,q*0.4,1],[C5,q*0.4,2],[Ab4,q*0.4,1],[F4,q*0.4,0], + [Ab4,q*0.4,1],[C5,q*0.4,2],[Eb5,q*0.4,3],[C5,q*0.4,2],[Ab4,q*0.4,1], + [F4,q*0.8,0],[C5,q*0.4,2],[Ab4,q*0.4,1],[F4,q*0.8,0]]; + for(var ft=0;ft<4;ft++){ + var fv=0.5+ft*0.05; + fullTheme.forEach(function(n){ + str(t,n[0],n[1]*0.8,fv);brs(t,n[0],n[1]*0.8,fv*0.6); + bg.push({t:t,f:n[0]/2,d:n[1]*0.8,i:'bass',v:fv*0.4}); + if(ft>1)bg.push({t:t,f:n[0],d:n[1]*0.8,i:'choir',v:fv*0.2}); + if(ft>2&&n[2]===0)bg.push({t:t,f:F3,d:0.15,i:'timpani',v:fv*0.5}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + bg.push({t:t,f:F3,d:0.3,i:'timpani',v:fv*0.6});mel.push({t:t,l:4});t+=q; + } + + // === SECTION 5 (64-78s): Wild ending === + // Descending cascades + [C5,Bb4,Ab4,G4,F4,Eb4,Db4,C4,Bb3,Ab3,G3,F3].forEach(function(f,i){ + str(t,f,q*0.3,0.55);brs(t,f,q*0.3,0.45); + mel.push({t:t,l:[2,3,1,0,3,2,0,1,3,1,0,4][i]});t+=q*0.35; + }); + t+=q; + + // Final chords + for(var c=0;c<6;c++){ + [F3,C4,F4,Ab4].forEach(function(f){brs(t,f,0.35,0.65);str(t,f,0.35,0.55);}); + bg.push({t:t,f:F3/2,d:0.35,i:'timpani',v:0.6});mel.push({t:t,l:4});t+=0.45; + } + [F3,C4,F4,Ab4,C5].forEach(function(f){brs(t,f,3.0,0.65);str(t,f,3.0,0.55);}); + bg.push({t:t,f:F3/2,d:2.5,i:'timpani',v:0.7});mel.push({t:t,l:4}); + + return {n:"Sorcerer's Apprentice",composer:"Dukas",bpm:132,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; + })(); // ── Morning Mood ── - var morning=tp("Morning Mood","Grieg",60, - [F4,A4,C5,A4,F4,A4,C5,E5,F5,E5,C5,A4,F4,G4,A4,Bb4,C5,Bb4,A4,F4], - [0,1,2,1,0,1,2,3,0,3,2,1,0,1,1,2,2,2,1,0], - [{d:0.45,v:0.15,i:'woodwind'},{d:0.42,v:0.2,i:'woodwind'},{d:0.39,v:0.28,i:'woodwind'},{d:0.36,v:0.35,i:'strings'},{d:0.33,v:0.42,i:'strings'},{d:0.30,v:0.5,i:'brass'}], - [F4,A4,C5,F5]); + // Grieg's Peer Gynt — gentle sunrise in F major, ~80s + // Famous flute melody rising like dawn, builds to full orchestra + var morning=(function(){ + var bg=[],mel=[],t=0,q=60/60; // slow, pastoral tempo + function ww(t,f,d,v){bg.push({t:t,f:f,d:d,i:'woodwind',v:v||0.25});} + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.3});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.35});} + + // Gentle harmonic bed — sustained strings simulating dawn + var harm=[ + [0,18,[F3,A3,C4],0.06],[18,36,[F3,A3,C4],0.1],[36,54,[F3,A3,C4],0.15], + [54,70,[Bb3,D4,F4],0.14],[70,85,[F3,A3,C4],0.18] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht0)bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:wv*0.2}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + + // === SECTION 5 (70-82s): Final sunrise — melody one last time, full and warm === + fluteMel1.forEach(function(n){ + str(t,n[0],n[1]*0.9,0.5);brs(t,n[0],n[1]*0.9,0.35);ww(t,n[0],n[1]*0.9,0.3); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:0.25}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q*0.5; + fluteMel2.forEach(function(n){ + str(t,n[0],n[1]*0.9,0.5);brs(t,n[0],n[1]*0.9,0.35);ww(t,n[0],n[1]*0.9,0.3); + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:0.2}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + + // Gentle ending — sustained E major chord fading + [E3,B3,E4,G4,B4,E5].forEach(function(f){ + str(t,f,4.0,0.4);ww(t,f,4.0,0.25); + }); + bg.push({t:t,f:E3/2,d:3.0,i:'bass',v:0.2});mel.push({t:t,l:4}); + + return {n:"Morning Mood",composer:"Grieg",bpm:60,duration:Math.ceil(t+4),isClassical:true,bg:bg,melody:mel}; + })(); // ── Mars, Bringer of War ── var mars=(function(){ @@ -1816,11 +2453,122 @@ const CLASSICAL_PIECES=(function(){ })(); // ── Flight of the Bumblebee ── - var bumblebee=tp("Flight of the Bumblebee","Rimsky-Korsakov",180, - [E5,Eb5,D5,C5,B4,Bb4,A4,Ab4,G4,Gb4,F4,E4,F4,Gb4,G4,Ab4,A4,Bb4,B4,C5,D5,Eb5], - [2,1,0,2,3,2,1,0,3,2,1,0,1,2,3,0,1,2,3,2,0,1], - [{d:0.20,v:0.2,i:'strings'},{d:0.16,v:0.26,i:'strings'},{d:0.14,v:0.32,i:'strings'},{d:0.12,v:0.38,i:'strings'},{d:0.11,v:0.44,i:'strings'},{d:0.10,v:0.48,i:'strings'},{d:0.09,v:0.52,i:'strings'},{d:0.08,v:0.56,i:'strings'},{d:0.07,v:0.6,i:'strings'}], - [E4,Ab4,B4,E5]); + // Rimsky-Korsakov's famous chromatic whirlwind in A minor, ~65s + // Rapid chromatic scales up and down — the buzzing bee + var bumblebee=(function(){ + var bg=[],mel=[],t=0,q=60/180; + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.4});} + + // Sparse harmonic bed — stays out of the way of the rapid runs + var harm=[ + [0,12,[A3,C4,E4],0.06],[12,24,[A3,C4,E4],0.1],[24,40,[A3,C4,E4],0.14], + [40,52,[D4,F4,A4],0.12],[52,68,[A3,C4,E4],0.16] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht0)bg.push({t:t,f:f,d:nq2*0.8,i:'woodwind',v:v2*0.4}); + mel.push({t:t,l:dLn[i]});t+=nq2; + }); + ascChrom.forEach(function(f,i){ + str(t,f,nq2*0.8,v2); + if(s2>0)bg.push({t:t,f:f,d:nq2*0.8,i:'woodwind',v:v2*0.4}); + mel.push({t:t,l:aLn[i]});t+=nq2; + }); + t+=q*0.5; + } + + // === SECTION 3 (24-40s): Full string section — the bee gets frantic === + for(var s3=0;s3<4;s3++){ + var v3=0.38+s3*0.04; + var nq3=q*0.4; + // Alternate between descending and ascending with different patterns + var pattern=s3%2===0?descChrom:ascChrom; + var pLn=s3%2===0?dLn:aLn; + pattern.forEach(function(f,i){ + str(t,f,nq3*0.8,v3);bg.push({t:t,f:f,d:nq3*0.8,i:'woodwind',v:v3*0.3}); + bg.push({t:t,f:f/2,d:nq3*0.8,i:'bass',v:v3*0.2}); + mel.push({t:t,l:pLn[i]});t+=nq3; + }); + // Quick turnaround notes + [E4,G4,B4,E5].forEach(function(f,i){ + str(t,f,nq3*0.6,v3);mel.push({t:t,l:[0,3,0,2][i]});t+=nq3*0.7; + }); + t+=q*0.3; + } + + // === SECTION 4 (40-52s): Contrasting middle — broader melody === + var middle=[[A4,q*1.5,1],[G4,q*0.75,3],[F4,q*0.75,0],[E4,q*1.5,2], + [G4,q*0.75,3],[A4,q*0.75,1],[B4,q*1.5,0],[A4,q*0.75,1], + [G4,q*0.75,3],[E4,q*2,2]]; + for(var m=0;m<2;m++){ + var mv=0.4+m*0.08; + middle.forEach(function(n){ + str(t,n[0],n[1]*0.9,mv);bg.push({t:t,f:n[0],d:n[1]*0.9,i:'woodwind',v:mv*0.5}); + if(m>0)bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:mv*0.3}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + + // === SECTION 5 (52-65s): Final frenzy — fastest runs === + for(var s5=0;s5<4;s5++){ + var v5=0.48+s5*0.04; + var nq5=q*(0.38-s5*0.02); // accelerating + descChrom.forEach(function(f,i){ + str(t,f,nq5*0.75,v5);bg.push({t:t,f:f,d:nq5*0.75,i:'woodwind',v:v5*0.4}); + if(s5>1)bg.push({t:t,f:f/2,d:nq5*0.75,i:'bass',v:v5*0.3}); + mel.push({t:t,l:dLn[i]});t+=nq5; + }); + if(s5<3){ + ascChrom.slice(0,7).forEach(function(f,i){ + str(t,f,nq5*0.75,v5);mel.push({t:t,l:aLn[i]});t+=nq5; + }); + } + t+=q*0.3; + } + + // Final sting — the bee lands! + [A3,C4,E4,A4].forEach(function(f){ + str(t,f,0.3,0.55);bg.push({t:t,f:f,d:0.3,i:'brass',v:0.4}); + }); + mel.push({t:t,l:4});t+=0.5; + [A3,E4,A4].forEach(function(f){str(t,f,2.0,0.4);}); + bg.push({t:t,f:A3/2,d:1.5,i:'bass',v:0.3});mel.push({t:t,l:4}); + + return {n:"Flight of the Bumblebee",composer:"Rimsky-Korsakov",bpm:180,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; + })(); // ── Dance of the Sugar Plum Fairy ── var sugarplum=(function(){ @@ -1879,18 +2627,249 @@ const CLASSICAL_PIECES=(function(){ })(); // ── Habanera (Carmen) ── - var habanera=tp("Habanera (Carmen)","Bizet",108, - [D5,Db5,C5,B4,Bb4,A4,Ab4,G4,Gb4,F4,E4,F4,Gb4,G4,Ab4,A4,Bb4,A4,Ab4,G4], - [0,1,2,3,2,1,0,3,2,1,0,1,2,3,0,1,2,1,0,3], - [{d:0.32,v:0.2,i:'strings'},{d:0.30,v:0.28,i:'strings'},{d:0.28,v:0.35,i:'strings'},{d:0.26,v:0.42,i:'brass'},{d:0.24,v:0.48,i:'brass'},{d:0.22,v:0.55,i:'brass'}], - [D4,F4,A4,D5]); + // Bizet's famous aria in D minor, ~80s + // Descending chromatic melody with the habanera rhythm (dotted + sixteenth) + var habanera=(function(){ + var bg=[],mel=[],t=0,q=60/108; + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.35});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.35});} + function ww(t,f,d,v){bg.push({t:t,f:f,d:d,i:'woodwind',v:v||0.3});} + + // Harmonic bed + var harm=[ + [0,18,[D3,F3,A3],0.08],[18,36,[D3,F3,A3],0.12],[36,54,[D3,F3,A3],0.16], + [54,68,[Bb3,D4,F4],0.14],[68,84,[D3,F3,A3],0.18] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht0)str(t,n[0],n[1]*0.9,v1*0.5); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + ans1.forEach(function(n){ + ww(t,n[0],n[1]*0.9,v1); + if(s1>0)str(t,n[0],n[1]*0.9,v1*0.5); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + + // === SECTION 2 (18-36s): Second verse — strings take melody === + // Same chromatic descent but with richer orchestration + var desc2=[[D5,q*0.65,0],[Db5,q*0.65,1],[C5,q*0.65,2],[B4,q*0.65,3], + [Bb4,q*0.65,2],[A4,q*0.65,1],[Ab4,q*0.65,0],[G4,q*1.3,3]]; + var ans2=[[A4,q*0.5,1],[Bb4,q*0.5,2],[C5,q*0.5,2],[A4,q,1],[F4,q*0.5,3],[D4,q*1.5,0]]; + + for(var s2=0;s2<3;s2++){ + var v2=0.32+s2*0.06; + habBass(t,D3,v2);habBass(t+q*3,A3,v2); + desc2.forEach(function(n){ + str(t,n[0],n[1]*0.9,v2);ww(t,n[0],n[1]*0.9,v2*0.5); + if(s2>0)bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:v2*0.3}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + ans2.forEach(function(n){ + str(t,n[0],n[1]*0.9,v2);ww(t,n[0],n[1]*0.9,v2*0.5); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + bg.push({t:t,f:D3,d:0.2,i:'timpani',v:v2*0.4});mel.push({t:t,l:4});t+=q; + } + + // === SECTION 3 (36-54s): Major key contrast — "L'amour" refrain === + // Shifts to D major — bright, passionate + var refrain=[[D4,q,0],[F4,q*0.5,3],[A4,q*0.5,1],[D5,q*1.5,0], + [C5,q*0.5,2],[Bb4,q*0.5,2],[A4,q,1],[G4,q*0.5,3],[A4,q*0.5,1], + [D4,q*2,0]]; + for(var s3=0;s3<3;s3++){ + var v3=0.4+s3*0.06; + habBass(t,D3,v3);habBass(t+q*3,A3,v3); + refrain.forEach(function(n){ + str(t,n[0],n[1]*0.9,v3);brs(t,n[0],n[1]*0.9,v3*0.5); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:v3*0.35}); + if(s3>1)bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:v3*0.2}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + if(s3>0){bg.push({t:t,f:D3,d:0.3,i:'timpani',v:v3*0.5});mel.push({t:t,l:4});} + t+=q; + } + + // === SECTION 4 (54-68s): Return of chromatic descent — full orchestra === + for(var s4=0;s4<3;s4++){ + var v4=0.5+s4*0.05; + habBass(t,D3,v4);habBass(t+q*3,D3,v4); + desc1.forEach(function(n){ + str(t,n[0],n[1]*0.9,v4);brs(t,n[0],n[1]*0.9,v4*0.6); + ww(t,n[0],n[1]*0.9,v4*0.4); + if(s4>0)bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:v4*0.2}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + ans1.forEach(function(n){ + str(t,n[0],n[1]*0.9,v4);brs(t,n[0],n[1]*0.9,v4*0.6); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + bg.push({t:t,f:D3,d:0.25,i:'timpani',v:v4*0.6});mel.push({t:t,l:4});t+=q; + } + + // === FINALE: Passionate ending === + // Final descent + big D minor chord + desc1.forEach(function(n){ + str(t,n[0],n[1]*0.8,0.6);brs(t,n[0],n[1]*0.8,0.5); + bg.push({t:t,f:n[0],d:n[1]*0.8,i:'choir',v:0.3}); + mel.push({t:t,l:n[2]});t+=n[1]*0.85; + }); + t+=q; + for(var c=0;c<4;c++){ + [D3,A3,D4,F4].forEach(function(f){brs(t,f,0.4,0.6);str(t,f,0.4,0.5);}); + bg.push({t:t,f:D3/2,d:0.4,i:'timpani',v:0.6});mel.push({t:t,l:4});t+=0.5; + } + [D3,A3,D4,F4,A4].forEach(function(f){brs(t,f,3.0,0.6);str(t,f,3.0,0.5);}); + bg.push({t:t,f:D3/2,d:2.5,i:'timpani',v:0.65});mel.push({t:t,l:4}); + + return {n:"Habanera (Carmen)",composer:"Bizet",bpm:108,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; + })(); // ── Spring (Four Seasons) ── - var spring=tp("Spring (Four Seasons)","Vivaldi",120, - [F4,A4,C5,A4,F4,G4,A4,Bb4,C5,D5,C5,Bb4,A4,G4,F4,E4,F4,G4,A4,C5], - [0,1,2,1,0,3,1,2,2,0,2,2,1,3,0,2,0,3,1,2], - [{d:0.24,v:0.22,i:'strings'},{d:0.22,v:0.28,i:'strings'},{d:0.20,v:0.35,i:'strings'},{d:0.18,v:0.42,i:'strings'},{d:0.16,v:0.48,i:'brass'},{d:0.14,v:0.54,i:'brass'},{d:0.12,v:0.6,i:'brass'}], - [F4,A4,C5,F5]); + // Vivaldi's Spring from The Four Seasons in E major, ~75s + // Joyful opening ritornello → birdsong trills → pastoral dance + var spring=(function(){ + var bg=[],mel=[],t=0,q=60/120; + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.4});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.35});} + + // Harmonic bed + var harm=[ + [0,14,[E3,G3,B3],0.1],[14,28,[E3,G3,B3],0.14],[28,44,[A3,C4,E4],0.13], + [44,58,[E3,G3,B3],0.16],[58,78,[E3,G3,B3],0.2] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht0)bg.push({t:t,f:n[0],d:n[1]*0.8,i:'woodwind',v:bv*0.4}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q*0.5; + // Gentle bass response + [E3,B3,E4].forEach(function(f){bg.push({t:t,f:f,d:q*1.5,i:'bass',v:bv*0.3});}); + mel.push({t:t,l:4});t+=q*2; + } + + // === SECTION 3 (28-44s): Ritornello returns — fuller === + for(var r2=0;r2<2;r2++){ + var rv2=0.42+r2*0.08; + rit.forEach(function(n){ + str(t,n[0],n[1]*0.85,rv2);brs(t,n[0],n[1]*0.85,rv2*0.4); + bg.push({t:t,f:n[0]/2,d:n[1]*0.85,i:'bass',v:rv2*0.3}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q*0.3; + ritAns.forEach(function(n){ + str(t,n[0],n[1]*0.85,rv2);brs(t,n[0],n[1]*0.85,rv2*0.4); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + // Running scales + [E4,Ab4,B4,E5,D5,B4,Ab4,E4,D4,E4,Ab4,B4,D5,E5,Ab5,E5].forEach(function(f,i){ + str(t,f,q*0.35,0.5);mel.push({t:t,l:[2,1,0,2,1,0,1,2,0,2,1,0,1,2,0,2][i]});t+=q*0.4; + }); + t+=q; + + // === SECTION 4 (44-58s): Pastoral dance — lilting 12/8 feel === + var dance=[[E4,q,2],[Ab4,q*0.5,1],[B4,q*0.5,0],[E4,q*0.5,2],[Ab4,q*0.5,1], + [B4,q,0],[E5,q*0.5,2],[D5,q*0.5,1],[B4,q,0],[Ab4,q*0.5,1],[E4,q*1,2]]; + for(var d=0;d<3;d++){ + var dv=0.45+d*0.06; + dance.forEach(function(n){ + str(t,n[0],n[1]*0.85,dv); + if(d>0)brs(t,n[0],n[1]*0.85,dv*0.4); + if(d>1)bg.push({t:t,f:n[0]/2,d:n[1]*0.85,i:'bass',v:dv*0.35}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + } + + // === SECTION 5 (58-72s): Final ritornello — full orchestra === + for(var r3=0;r3<3;r3++){ + var rv3=0.52+r3*0.06; + rit.forEach(function(n){ + str(t,n[0],n[1]*0.85,rv3);brs(t,n[0],n[1]*0.85,rv3*0.5); + bg.push({t:t,f:n[0]/2,d:n[1]*0.85,i:'bass',v:rv3*0.35}); + if(r3>1)bg.push({t:t,f:n[0],d:n[1]*0.85,i:'choir',v:rv3*0.2}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q*0.3; + ritAns.forEach(function(n){ + str(t,n[0],n[1]*0.85,rv3);brs(t,n[0],n[1]*0.85,rv3*0.5); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q*0.5; + } + + // Finale chords + for(var c=0;c<4;c++){ + [E3,B3,E4,Ab4,B4].forEach(function(f){str(t,f,0.4,0.6);brs(t,f,0.4,0.5);}); + mel.push({t:t,l:4});t+=0.5; + } + [E3,B3,E4,Ab4,B4,E5].forEach(function(f){str(t,f,3.0,0.6);brs(t,f,3.0,0.5);}); + bg.push({t:t,f:E3/2,d:2.5,i:'timpani',v:0.55});mel.push({t:t,l:4}); + + return {n:"Spring (Four Seasons)",composer:"Vivaldi",bpm:120,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; + })(); // ── Für Elise ── var furelise=(function(){ @@ -2006,11 +2985,134 @@ const CLASSICAL_PIECES=(function(){ })(); // ── Ode to Joy ── - var odeToJoy=tp("Ode to Joy","Beethoven",100, - [E4,E4,F4,G4,G4,F4,E4,D4,C4,C4,D4,E4,E4,D4,D4,C4,C4,D4,E4,D4,C4,C4], - [2,2,1,3,3,1,2,0,0,0,1,2,2,0,0,0,0,1,2,0,0,0], - [{d:0.42,v:0.18,i:'woodwind'},{d:0.40,v:0.25,i:'strings'},{d:0.38,v:0.32,i:'strings'},{d:0.36,v:0.4,i:'brass'},{d:0.34,v:0.48,i:'brass'}], - [C4,E4,G4,C5]); + // Beethoven's 9th Symphony finale in D major, ~85s + // The most famous melody in classical music, builds from solo to full chorus + var odeToJoy=(function(){ + var bg=[],mel=[],t=0,q=60/100; + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.4});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.4});} + function ww(t,f,d,v){bg.push({t:t,f:f,d:d,i:'woodwind',v:v||0.3});} + + // Harmonic bed + var harm=[ + [0,16,[D3,A3,D4],0.08],[16,32,[D3,A3,D4],0.12],[32,48,[D3,A3,D4],0.16], + [48,64,[G3,B3,D4],0.15],[64,88,[D3,A3,D4],0.2] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht0)bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:bv*0.25}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + bg.push({t:t,f:D3,d:0.3,i:'timpani',v:bv*0.5});mel.push({t:t,l:4});t+=q; + } + + // === SECTION 5 (64-80s): Grand finale — full orchestra + choir === + // "Freude, schöner Götterfunken" at full power + melA.forEach(function(n){ + str(t,n[0],n[1]*0.9,0.55);brs(t,n[0],n[1]*0.9,0.45); + ww(t,n[0],n[1]*0.9,0.3); + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:0.35}); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:0.3}); + if(n[2]===1||n[2]===0)bg.push({t:t,f:D3,d:0.15,i:'timpani',v:0.35}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + melB.forEach(function(n){ + str(t,n[0],n[1]*0.9,0.58);brs(t,n[0],n[1]*0.9,0.48); + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:0.38}); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:0.3}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + t+=q; + + // Final triumphant repeat of A + melA.forEach(function(n){ + str(t,n[0],n[1]*0.9,0.6);brs(t,n[0],n[1]*0.9,0.5); + bg.push({t:t,f:n[0],d:n[1]*0.9,i:'choir',v:0.4}); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:0.35}); + mel.push({t:t,l:n[2]});t+=n[1]; + }); + + // === CODA: Big D major chords === + t+=q; + for(var c=0;c<6;c++){ + [D3,A3,D4,Gb4,A4].forEach(function(f){brs(t,f,0.45,0.65);str(t,f,0.45,0.55);}); + bg.push({t:t,f:D3/2,d:0.45,i:'timpani',v:0.6}); + bg.push({t:t,f:D4,d:0.45,i:'choir',v:0.4}); + mel.push({t:t,l:4});t+=0.55; + } + [D3,A3,D4,Gb4,A4,D5].forEach(function(f){ + brs(t,f,4.0,0.7);str(t,f,4.0,0.6);bg.push({t:t,f:f,d:4.0,i:'choir',v:0.4}); + }); + bg.push({t:t,f:D3/2,d:3.0,i:'timpani',v:0.7});mel.push({t:t,l:4}); + + return {n:"Ode to Joy",composer:"Beethoven",bpm:100,duration:Math.ceil(t+4),isClassical:true,bg:bg,melody:mel}; + })(); // ── William Tell Overture (Storm) ── var tellStorm=(function(){ From b9f46feba936dd37a906237f7707daf9cf310608 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 02:53:23 +0000 Subject: [PATCH 02/22] Fix wrong notes in 7 classical pieces verified against actual scores MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hall of the Mountain King: Fix theme 2nd phrase to D-B-D-Db-A-Db (was using Eb where Db/C# belongs, wrong phrase structure) Für Elise: Fix answer phrase G# note - C5 → Ab4 (G#4) (E-G#-B-A arpeggio, not E-C-B-A) Toccata & Fugue in D Minor: Fix opening mordent A-G-A (whole step) (was A-Ab-A half step, standard editions use whole step) Morning Mood: Complete melody rewrite to correct E major key (was in wrong key; real Grieg melody is G#-A-B-C#-B-A ascending) Dance of the Sugar Plum Fairy: Fix celesta theme to E-D#-E-B-D-C-A (was repeating E-D#-E-B twice; real piece descends after trill) Fix answer phrase G4 → Ab4 (G#4) The Blue Danube: Rewrite melody to match real waltz (ascending thirds C-E-G, G-B-D with oom-pah-pah bass pattern) Canon in D: Fix violin melody to F#-E-D-C#-B-A-B-C# (var 1) then D-C#-B-A-G-F#-G-A (var 2) matching Pachelbel's actual score https://claude.ai/code/session_016nhMjrAqwWXKKgBm6EQuX1 --- index.html | 205 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 133 insertions(+), 72 deletions(-) diff --git a/index.html b/index.html index 7c47db5..9b42c93 100644 --- a/index.html +++ b/index.html @@ -849,8 +849,8 @@ const CLASSICAL_PIECES=(function(){ var hmk=(function(){ var bg=[],mel=[]; function orch(t,freq,dur,v,inst){bg.push({t:t,f:freq,d:dur,i:inst||'strings',v:v||0.3});} - var theme=[A3,B3,C4,D4,E4,C4,E4,Eb4,E4,Eb4,E4,D4,C4,B3]; - var lanes=[0,1,2,0,1,2,1,3,1,3,1,0,2,1]; + var theme=[A3,B3,C4,D4,E4,C4,E4,D4,B3,D4,Db4,A3,Db4,A3]; + var lanes=[0,1,2,0,1,2,1,0,3,0,1,3,1,3]; var t=0; // Pass 1: Very slow, barely audible (creeping start) var d0=0.55; @@ -2094,18 +2094,18 @@ const CLASSICAL_PIECES=(function(){ })(); // ── Morning Mood ── - // Grieg's Peer Gynt — gentle sunrise in F major, ~80s - // Famous flute melody rising like dawn, builds to full orchestra + // Grieg's Peer Gynt — gentle sunrise in E major, ~80s + // Famous flute melody: G#-A-B-C#-B-A, then G#-A-B-C#-E-D#-C#-B-A-G# var morning=(function(){ var bg=[],mel=[],t=0,q=60/60; // slow, pastoral tempo function ww(t,f,d,v){bg.push({t:t,f:f,d:d,i:'woodwind',v:v||0.25});} function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.3});} function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.35});} - // Gentle harmonic bed — sustained strings simulating dawn + // Gentle harmonic bed — E major sustained strings var harm=[ - [0,18,[F3,A3,C4],0.06],[18,36,[F3,A3,C4],0.1],[36,54,[F3,A3,C4],0.15], - [54,70,[Bb3,D4,F4],0.14],[70,85,[F3,A3,C4],0.18] + [0,18,[E3,Ab3,B3],0.06],[18,36,[E3,Ab3,B3],0.1],[36,54,[E3,Ab3,B3],0.15], + [54,70,[A3,Db4,E4],0.14],[70,85,[E3,Ab3,B3],0.18] ]; harm.forEach(function(h){ for(var ht=h[0];ht0)bg.push({t:t,f:n[0],d:n[1]*0.9,i:'brass',v:v2*0.5}); + function str(t,f,d,v){bg.push({t:t,f:f,d:d,i:'strings',v:v||0.4});} + function brs(t,f,d,v){bg.push({t:t,f:f,d:d,i:'brass',v:v||0.35});} + + // Harmonic bed + var harm=[ + [0,12,[C3,E3,G3],0.06],[12,30,[C3,E3,G3],0.1],[30,50,[C3,E3,G3],0.14], + [50,65,[G3,B3,D4],0.12],[65,80,[C3,E3,G3],0.18] + ]; + harm.forEach(function(h){ + for(var ht=h[0];ht0)brs(t,n[0],n[1]*0.9,wv*0.4); + // Add waltz bass on beat 1 of each 3-beat group + if(n[1]>=q*2)waltz(t,C3,E3,wv); + mel.push({t:t,l:n[2]});t+=n[1];bi++; + }); + t+=q; + } + + // === SECTION 3 (30-50s): Second waltz — contrasting theme === + // More lyrical flowing melody + var waltz2=[ + [E4,q*2,2],[D4,q,1],[C4,q*3,0],[E4,q*2,2],[G4,q,3], + [G4,q*2,3],[F4,q,1],[E4,q*3,2],[D4,q*2,1],[E4,q,2], + [F4,q*2,1],[E4,q,2],[D4,q*3,1],[C4,q*3,0] + ]; + for(var w2=0;w2<2;w2++){ + var wv2=0.38+w2*0.08; + waltz2.forEach(function(n){ + str(t,n[0],n[1]*0.9,wv2); + if(w2>0)brs(t,n[0],n[1]*0.9,wv2*0.4); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:wv2*0.3}); + if(n[1]>=q*2)waltz(t,C3,E3,wv2); mel.push({t:t,l:n[2]});t+=n[1]; }); - t+=0.4; + t+=q; } - // Recap theme 1 with full orchestra - th1.forEach(function(n){ - bg.push({t:t,f:n[0],d:n[1]*0.9,i:'brass',v:0.55});bg.push({t:t,f:n[0],d:n[1]*0.9,i:'strings',v:0.45}); - bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:0.35}); + + // === SECTION 4 (50-65s): Waltz 1 returns — full orchestra === + waltz1.forEach(function(n){ + str(t,n[0],n[1]*0.9,0.52);brs(t,n[0],n[1]*0.9,0.4); + bg.push({t:t,f:n[0]/2,d:n[1]*0.9,i:'bass',v:0.3}); + if(n[1]>=q*2)waltz(t,C3,E3,0.5); mel.push({t:t,l:n[2]});t+=n[1]; }); - t+=0.4; - // Finale waltz chords - for(var c=0;c<4;c++){ - [C4,E4,G4,C5].forEach(function(f){bg.push({t:t,f:f,d:q*2.5,i:'brass',v:0.6});bg.push({t:t,f:f,d:q*2.5,i:'strings',v:0.5});}); + t+=q; + // Faster, more energetic repeat + waltz1.forEach(function(n){ + str(t,n[0],n[1]*0.85,0.55);brs(t,n[0],n[1]*0.85,0.45); + bg.push({t:t,f:n[0],d:n[1]*0.85,i:'choir',v:0.2}); + mel.push({t:t,l:n[2]});t+=n[1]*0.9; + }); + + // === FINALE: Big waltz chords === + t+=q; + for(var c=0;c<6;c++){ + [C4,E4,G4,C5].forEach(function(f){brs(t,f,q*2.5,0.6);str(t,f,q*2.5,0.5);}); + bg.push({t:t,f:C3,d:q*2,i:'timpani',v:0.5}); mel.push({t:t,l:4});t+=q*3; } - [C4,E4,G4,C5].forEach(function(f){bg.push({t:t,f:f,d:2.5,i:'brass',v:0.6});bg.push({t:t,f:f,d:2.5,i:'strings',v:0.5});}); + [C4,E4,G4,C5].forEach(function(f){brs(t,f,2.5,0.65);str(t,f,2.5,0.55);}); bg.push({t:t,f:C3,d:2.0,i:'timpani',v:0.65});mel.push({t:t,l:4}); + return {n:"The Blue Danube",composer:"J. Strauss II",bpm:180,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; })(); @@ -2573,10 +2633,10 @@ const CLASSICAL_PIECES=(function(){ // ── Dance of the Sugar Plum Fairy ── var sugarplum=(function(){ var bg=[],mel=[],t=0,q=0.4; - var theme=[E4,Eb4,E4,B3,E4,Eb4,E4,B3,E4,F4,E4,D4,C4,B3,A3,B3]; - var tLn=[2,1,2,3,2,1,2,3,2,1,2,0,1,3,0,3]; - var ans=[E4,G4,B4,E5,B4,G4,E4,B3]; - var aLn=[2,3,0,2,0,3,2,3]; + var theme=[E4,Eb4,E4,B3,D4,C4,A3,C4,E4,A4,B3,E4,Ab4,B4,A4]; + var tLn=[2,1,2,3,0,2,0,2,2,1,3,2,1,0,1]; + var ans=[E4,Eb4,E4,B3,D4,C4,A3]; + var aLn=[2,1,2,3,0,2,0]; for(var rep=0;rep<5;rep++){ var v=0.2+rep*0.08; var inst=rep<2?'woodwind':rep<4?'strings':'brass'; @@ -2593,8 +2653,8 @@ const CLASSICAL_PIECES=(function(){ }); t+=0.4; } - [E4,G4,B4,E5].forEach(function(f){bg.push({t:t,f:f,d:2.0,i:'strings',v:0.5});}); - bg.push({t:t,f:E3,d:1.5,i:'bass',v:0.4});mel.push({t:t,l:4}); + [E3,B3,E4,Ab4,B4].forEach(function(f){bg.push({t:t,f:f,d:2.0,i:'strings',v:0.5});}); + bg.push({t:t,f:E3/2,d:1.5,i:'bass',v:0.4});mel.push({t:t,l:4}); return {n:"Dance of the Sugar Plum Fairy",composer:"Tchaikovsky",bpm:120,duration:Math.ceil(t+2.5),isClassical:true,bg:bg,melody:mel}; })(); @@ -2876,8 +2936,8 @@ const CLASSICAL_PIECES=(function(){ var bg=[],mel=[],t=0,q=0.35; var motif=[E4,Eb4,E4,Eb4,E4,B3,D4,C4,A3]; var mLn=[2,1,2,1,2,3,0,2,0]; - var ph2=[C4,E4,A4,B4,E4,C5,B4,A4]; - var p2Ln=[1,2,0,3,2,0,3,0]; + var ph2=[C4,E4,A4,B4,E4,Ab4,B4,A4]; + var p2Ln=[1,2,0,3,2,1,3,0]; for(var rep=0;rep<5;rep++){ var v=0.2+rep*0.08; var inst=rep<2?'woodwind':rep<3?'strings':'brass'; @@ -2909,8 +2969,9 @@ const CLASSICAL_PIECES=(function(){ var canon=(function(){ var bg=[],mel=[],t=0,q=0.55; var bassLine=[D3,A3,B3,Gb3,G3,D3,G3,A3]; - var melody2=[A4,Gb4,G4,A4,Gb4,D4,Gb4,G4,A4,B4,G4,A4,Gb4,D4,E4,Gb4]; - var m2Ln=[1,2,3,1,2,0,2,3,1,0,3,1,2,0,1,2]; + // Real Pachelbel violin melody: F#-E-D-C#-B-A-B-C# (var 1) then D-C#-B-A-G-F#-G-A (var 2) + var melody2=[Gb4,E4,D4,Db4,B3,A3,B3,Db4,D4,Db4,B3,A3,G3,Gb3,G3,A3]; + var m2Ln=[2,1,0,1,3,0,3,1,0,1,3,0,3,2,3,0]; for(var rep=0;rep<4;rep++){ var v=0.2+rep*0.08; bassLine.forEach(function(f,i){ From 3bded9ad53c1fc3f53c881ef9a358c42710e331b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 03:13:11 +0000 Subject: [PATCH 03/22] Fix 4 Singalong melodies for musical accuracy - Amazing Grace: corrected to proper C major pentatonic melody (G-C-E-C-E-D) - Auld Lang Syne: fixed second half to D5-D5-C5-A4, proper F major melody - Scarborough Fair: changed Bb4 to B4 (D Dorian mode has B natural) - My Bonnie: complete rewrite with characteristic leaping melody and chorus https://claude.ai/code/session_016nhMjrAqwWXKKgBm6EQuX1 --- index.html | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/index.html b/index.html index 9b42c93..fc1c2ec 100644 --- a/index.html +++ b/index.html @@ -3701,14 +3701,14 @@ const SINGALONG_PIECES=(function(){ [1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,3], 4,E4); var amazing=pub("Amazing Grace","J. Newton (1779)",80, - [G4,C5,E5,E5,D5,C5,A4,G4,G4,C5,E5,E5,D5,E5,E5,G5,G5,E5,C5,C5,A4,G4,G4,C5,E5,E5,D5,C5], - [3,0,2,2,1,0,0,3,3,0,2,2,1,2,2,3,3,2,0,0,0,3,3,0,2,2,1,0], - [1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,2,1,2,1,2,1,2,1,2,1,2,1,4], + [G4,C5,E5,C5,E5,D5,C5,A4,G4,G4,C5,E5,C5,E5,D5,G5,G5,E5,C5,C5,A4,G4,G4,C5,E5,C5,E5,D5,C5], + [3,0,2,0,2,1,0,0,3,3,0,2,0,2,1,3,3,2,0,0,0,3,3,0,2,0,2,1,0], + [1,2,1,1,2,2,1,2,2,1,2,1,1,2,4,2,1,2,1,2,1,2,1,2,1,1,2,2,4], 4,C4); var auld=pub("Auld Lang Syne","R. Burns (1788)",95, - [C4,F4,F4,F4,A4,G4,F4,G4,A4,F4,F4,A4,C5,D5,C5,D5,C5,D5,C5,A4,F4,G4,A4,G4,F4,G4], - [0,1,1,1,0,3,1,3,0,1,1,0,0,1,0,1,0,1,0,0,1,3,0,3,1,3], - [1,2,1,1,1,2,1,1,1,2,1,1,1,2,1,2,1,1,1,2,1,1,1,2,1,4], + [C4,F4,F4,F4,A4,G4,F4,G4,A4,F4,F4,A4,C5,D5,D5,D5,C5,A4,F4,F4,G4,A4,G4,F4,D4,C4], + [0,1,1,1,0,3,1,3,0,1,1,0,0,1,1,1,0,0,1,1,3,0,3,1,1,0], + [1,2,1,1,1,2,1,1,1,2,1,1,1,4,1,1,1,2,1,1,1,2,1,2,1,4], 4,F4); var saints=pub("When the Saints Go Marching In","Spiritual (Trad.)",120, [C4,E4,F4,G4,C4,E4,F4,G4,C4,E4,F4,G4,E4,C4,E4,D4,E4,E4,D4,C4,C4,E4,G4,G4,F4,E4,F4,G4,E4,C4,D4,C4], @@ -3721,15 +3721,15 @@ const SINGALONG_PIECES=(function(){ [1,1,1,2,1,1,1,2,1,1,2,1,1,1,2,1,1,1,1,1,1,2,1,1,2,1,1,1,1,1,4], 4,C4); var scarborough=pub("Scarborough Fair","English (Medieval)",85, - [D4,D4,A4,A4,D5,D5,C5,D5,E5,D5,C5,A4,Bb4,A4,G4,B4,A4,G4,F4,F4,G4,A4,F4,E4,D4,E4,F4,D4,D4,F4,G4,A4,G4,F4,E4,D4], - [0,0,0,0,1,1,0,1,2,1,0,0,2,0,3,3,0,3,1,1,3,0,1,2,0,2,1,0,0,1,3,0,3,1,2,0], + [D4,D4,A4,A4,D5,D5,C5,D5,E5,D5,C5,A4,B4,A4,G4,B4,A4,G4,F4,F4,G4,A4,F4,E4,D4,E4,F4,D4,D4,F4,G4,A4,G4,F4,E4,D4], + [0,0,0,0,1,1,0,1,2,1,0,0,3,0,3,3,0,3,1,1,3,0,1,2,0,2,1,0,0,1,3,0,3,1,2,0], [3,3,2,1,3,1,1,1,3,2,1,1,1,1,2,1,3,3,1,2,1,1,1,1,2,1,3,3,1,1,1,3,1,1,1,4], 4,D4); var bonnie=pub("My Bonnie Lies Over the Ocean","Scottish (1881)",120, - [G4,F4,E4,F4,G4,A4,G4,F4,E4,C4,D4,E4,F4,G4,F4,E4,F4,G4,A4,G4,F4,E4,D4,C4,E4,G4,E4,C4], - [3,1,2,1,3,0,3,1,2,0,1,2,1,3,1,2,1,3,0,3,1,2,1,0,2,3,2,0], - [1,1,1,1,1,2,1,1,1,2,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,2,1,4], - 5,C4); + [G4,C5,C5,D5,E5,E5,D5,C5,A4,G4,C5,C5,D5,E5,G5,E5,D5,G4,C5,C5,D5,E5,E5,D5,C5,A4,A4,G4,F4,E4,F4,G4,E4,C4,E5,G5,G5,G5,E5,C5,C5,D5,E5,G5,G5,G5,F5,E5,D5,C5], + [3,0,0,1,2,2,1,0,0,3,0,0,1,2,3,2,1,3,0,0,1,2,2,1,0,0,0,3,1,2,1,3,2,0,2,3,3,3,2,0,0,1,2,3,3,3,1,2,1,0], + [1,1,1,1,1,2,1,1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,2,1,1,2,1,1,1,1,1,2,1,4,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,4], + 4,C4); // ── Wellerman (accurate melody with driving stomp beat) ── var wellerman=(function(){ var bg=[],mel=[],t=0,q=0.32; From c7f800f321b1a7a0699caa621425f8ed6cfdbf37 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 03:19:50 +0000 Subject: [PATCH 04/22] Update README to include Prime genre and correct counts - Add Prime genre section (6 beginner songs: Twinkle Twinkle, Mary Had a Little Lamb, Happy Birthday, Chopsticks, Lavender's Blue, Shortnin' Bread) - Update genre count from 16 to 17 - Update synth piece count from 91 to 97 - Update line count from ~3000 to ~4500 https://claude.ai/code/session_01FNZw4curZbJp38HFUaPXwR --- README.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a8403ae..bc1ce63 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ Works with **keyboard**, **Wii Rock Band drums**, **Xbox/PS Rock Band drums**, * ## Features -- **16 Genres** across two modes: synth orchestra songs + drum beat patterns -- **91 synth pieces** with full synthesized orchestra background (68 minutes) +- **17 Genres** across two modes: synth orchestra songs + drum beat patterns +- **97 synth pieces** with full synthesized orchestra background - **120 drum patterns** across 8 genres - **Drums or Orchestra mode** — choose whether pad hits play drum sounds or the actual melody note - **Speed control** — slow down to 50% for practice or speed up to 150% @@ -39,6 +39,14 @@ Works with **keyboard**, **Wii Rock Band drums**, **Xbox/PS Rock Band drums**, * ## Song List +### Prime (6 songs) +- Twinkle Twinkle Little Star (Traditional, 1760s) +- Mary Had a Little Lamb (S.J. Hale, 1830) +- Happy Birthday (P.S. Hill, 1893) +- Chopsticks (Euphemia Allen, 1877) +- Lavender's Blue (English Traditional, 1670s) +- Shortnin' Bread (Traditional, 1900s) + ### Singalong (20 songs) - Drunken Sailor (Sea Shanty) - Wellerman (NZ Sea Shanty, 1860s) @@ -204,7 +212,7 @@ All sounds are generated in real-time using the Web Audio API — no audio files ## Tech - Pure vanilla JavaScript — no libraries, no build step, no server -- Single `index.html` file (~3000 lines) +- Single `index.html` file (~4500 lines) - Web Audio API for all sound synthesis - Canvas 2D for the note highway - Gamepad API for drum kit input From c5ac0971d14fbc3a583e0837e65eea2221b0829f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 03:22:14 +0000 Subject: [PATCH 05/22] Fix 6 melodies across Christmas, Folk, Spirituals, and World genres MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - O Christmas Tree: fixed Eb4→Eb5 (wrong octave in running passage) - Danny Boy: complete rewrite with soaring Londonderry Air melody up to E5 - Swing Low Sweet Chariot: fixed "Swing low" to descend (was ascending) - Michael Row the Boat Ashore: fixed ascending C-E-F-G-A for "row the boat" - Hava Nagila: replaced G naturals with Ab/G# for correct Freygish scale - O Sole Mio: rewrite with characteristic soaring Bb refrain https://claude.ai/code/session_016nhMjrAqwWXKKgBm6EQuX1 --- index.html | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/index.html b/index.html index fc1c2ec..accb8fb 100644 --- a/index.html +++ b/index.html @@ -3569,10 +3569,10 @@ const FOLK_PIECES=(function(){ // ── Danny Boy ── var dannyboy=folk("Danny Boy","Irish Traditional (1910s)",72, - [C4,E4,F4,G4,A4,G4,F4,E4,C4,D4,E4,F4,E4,D4,C4,E4,F4,G4,A4,C5,A4,G4,F4,C4], - [0,2,1,3,0,3,1,2,0,1,2,1,2,1,0,2,1,3,0,0,0,3,1,0], - [2,1,1,2,2,1,1,2,2,1,2,1,2,2,2,1,1,2,2,2,1,1,2,3], - 4,C4); + [C4,E4,F4,G4,A4,G4,A4,C5,B4,A4,G4,F4,G4,C4,E4,F4,G4,A4,G4,A4,C5,D5,C5,A4,G4,A4,A4,C5,D5,E5,D5,C5,A4,C5,B4,A4,G4,A4,G4,E4,C4,E4,F4,G4,A4,G4,F4,E4,C4], + [0,2,1,3,0,3,0,0,3,0,3,1,3,0,2,1,3,0,3,0,0,1,0,0,3,0,0,0,1,2,1,0,0,0,3,0,3,0,3,2,0,2,1,3,0,3,1,2,0], + [2,1,1,2,1,1,1,2,1,1,1,2,3,2,1,1,2,1,1,1,2,1,1,1,2,3,1,1,2,2,1,1,1,1,1,1,2,1,1,1,2,1,1,2,1,1,1,2,4], + 3,C4); return [ohsusanna,greensleeves,camptown,redriver,homerange,yankee,turkey,dannyboy]; })(); @@ -3582,7 +3582,7 @@ const FOLK_PIECES=(function(){ const CHRISTMAS_PIECES=(function(){ var C3=NT.C3,D3=NT.D3,E3=NT.E3,F3=NT.F3,G3=NT.G3,A3=NT.A3,B3=NT.B3, C4=NT.C4,D4=NT.D4,Eb4=NT.Eb4,E4=NT.E4,F4=NT.F4,G4=NT.G4,A4=NT.A4,Bb4=NT.Bb4,B4=NT.B4, - C5=NT.C5,D5=NT.D5,E5=NT.E5,F5=NT.F5,G5=NT.G5; + C5=NT.C5,D5=NT.D5,Eb5=NT.Eb5,E5=NT.E5,F5=NT.F5,G5=NT.G5; function carol(name,origin,bpm,theme,lanes,durations,passes,root){ var bg=[],mel=[],t=0,q=0.25; for(var rep=0;rep Date: Tue, 31 Mar 2026 03:27:44 +0000 Subject: [PATCH 06/22] Make Prime easier and expand Christmas to 20 carols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prime genre changes: - Reduced tempos: Twinkle 100→75, Mary 110→80, Birthday 100→75, Chopsticks 140→95, Lavender 110→80, Shortnin' 130→95 - Reduced passes from 3-4 to 3 across the board - Added longer held notes in durations for more breathing room - Simplified Chopsticks from 48 to 36 notes - Trimmed Twinkle/Mary/Lavender note counts Christmas genre expansion (10→20 carols): - O Come All Ye Faithful, God Rest Ye Merry Gentlemen, What Child Is This, Angels We Have Heard on High, O Holy Night, Rudolph the Red-Nosed Reindeer, Frosty the Snowman, Winter Wonderland, Good King Wenceslas, We Three Kings https://claude.ai/code/session_016nhMjrAqwWXKKgBm6EQuX1 --- index.html | 134 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 102 insertions(+), 32 deletions(-) diff --git a/index.html b/index.html index accb8fb..8619f58 100644 --- a/index.html +++ b/index.html @@ -3446,47 +3446,47 @@ const PRIME_PIECES=(function(){ return {n:name,composer:origin,bpm:bpm,duration:Math.ceil(t+2.5),isClassical:true,bg:bg,melody:mel}; } - // ── Twinkle Twinkle Little Star (C major, from lead sheet) ── - var twinkle=primer("Twinkle Twinkle Little Star","Traditional (1760s)",100, - [C4,C4,G4,G4,A4,A4,G4,F4,F4,E4,E4,D4,D4,C4,G4,G4,F4,F4,E4,E4,D4,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,3,3,1,1,2,2,1,0,0,3,3,0,0,3,1,1,2,2,1,1,0], - [1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,1,1,1,3], + // ── Twinkle Twinkle Little Star (C major, slow & simple) ── + var twinkle=primer("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], + [1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,4], 3,C4); - // ── Mary Had a Little Lamb (C major, from lead sheet) ── - var mary=primer("Mary Had a Little Lamb","S.J. Hale (1830)",110, - [E4,D4,C4,D4,E4,E4,E4,D4,D4,D4,E4,G4,G4,E4,D4,C4,D4,E4,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,2,1,1,2,1,0], - [1,1,1,1,1,1,2,1,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,3], - 4,C4); + // ── Mary Had a Little Lamb (C major, slow & simple) ── + var mary=primer("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], + [1,1,1,1,1,1,3,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,4], + 3,C4); - // ── Happy Birthday (C major, from lead sheet in D transposed) ── - var birthday=primer("Happy Birthday","P.S. Hill (1893)",100, + // ── Happy Birthday (C major, slow & simple) ── + var birthday=primer("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,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,3], - 4,C4); - - // ── Chopsticks (C major, from lead sheet — alternating dyad notes) ── - var chopsticks=primer("Chopsticks","Euphemia Allen (1877)",140, - [F4,G4,F4,G4,F4,G4,E4,G4,E4,G4,E4,G4,D4,F4,D4,F4,D4,F4,C4,E4,C4,E4,C4,E4,F4,G4,F4,G4,F4,G4,E4,G4,E4,G4,E4,G4,D4,F4,D4,F4,D4,F4,C4,E4,C4,E4,C4,E4], - [1,3,1,3,1,3,2,3,2,3,2,3,1,1,1,1,1,1,0,2,0,2,0,2,1,3,1,3,1,3,2,3,2,3,2,3,1,1,1,1,1,1,0,2,0,2,0,2], - [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3], + [1,1,2,2,2,3,1,1,2,2,2,3,1,1,2,1,1,1,2,1,1,1,1,2,4], 3,C4); - // ── Lavender's Blue (C major, from lead sheet in D transposed) ── - var lavender=primer("Lavender's Blue","English Traditional (1670s)",110, - [E4,E4,E4,D4,E4,F4,G4,G4,G4,G4,A4,G4,F4,F4,F4,E4,D4,E4,F4,E4,E4,E4,D4,E4,F4,G4,G4,G4,A4,G4,F4,E4], - [2,2,2,1,2,1,3,3,3,3,0,3,1,1,1,2,1,2,1,2,2,2,1,2,1,3,3,3,0,3,1,2], - [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,3], - 4,C4); + // ── Chopsticks (C major, simplified alternating pattern) ── + var chopsticks=primer("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], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4], + 3,C4); - // ── Shortnin' Bread (C major, from lead sheet in A transposed) ── - var shortnin=primer("Shortnin' Bread","Traditional (1900s)",130, + // ── Lavender's Blue (C major, gentle waltz feel) ── + var lavender=primer("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], + [1,1,1,1,1,1,1,1,1,2,1,1,1,3,1,1,1,1,1,1,1,1,1,1,4], + 3,C4); + + // ── Shortnin' Bread (C major, bouncy but approachable) ── + var shortnin=primer("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], - [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3], - 4,C4); + [1,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,4], + 3,C4); return [twinkle,mary,birthday,chopsticks,lavender,shortnin]; })(); @@ -3653,7 +3653,77 @@ const CHRISTMAS_PIECES=(function(){ [0,1,1,2,1,0,0,3,0,0,0,3,0,0,0,3,0,2,3,0,2,0,0,1,3,2,0,3,1], [1,2,1,1,2,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,4], 4,F4); - return [jingle,silent,deck,wish,ocometree,firstnoel,joy,away,twelve,hark]; + // ── O Come All Ye Faithful (G major → transposed to C) ── + var ocome=carol("O Come All Ye Faithful","J.F. Wade (1743)",100, + [C4,C4,G4,C4,D4,G4,E4,D4,E4,F4,E4,D4,C4,B4,A4,B4,C5,B4,A4,G4,A4,E4,F4,E4,D4,E4,F4,D4,C4,D4,C4,Bb4,A4,G4,F4,E4,F4,E4,D4,C4], + [0,0,3,0,1,3,2,1,2,1,2,1,0,3,0,3,0,3,0,3,0,2,1,2,1,2,1,1,0,1,0,2,0,3,1,2,1,2,1,0], + [2,1,2,1,2,3,1,1,1,1,1,1,2,1,1,1,2,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,4], + 3,C4); + + // ── God Rest Ye Merry Gentlemen (E minor / A minor) ── + var godrest=carol("God Rest Ye Merry Gentlemen","English (1500s)",120, + [E4,E4,E4,D4,C4,D4,E4,F4,G4,A4,Bb4,A4,G4,F4,E4,D4,C4,D4,E4,F4,E4,D4,C4,B3,C4,G4,G4,F4,E4,F4,G4,A4,Bb4,A4,G4,F4,E4], + [2,2,2,1,0,1,2,1,3,0,2,0,3,1,2,1,0,1,2,1,2,1,0,3,0,3,3,1,2,1,3,0,2,0,3,1,2], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,4], + 4,E4); + + // ── What Child Is This (Greensleeves melody as a carol) ── + var whatchild=carol("What Child Is This","English (1865)",95, + [E4,A4,B4,C5,B4,A4,G4,E4,D4,E4,F4,E4,D4,C4,E4,A4,B4,C5,B4,A4,Ab4,B4,C5,A4,A4], + [2,0,3,0,3,0,3,2,1,2,1,2,1,0,2,0,3,0,3,0,1,3,0,0,0], + [2,2,2,1,2,2,2,1,2,1,2,1,2,3,2,2,2,1,2,1,1,1,2,1,4], + 4,A4); + + // ── Angels We Have Heard on High ── + var angels=carol("Angels We Have Heard on High","French (1862)",110, + [E4,E4,E4,E4,F4,D4,E4,F4,E4,E4,F4,D4,E4,F4,G4,F4,E4,D4,E4,C4,D4,E4,F4,D4,E4,F4,G4,F4,E4,D4,E4,C4,C4], + [2,2,2,2,1,1,2,1,2,2,1,1,2,1,3,1,2,1,2,0,1,2,1,1,2,1,3,1,2,1,2,0,0], + [1,1,1,1,1,2,1,1,1,1,1,2,1,1,2,1,1,1,1,2,1,1,1,2,1,1,2,1,1,1,1,2,4], + 4,C4); + + // ── O Holy Night (in C major) ── + var oholynight=carol("O Holy Night","A. Adam (1847)",72, + [C4,F4,F4,F4,E4,F4,A4,A4,G4,F4,F4,Bb4,A4,G4,F4,G4,A4,G4,F4,E4,F4,C5,C5,Bb4,A4,G4,A4,Bb4,A4,G4,F4], + [0,1,1,1,2,1,0,0,3,1,1,2,0,3,1,3,0,3,1,2,1,0,0,2,0,3,0,2,0,3,1], + [2,2,1,1,1,1,2,1,1,2,1,2,1,1,1,1,2,1,1,1,3,2,1,1,1,1,1,1,1,1,4], + 3,F4); + + // ── Rudolph the Red-Nosed Reindeer (in C major) ── + var rudolph=carol("Rudolph the Red-Nosed Reindeer","J. Marks (1949)",130, + [G4,A4,G4,E4,C5,A4,G4,G4,A4,G4,A4,G4,C5,B4,F4,A4,G4,F4,D4,E4,F4,D4,G4,A4,G4,E4,C5,A4,G4,G4,A4,G4,A4,G4,A4,D5,C5], + [3,0,3,2,0,0,3,3,0,3,0,3,0,3,1,0,3,1,1,2,1,1,3,0,3,2,0,0,3,3,0,3,0,3,0,1,0], + [1,1,1,1,2,1,2,1,1,1,1,1,2,3,1,1,1,1,1,1,1,3,1,1,1,1,2,1,2,1,1,1,1,1,1,1,4], + 3,C4); + + // ── Frosty the Snowman (in C major) ── + var frosty=carol("Frosty the Snowman","S. Nelson (1950)",125, + [G4,E4,F4,G4,C5,B4,A4,G4,A4,G4,F4,E4,F4,A4,G4,F4,E4,D4,C4,C4,G4,E4,F4,G4,C5,B4,A4,G4,A4,G4,F4,E4,D4,C4], + [3,2,1,3,0,3,0,3,0,3,1,2,1,0,3,1,2,1,0,0,3,2,1,3,0,3,0,3,0,3,1,2,1,0], + [1,1,1,2,1,1,1,1,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,4], + 3,C4); + + // ── Winter Wonderland (in C major) ── + var winter=carol("Winter Wonderland","F. Bernard (1934)",120, + [E4,F4,G4,G4,A4,G4,F4,E4,D4,E4,F4,F4,G4,F4,E4,D4,C4,E4,F4,G4,G4,A4,G4,F4,E4,D4,E4,F4,F4,G4,F4,E4,D4,C4], + [2,1,3,3,0,3,1,2,1,2,1,1,3,1,2,1,0,2,1,3,3,0,3,1,2,1,2,1,1,3,1,2,1,0], + [1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,3,1,1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,4], + 3,C4); + + // ── Good King Wenceslas (in F major) ── + var wenceslas=carol("Good King Wenceslas","Finnish (1582)",110, + [F4,F4,F4,G4,F4,F4,C4,D4,E4,F4,F4,G4,F4,F4,C4,C5,Bb4,A4,G4,A4,Bb4,A4,G4,F4,G4,A4,Bb4,C5,Bb4,A4,G4,F4], + [1,1,1,3,1,1,0,1,2,1,1,3,1,1,0,0,2,0,3,0,2,0,3,1,3,0,2,0,2,0,3,1], + [1,1,1,1,1,1,2,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,2,1,1,1,2,1,1,1,4], + 4,F4); + + // ── We Three Kings (E minor) ── + var threekings=carol("We Three Kings","J.H. Hopkins Jr. (1857)",105, + [B4,A4,G4,A4,B4,B4,B4,A4,G4,A4,B4,A4,G4,F4,E4,E4,B4,B4,C5,D5,D5,C5,B4,A4,B4,C5,B4,A4,G4,A4,G4,E4], + [3,0,3,0,3,3,3,0,3,0,3,0,3,1,2,2,3,3,0,1,1,0,3,0,3,0,3,0,3,0,3,2], + [2,1,2,1,1,1,2,1,2,1,1,1,1,1,2,3,2,1,1,2,1,1,2,1,1,1,1,1,1,1,1,4], + 4,E4); + + return [jingle,silent,deck,wish,ocometree,firstnoel,joy,away,twelve,hark,ocome,godrest,whatchild,angels,oholynight,rudolph,frosty,winter,wenceslas,threekings]; })(); // ── SINGALONG (campfire, sea shanties, pub songs) ── From 051cb20cf026b0a2b0d01606439e61e7af9a5263 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 03:35:47 +0000 Subject: [PATCH 07/22] Add trademark disclaimer for Rock Band, Guitar Hero, and console names https://claude.ai/code/session_01FNZw4curZbJp38HFUaPXwR --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index bc1ce63..e6c73ef 100644 --- a/README.md +++ b/README.md @@ -222,3 +222,7 @@ All sounds are generated in real-time using the Web Audio API — no audio files ## License [MIT](LICENSE) + +## Disclaimer + +Rock Band is a trademark of Harmonix Music Systems. Guitar Hero is a trademark of Activision Publishing. Wii is a trademark of Nintendo. Xbox is a trademark of Microsoft. PlayStation is a trademark of Sony Interactive Entertainment. This project is not affiliated with, endorsed by, or connected to any of these companies. All trademarks are the property of their respective owners and are used here solely for hardware compatibility reference. From 1aab788c24273d7b16bca8a588d6678ab43f436f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 03:38:01 +0000 Subject: [PATCH 08/22] Add Nursery Rhymes & Ragtime genres, add Simple/Full note density toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New genres: - Nursery Rhymes (10 songs): Baa Baa Black Sheep, London Bridge, Old MacDonald, Row Row Row Your Boat, Three Blind Mice, Itsy Bitsy Spider, Pop Goes the Weasel, Hot Cross Buns, Jack and Jill, Humpty Dumpty — all at slow tempos (65-85 BPM) - Ragtime (8 songs): The Entertainer, Maple Leaf Rag, The Easy Winners, Elite Syncopations, Solace, Peacherine Rag, The Cascades, Pineapple Rag — all Scott Joplin (public domain) Simple/Full mode: - Toggle in Active Pads card switches between Full and Simple density - Simple mode enforces 350ms minimum gap between notes, removing rapid passages while keeping the melody recognizable - Works on both synth genres (classical/folk/etc) and rhythm patterns - Lightweight: just a filter on the note array, no piece data changes https://claude.ai/code/session_016nhMjrAqwWXKKgBm6EQuX1 --- index.html | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 204 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 8619f58..e9e175f 100644 --- a/index.html +++ b/index.html @@ -98,6 +98,12 @@ canvas{display:block;}

Active Pads

Toggle which pads show notes. Inactive pads still make sound when hit.

+
+ Note density: + + + Fewer notes for beginners +
@@ -167,8 +168,10 @@ canvas{display:block;} - +
+ +
@@ -4359,8 +4362,9 @@ function confirmReset(){ if(ans===null)return; if(parseInt(ans)===a+b){ localStorage.removeItem("drgame5");localStorage.removeItem("drgameSettings"); - localStorage.removeItem("drgameGpMap");localStorage.removeItem("drgameHidden");localStorage.removeItem("drgameHiddenSongs"); - savedScores=[];hiddenGenres=[];hiddenSongs={};gpMap={0:2,1:3,2:0,3:1,4:4,8:4}; + localStorage.removeItem("drgameGpMap");localStorage.removeItem("drgameKeyMap");localStorage.removeItem("drgameHidden");localStorage.removeItem("drgameHiddenSongs"); + savedScores=[];hiddenGenres=[];hiddenSongs={};gpMap={0:2,1:3,2:0,3:1,4:4,5:5,6:6,7:7,8:4};customKeyMap=null; + LANES[0].key="f";LANES[1].key="g";LANES[2].key="h";LANES[3].key="j";LANES[4].key=" ";LANES[5].key="d";LANES[6].key="k";LANES[7].key="l"; refreshMiniLB();resetSettings();buildMenu(); alert("All data cleared!"); } else {alert("Incorrect — data NOT cleared.");} @@ -4878,19 +4882,87 @@ function handleRemapButton(bi){ return true; } +// ── KEYBOARD REMAP ──────────────────────────────────── +var keyRemapping=false,keyRemapStep=0,keyRemapResult={}; +var customKeyMap=JSON.parse(localStorage.getItem("drgameKeyMap")||"null"); +// Apply saved key mappings on load +if(customKeyMap){ + LANES.forEach(function(ln,i){if(customKeyMap[i]!==undefined)ln.key=customKeyMap[i];}); +} +function startKeyRemap(){ + keyRemapping=true;keyRemapStep=0;keyRemapResult={}; + document.getElementById("keyremap-overlay").classList.add("show"); + showKeyRemapStep(); +} +function cancelKeyRemap(){ + keyRemapping=false;document.getElementById("keyremap-overlay").classList.remove("show"); +} +function showKeyRemapStep(){ + if(keyRemapStep>=LANES.length){ + // Done — apply and save + LANES.forEach(function(ln,i){if(keyRemapResult[i]!==undefined)ln.key=keyRemapResult[i];}); + var map={};LANES.forEach(function(ln,i){map[i]=ln.key;}); + localStorage.setItem("drgameKeyMap",JSON.stringify(map)); + customKeyMap=map; + keyRemapping=false; + document.getElementById("keyremap-overlay").classList.remove("show"); + buildPadToggles(); + return; + } + var ln=LANES[keyRemapStep]; + document.getElementById("keyremap-prompt").innerHTML="Press key for "+ln.label.toUpperCase()+""; + document.getElementById("keyremap-status").textContent="Step "+(keyRemapStep+1)+" of "+LANES.length+" (press any key)"; +} +var keyRemapCooldown=false; +window.addEventListener("keydown",function(e){ + if(keyRemapping){ + if(e.key==="Escape"){cancelKeyRemap();e.preventDefault();return;} + if(keyRemapCooldown)return; + e.preventDefault(); + keyRemapResult[keyRemapStep]=e.key===" "?" ":e.key.toLowerCase(); + keyRemapStep++; + keyRemapCooldown=true; + setTimeout(function(){keyRemapCooldown=false;},300); + showKeyRemapStep(); + return; + } +},true); + // ── INPUT ────────────────────────────────────────────── window.addEventListener("keydown",e=>{ + if(keyRemapping)return; if(e.key==="Escape"){e.preventDefault();togglePause();return;} if(paused)return; const i=LANES.findIndex(l=>l.key===e.key.toLowerCase()||(l.key===" "&&e.key===" ")); if(i>=0){e.preventDefault();triggerPad(i);} }); + +// ── GAMEPAD AUTO-DETECT ────────────────────────────── +var gpAutoDetected=false; +function autoDetectGamepad(gp){ + if(gpAutoDetected)return; + gpAutoDetected=true; + var nButtons=gp.buttons.length; + // Enable lanes based on detected button count (5 = standard Rock Band, more = extended kit) + var lanesToEnable=Math.min(nButtons,LANES.length); + // Always enable at least the first 5 (standard kit) if we have 5+ buttons + if(lanesToEnable>=5){ + for(var i=0;i<5;i++)activePads[i]=true; + // Enable extra lanes for extended kits (6+ buttons) + for(var j=5;j{ if(btn.pressed&&!prevBtns[bi]){ From 5b0100270789be9954842bdfe2ec065dcd374938 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 04:12:28 +0000 Subject: [PATCH 16/22] Remove Prime genre (merged into Nursery Rhymes), add missing genre icons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove "Prime":PRIME_PIECES from SYNTH_GENRES (fixes ReferenceError crash) - Add Nursery Rhymes 🧒 and Ragtime 🎹 icons to synthIcons map https://claude.ai/code/session_016nhMjrAqwWXKKgBm6EQuX1 --- index.html | 113 ++++++++++++++++++----------------------------------- 1 file changed, 38 insertions(+), 75 deletions(-) diff --git a/index.html b/index.html index 4bbb0ac..df7caf3 100644 --- a/index.html +++ b/index.html @@ -598,7 +598,7 @@ const GENRES={ }; // ── CLASSICAL MODE ──────────────────────────────────── -const NT={C3:130.81,D3:146.83,Eb3:155.56,E3:164.81,F3:174.61,G3:196.00,Ab3:207.65,A3:220.00,Bb3:233.08,B3:246.94,C4:261.63,D4:293.66,Eb4:311.13,E4:329.63,F4:349.23,G4:392.00,Ab4:415.30,A4:440.00,Bb4:466.16,B4:493.88,C5:523.25,D5:587.33,Eb5:622.25,E5:659.25,F5:698.46,G5:783.99,A5:880.00,Gb3:185.00,Db4:277.18,Gb4:369.99,Db5:554.37,C6:1046.50}; +const NT={C3:130.81,D3:146.83,Eb3:155.56,E3:164.81,F3:174.61,G3:196.00,Ab3:207.65,A3:220.00,Bb3:233.08,B3:246.94,C4:261.63,D4:293.66,Eb4:311.13,E4:329.63,F4:349.23,G4:392.00,Ab4:415.30,A4:440.00,Bb4:466.16,B4:493.88,C5:523.25,D5:587.33,Eb5:622.25,E5:659.25,F5:698.46,G5:783.99,A5:880.00,Ab5:830.61,Gb3:185.00,Db4:277.18,Gb4:369.99,Db5:554.37,C6:1046.50}; function playSynth(ac,freq,t,dur,inst,vol,arr){ if(t1)bg.push({t:t,f:f/2,d:d*0.85,i:'bass',v:v*0.3}); - mel.push({t:t,l:lanes[i]});t+=d; - }); - t+=0.4; - } - var r=root||theme[0]; - [r,r*5/4,r*3/2,r*2].forEach(function(f){bg.push({t:t,f:f,d:2.0,i:'strings',v:0.45});}); - bg.push({t:t,f:r/2,d:1.5,i:'timpani',v:0.5});mel.push({t:t,l:4}); - return {n:name,composer:origin,bpm:bpm,duration:Math.ceil(t+2.5),isClassical:true,bg:bg,melody:mel}; - } - - // ── Twinkle Twinkle Little Star (C major, slow & simple) ── - var twinkle=primer("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], - [1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,4], - 3,C4); - - // ── Mary Had a Little Lamb (C major, slow & simple) ── - var mary=primer("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], - [1,1,1,1,1,1,3,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,4], - 3,C4); - - // ── Happy Birthday (C major, slow & simple) ── - var birthday=primer("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,3,1,1,2,2,2,3,1,1,2,1,1,1,2,1,1,1,1,2,4], - 3,C4); - - // ── Chopsticks (C major, simplified alternating pattern) ── - var chopsticks=primer("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], - [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4], - 3,C4); - - // ── Lavender's Blue (C major, gentle waltz feel) ── - var lavender=primer("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], - [1,1,1,1,1,1,1,1,1,2,1,1,1,3,1,1,1,1,1,1,1,1,1,1,4], - 3,C4); - - // ── Shortnin' Bread (C major, bouncy but approachable) ── - var shortnin=primer("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], - [1,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,4], - 3,C4); - - return [twinkle,mary,birthday,chopsticks,lavender,shortnin]; -})(); - // ── FOLK (public domain traditional songs) ── const FOLK_PIECES=(function(){ var C3=NT.C3,D3=NT.D3,E3=NT.E3,F3=NT.F3,G3=NT.G3,Ab3=NT.Ab3,A3=NT.A3,B3=NT.B3, @@ -3595,7 +3527,7 @@ const FOLK_PIECES=(function(){ // ── CHRISTMAS (public domain carols) ── const CHRISTMAS_PIECES=(function(){ var C3=NT.C3,D3=NT.D3,E3=NT.E3,F3=NT.F3,G3=NT.G3,A3=NT.A3,B3=NT.B3, - C4=NT.C4,D4=NT.D4,Eb4=NT.Eb4,E4=NT.E4,F4=NT.F4,G4=NT.G4,A4=NT.A4,Bb4=NT.Bb4,B4=NT.B4, + C4=NT.C4,D4=NT.D4,Eb4=NT.Eb4,E4=NT.E4,F4=NT.F4,G4=NT.G4,Ab4=NT.Ab4,A4=NT.A4,Bb4=NT.Bb4,B4=NT.B4, C5=NT.C5,D5=NT.D5,Eb5=NT.Eb5,E5=NT.E5,F5=NT.F5,G5=NT.G5; function carol(name,origin,bpm,theme,lanes,durations,passes,root){ var bg=[],mel=[],t=0,q=0.25; @@ -4075,7 +4007,7 @@ const WORLD_PIECES=(function(){ // ── NURSERY RHYMES (very simple, beginner-friendly) ── const NURSERY_PIECES=(function(){ - var C4=NT.C4,D4=NT.D4,E4=NT.E4,F4=NT.F4,G4=NT.G4,A4=NT.A4,B4=NT.B4, + var C4=NT.C4,D4=NT.D4,E4=NT.E4,F4=NT.F4,G4=NT.G4,A4=NT.A4,Bb4=NT.Bb4,B4=NT.B4, C5=NT.C5,D5=NT.D5,E5=NT.E5,G3=NT.G3,A3=NT.A3,B3=NT.B3; function rhyme(name,origin,bpm,theme,lanes,durations,passes,root){ var bg=[],mel=[],t=0,q=0.3; @@ -4155,7 +4087,38 @@ const NURSERY_PIECES=(function(){ [2,3,0,3,1,2,1,2,1,2,1,0,2,3,0,3,1,2,1,0], [1,1,2,1,1,1,2,1,1,1,1,2,1,1,2,1,1,1,1,4], 3,C4); - return [baa,london,macdonald,row,mice,spider,weasel,hotcross,jack,humpty]; + // ── 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], + [1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,4], + 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], + [1,1,1,1,1,1,3,1,1,3,1,1,3,1,1,1,1,1,1,1,1,1,1,1,4], + 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,3,1,1,2,2,2,3,1,1,2,1,1,1,2,1,1,1,1,2,4], + 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], + [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4], + 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], + [1,1,1,1,1,1,1,1,1,2,1,1,1,3,1,1,1,1,1,1,1,1,1,1,4], + 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], + [1,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,1,2,1,1,1,4], + 3,C4); + return [baa,london,macdonald,row,mice,spider,weasel,hotcross,jack,humpty,twinkle,mary,birthday,chopsticks,lavender,shortnin]; })(); // ── RAGTIME (Scott Joplin & contemporaries, all public domain) ── @@ -4244,7 +4207,7 @@ const RAGTIME_PIECES=(function(){ return [entertainer,maple,easyw,elite,solace,peacherine,cascades,pineapple]; })(); -var SYNTH_GENRES={"Prime":PRIME_PIECES,"Nursery Rhymes":NURSERY_PIECES,"Singalong":SINGALONG_PIECES,"Christmas":CHRISTMAS_PIECES,"Folk":FOLK_PIECES,"Spirituals":SPIRITUAL_PIECES,"World":WORLD_PIECES,"Ragtime":RAGTIME_PIECES,"Classical":CLASSICAL_PIECES,"Video Games":VIDEOGAME_PIECES,"Chiptune Originals":CHIPTUNE_PIECES}; +var SYNTH_GENRES={"Nursery Rhymes":NURSERY_PIECES,"Singalong":SINGALONG_PIECES,"Christmas":CHRISTMAS_PIECES,"Folk":FOLK_PIECES,"Spirituals":SPIRITUAL_PIECES,"World":WORLD_PIECES,"Ragtime":RAGTIME_PIECES,"Classical":CLASSICAL_PIECES,"Video Games":VIDEOGAME_PIECES,"Chiptune Originals":CHIPTUNE_PIECES}; function simplifyNotes(notes){ if(!simpleMode||notes.length<2)return notes; @@ -4387,7 +4350,7 @@ function updateHitModeVisibility(){ // ── MENU ─────────────────────────────────────────────── function buildMenu(){ const gt=document.getElementById("gtabs");gt.innerHTML=""; - var synthIcons={"Singalong":"\uD83C\uDFB5","Christmas":"\uD83C\uDF84","Folk":"\uD83C\uDFB6","Spirituals":"\uD83D\uDE4F","World":"\uD83C\uDF0D","Classical":"\uD83C\uDFBB","Video Games":"\uD83C\uDFAE","Chiptune Originals":"\uD83D\uDC7E"}; + var synthIcons={"Nursery Rhymes":"\uD83E\uDDD2","Singalong":"\uD83C\uDFB5","Christmas":"\uD83C\uDF84","Folk":"\uD83C\uDFB6","Spirituals":"\uD83D\uDE4F","World":"\uD83C\uDF0D","Ragtime":"\uD83C\uDFB9","Classical":"\uD83C\uDFBB","Video Games":"\uD83C\uDFAE","Chiptune Originals":"\uD83D\uDC7E"}; var allGenres=Object.keys(SYNTH_GENRES).concat(Object.keys(GENRES)); var anyHidden=hiddenGenres.length>0; allGenres.forEach(function(g){ From fd140761734e6558d474af4fb701c0a91d046761 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 04:22:40 +0000 Subject: [PATCH 17/22] Fix missing 'baa' variable in NURSERY_PIECES causing all genres to disappear MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The NURSERY_PIECES IIFE referenced 'baa' (Baa Baa Black Sheep) in its return array but the variable was never defined — it was lost during the Prime genre merge. This ReferenceError crashed the script on load, preventing all genre tabs and rhythm lists from rendering. https://claude.ai/code/session_01MhCcEPfX3JqAk8zmvLXZ1g --- index.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/index.html b/index.html index 22b0b46..780092a 100644 --- a/index.html +++ b/index.html @@ -4118,6 +4118,12 @@ const NURSERY_PIECES=(function(){ [2,3,0,3,1,2,1,2,1,2,1,0,2,3,0,3,1,2,1,0], [1,1,2,1,1,1,2,1,1,1,1,2,1,1,2,1,1,1,1,4], 3,C4); + // ── Baa Baa Black Sheep (same melody as Twinkle Twinkle) ── + var baa=rhyme("Baa Baa Black Sheep","English (1731)",80, + [C4,C4,G4,G4,A4,A4,A4,G4,F4,F4,E4,E4,D4,D4,C4,G4,G4,G4,F4,F4,F4,E4,E4,E4,D4,D4,D4,C4], + [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], + [1,1,1,1,1,1,1,3,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,4], + 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], From 2c67ca3b7c353d77a7bfb9df9669c3d5c52a3d31 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 11:22:41 +0000 Subject: [PATCH 18/22] Fix wrong melodies across multiple synth genres MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Classical: - Hall of the Mountain King: transpose from A minor to correct B minor key - Toccata & Fugue: extend from 39s to 74s with full toccata continuation - Swan Lake: transpose to B minor, fix melody contour to use repeating ascending motif - Hungarian Dance No. 5: rewrite themes in D minor with correct melody - Dance of the Sugar Plum Fairy: replace Für Elise melody with actual Nutcracker celesta theme Christmas: - God Rest Ye Merry Gentlemen: fix F natural→F#(Gb4) and Bb→B for correct E minor key - Angels We Have Heard on High: rewrite to correct F major melody with Gloria melisma Singalong: - Amazing Grace: fix G5 (too high) to E5, correct melody peak - My Bonnie Lies Over the Ocean: fix G5 (too high) to E5, correct chorus range https://claude.ai/code/session_01MhCcEPfX3JqAk8zmvLXZ1g --- index.html | 164 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 48 deletions(-) diff --git a/index.html b/index.html index 780092a..cb725ea 100644 --- a/index.html +++ b/index.html @@ -863,7 +863,7 @@ const CLASSICAL_PIECES=(function(){ var hmk=(function(){ var bg=[],mel=[]; function orch(t,freq,dur,v,inst){bg.push({t:t,f:freq,d:dur,i:inst||'strings',v:v||0.3});} - var theme=[A3,B3,C4,D4,E4,C4,E4,D4,B3,D4,Db4,A3,Db4,A3]; + var theme=[B3,Db4,D4,E4,Gb4,D4,Gb4,E4,Db4,E4,Eb4,B3,Eb4,B3]; var lanes=[0,1,2,0,1,2,1,0,3,0,1,3,1,3]; var t=0; // Pass 1: Very slow, barely audible (creeping start) @@ -906,7 +906,7 @@ const CLASSICAL_PIECES=(function(){ theme.forEach(function(f,i){ orch(t,f,d5*0.8,0.5,'strings');orch(t,f,d5*0.8,0.35,'brass'); orch(t,f/2,d5*0.8,0.35,'bass'); - if(i%4===0)bg.push({t:t,f:A3/2,d:0.3,i:'timpani',v:0.45}); + if(i%4===0)bg.push({t:t,f:B3/2,d:0.3,i:'timpani',v:0.45}); mel.push({t:t,l:lanes[i]});t+=d5; }); t+=0.2; @@ -915,7 +915,7 @@ const CLASSICAL_PIECES=(function(){ theme.forEach(function(f,i){ orch(t,f,d6*0.8,0.6,'strings');orch(t,f,d6*0.8,0.45,'brass'); orch(t,f/2,d6*0.8,0.4,'bass'); - if(i%2===0)bg.push({t:t,f:A3/2,d:0.2,i:'timpani',v:0.55}); + if(i%2===0)bg.push({t:t,f:B3/2,d:0.2,i:'timpani',v:0.55}); mel.push({t:t,l:lanes[i]});t+=d6; }); t+=0.15; @@ -924,25 +924,25 @@ const CLASSICAL_PIECES=(function(){ theme.forEach(function(f,i){ orch(t,f,d7*0.8,0.65,'strings');orch(t,f,d7*0.8,0.5,'brass'); orch(t,f/2,d7*0.8,0.45,'bass'); - bg.push({t:t,f:A3/2,d:0.15,i:'timpani',v:0.6}); + bg.push({t:t,f:B3/2,d:0.15,i:'timpani',v:0.6}); mel.push({t:t,l:lanes[i]});t+=d7; }); // Big finale: repeated chords t+=0.15; for(var ci=0;ci<4;ci++){ var t2=t+ci*0.4; - [A3,C4,E4,A4].forEach(function(f){ + [B3,D4,Gb4,B4].forEach(function(f){ orch(t2,f,0.35,0.65,'brass');orch(t2,f,0.35,0.55,'strings'); }); - bg.push({t:t2,f:A3/2,d:0.4,i:'timpani',v:0.65}); + bg.push({t:t2,f:B3/2,d:0.4,i:'timpani',v:0.65}); mel.push({t:t2,l:4}); } // Final long chord t=t+1.8; - [A3,C4,E4,A4].forEach(function(f){ + [B3,D4,Gb4,B4].forEach(function(f){ orch(t,f,2.0,0.6,'brass');orch(t,f,2.0,0.5,'strings'); }); - bg.push({t:t,f:A3/2,d:1.5,i:'timpani',v:0.7}); + bg.push({t:t,f:B3/2,d:1.5,i:'timpani',v:0.7}); mel.push({t:t,l:4}); return {n:"Hall of the Mountain King",composer:"Grieg",bpm:120,duration:Math.ceil(t+2.5),isClassical:true,bg:bg,melody:mel}; })(); @@ -2282,28 +2282,95 @@ const CLASSICAL_PIECES=(function(){ // Big chord [D3,A3,D4,F4,A4].forEach(function(f){org(t,f,1.5,0.6);}); bg.push({t:t,f:D3/2,d:1.2,i:'timpani',v:0.55});mel.push({t:t,l:4});t+=1.8; - // Fugue: 6 entries accelerating + + // === Toccata continuation: dramatic recitative-like passages === + // Rapid ascending arpeggios (organ virtuosity) + var arp1=[D4,F4,A4,D5,F5,D5,A4,F4]; + var a1Ln=[0,2,0,1,2,1,0,2]; + [0.18,0.16,0.14].forEach(function(spd,si){ + var av=0.4+si*0.06; + arp1.forEach(function(f,i){org(t,f,spd*0.8,av);mel.push({t:t,l:a1Ln[i]});t+=spd;}); + t+=0.2; + }); + // Sustained D minor chord with pedal point + [D3,A3,D4,F4,A4].forEach(function(f){org(t,f,2.5,0.6);}); + bg.push({t:t,f:D3/2,d:2.0,i:'timpani',v:0.55});mel.push({t:t,l:4});t+=3.0; + + // === Second toccata section: sequence descending through keys === + // D minor → C major → Bb major → A major (dominant) + var seqKeys=[[D4,F4,A4,D5],[C4,E4,G4,C5],[Bb3,D4,F4,Bb4],[A3,Db4,E4,A4]]; + seqKeys.forEach(function(ch,ki){ + var sv=0.45+ki*0.04; + // Rapid broken chord + ch.forEach(function(f,i){org(t,f,0.15,sv);mel.push({t:t,l:[0,1,2,3][i]});t+=0.16;}); + // Sustained chord + ch.forEach(function(f){org(t,f,1.2,sv);}); + mel.push({t:t,l:4});t+=1.5; + }); + t+=0.5; + + // === Dramatic ascending chromatic passage === + [D4,Eb4,E4,F4,Gb4,G4,Ab4,A4,Bb4,B4,C5,Db5,D5].forEach(function(f,i){ + org(t,f,0.14,0.5+i*0.01); + bg.push({t:t,f:f/2,d:0.14,i:'bass',v:0.3}); + mel.push({t:t,l:[0,1,2,3][i%4]});t+=0.15; + }); + // Massive Neapolitan chord → V → i cadence + [Eb4,G4,Bb4,Eb5].forEach(function(f){org(t,f,1.5,0.6);});mel.push({t:t,l:4});t+=1.8; + [A3,Db4,E4,A4].forEach(function(f){org(t,f,1.2,0.6);});mel.push({t:t,l:4});t+=1.5; + + // === Fugue: subject entries building in intensity === var subj=[D4,E4,F4,G4,A4,Bb4,A4,G4,F4,E4,D4,A3,D4]; var sLn=[0,1,2,3,0,2,0,3,2,1,0,4,0]; - var speeds=[0.30,0.26,0.23,0.20,0.17,0.14]; - var vols=[0.3,0.35,0.4,0.48,0.55,0.62]; + // 8 entries from slow to fast, quiet to loud + var speeds=[0.32,0.28,0.25,0.22,0.20,0.18,0.16,0.14]; + var vols=[0.25,0.3,0.35,0.4,0.45,0.5,0.55,0.62]; speeds.forEach(function(spd,si){ subj.forEach(function(f,i){ org(t,f,spd*0.85,vols[si]); if(si>1)bg.push({t:t,f:f/2,d:spd*0.85,i:'bass',v:vols[si]*0.5}); - if(si>3)bg.push({t:t,f:f,d:spd*0.85,i:'strings',v:vols[si]*0.4}); - if(si>3&&i%3===0)bg.push({t:t,f:D3,d:0.3,i:'timpani',v:vols[si]*0.6}); + if(si>3){ + bg.push({t:t,f:f,d:spd*0.85,i:'strings',v:vols[si]*0.4}); + if(i%3===0)bg.push({t:t,f:D3,d:0.3,i:'timpani',v:vols[si]*0.6}); + } mel.push({t:t,l:sLn[i]});t+=spd; }); - t+=0.4; + t+=0.35; }); - // Final cascade + + // === Stretto: subject entries overlapping, maximum intensity === + // Two interleaved subjects at breakneck speed + var strSpd=0.12; + subj.forEach(function(f,i){ + org(t,f,strSpd*0.85,0.65);org(t,f*2,strSpd*0.85,0.4); + bg.push({t:t,f:f/2,d:strSpd*0.85,i:'bass',v:0.5}); + bg.push({t:t,f:f,d:strSpd*0.85,i:'strings',v:0.45}); + if(i%2===0)bg.push({t:t,f:D3,d:0.2,i:'timpani',v:0.6}); + mel.push({t:t,l:sLn[i]});t+=strSpd; + }); + t+=0.3; + + // === Grand finale: cascading scales and massive chords === + // Descending cascade [D5,C5,Bb4,A4,G4,F4,E4,D4,C4,Bb3,A3,G3].forEach(function(f,i){ - org(t,f,0.13,0.6);bg.push({t:t,f:f,d:0.13,i:'strings',v:0.4});mel.push({t:t,l:[0,2,3,1][i%4]});t+=0.14; + org(t,f,0.12,0.6);bg.push({t:t,f:f,d:0.12,i:'strings',v:0.4});mel.push({t:t,l:[0,2,3,1][i%4]});t+=0.13; }); - t+=0.2; - [D3,A3,D4,F4,A4,D5].forEach(function(f){org(t,f,3.0,0.7);}); - bg.push({t:t,f:D3/2,d:2.5,i:'timpani',v:0.7});mel.push({t:t,l:4}); + t+=0.15; + // Ascending cascade + [D3,E3,F3,G3,A3,Bb3,C4,D4,E4,F4,G4,A4,Bb4,C5,D5].forEach(function(f,i){ + org(t,f,0.11,0.6);bg.push({t:t,f:f,d:0.11,i:'strings',v:0.45});mel.push({t:t,l:[0,1,2,3][i%4]});t+=0.12; + }); + t+=0.3; + + // Final massive chords: iv-V-i (plagal approach) + for(var fc=0;fc<3;fc++){ + var fch=[[G3,Bb3,D4,G4],[A3,Db4,E4,A4],[D3,A3,D4,F4,A4,D5]][fc]; + fch.forEach(function(f){org(t,f,0.8,0.65);bg.push({t:t,f:f,d:0.8,i:'strings',v:0.5});}); + bg.push({t:t,f:D3/2,d:0.7,i:'timpani',v:0.6});mel.push({t:t,l:4});t+=1.0; + } + // Sustained final D minor + [D3,A3,D4,F4,A4,D5].forEach(function(f){org(t,f,4.0,0.7);bg.push({t:t,f:f,d:4.0,i:'strings',v:0.5});}); + bg.push({t:t,f:D3/2,d:3.5,i:'timpani',v:0.7});mel.push({t:t,l:4}); return {n:"Toccata & Fugue in D Minor",composer:"Bach",bpm:100,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; })(); @@ -2503,8 +2570,8 @@ const CLASSICAL_PIECES=(function(){ // ── Swan Lake (Theme) ── var swan=(function(){ var bg=[],mel=[],t=0,q=0.55; - var theme=[A4,B4,C5,B4,A4,E4,A4,G4,F4,E4,D4,E4,F4,E4,D4,C4,B3,A3,B3,C4,D4,E4,A4]; - var tLn=[0,1,2,1,0,2,0,3,2,1,0,1,2,1,0,2,1,0,1,2,0,2,0]; + var theme=[B4,Db5,D5,Db5,B4,B4,Db5,D5,E5,D5,Db5,B4,A4,Gb4,B4,A4,G4,Gb4,E4,Gb4,G4,Gb4,B4]; + var tLn=[1,0,0,0,1,1,0,0,0,0,0,1,2,3,1,2,2,3,3,3,2,3,1]; for(var rep=0;rep<3;rep++){ var v=0.25+rep*0.12; var inst=rep===0?'woodwind':rep===1?'strings':'brass'; @@ -2512,17 +2579,17 @@ const CLASSICAL_PIECES=(function(){ bg.push({t:t,f:f,d:q*0.85,i:inst,v:v}); if(rep>0)bg.push({t:t,f:f/2,d:q*0.85,i:'bass',v:v*0.4}); if(rep>1)bg.push({t:t,f:f,d:q*0.85,i:'strings',v:v*0.5}); - if(i%3===0){bg.push({t:t,f:A3,d:q*2,i:'bass',v:v*0.3});} + if(i%3===0){bg.push({t:t,f:B3,d:q*2,i:'bass',v:v*0.3});} mel.push({t:t,l:tLn[i]});t+=q; }); t+=0.5; } for(var c=0;c<3;c++){ - [A3,C4,E4,A4].forEach(function(f){bg.push({t:t,f:f,d:q*2.5,i:'strings',v:0.55});bg.push({t:t,f:f,d:q*2.5,i:'brass',v:0.45});}); + [B3,D4,Gb4,B4].forEach(function(f){bg.push({t:t,f:f,d:q*2.5,i:'strings',v:0.55});bg.push({t:t,f:f,d:q*2.5,i:'brass',v:0.45});}); mel.push({t:t,l:4});t+=q*3; } - [A3,C4,E4,A4].forEach(function(f){bg.push({t:t,f:f,d:2.5,i:'strings',v:0.55});}); - bg.push({t:t,f:A3/2,d:2.0,i:'timpani',v:0.6});mel.push({t:t,l:4}); + [B3,D4,Gb4,B4].forEach(function(f){bg.push({t:t,f:f,d:2.5,i:'strings',v:0.55});}); + bg.push({t:t,f:B3/2,d:2.0,i:'timpani',v:0.6});mel.push({t:t,l:4}); return {n:"Swan Lake (Theme)",composer:"Tchaikovsky",bpm:110,duration:Math.ceil(t+3),isClassical:true,bg:bg,melody:mel}; })(); @@ -2647,10 +2714,11 @@ const CLASSICAL_PIECES=(function(){ // ── Dance of the Sugar Plum Fairy ── var sugarplum=(function(){ var bg=[],mel=[],t=0,q=0.4; - var theme=[E4,Eb4,E4,B3,D4,C4,A3,C4,E4,A4,B3,E4,Ab4,B4,A4]; - var tLn=[2,1,2,3,0,2,0,2,2,1,3,2,1,0,1]; - var ans=[E4,Eb4,E4,B3,D4,C4,A3]; - var aLn=[2,1,2,3,0,2,0]; + // Celesta melody from The Nutcracker — staccato descending/ascending pattern in E minor + var theme=[B4,A4,Ab4,A4,C5,B4,A4,Ab4,E4,Ab4,B4,E5,D5,C5,B4]; + var tLn=[3,0,1,0,2,3,0,1,2,1,3,2,1,0,3]; + var ans=[B4,A4,Ab4,A4,C5,B4,A4]; + var aLn=[3,0,1,0,2,3,0]; for(var rep=0;rep<5;rep++){ var v=0.2+rep*0.08; var inst=rep<2?'woodwind':rep<4?'strings':'brass'; @@ -2983,7 +3051,7 @@ const CLASSICAL_PIECES=(function(){ var canon=(function(){ var bg=[],mel=[],t=0,q=0.55; var bassLine=[D3,A3,B3,Gb3,G3,D3,G3,A3]; - // Real Pachelbel violin melody: F#-E-D-C#-B-A-B-C# (var 1) then D-C#-B-A-G-F#-G-A (var 2) + // Real Pachelbel violin melody: F#5-E5-D5-C#5-B4-A4-B4-C#5 (var 1) then D5-C#5-B4-A4-G4-F#4-G4-A4 (var 2) var melody2=[Gb4,E4,D4,Db4,B3,A3,B3,Db4,D4,Db4,B3,A3,G3,Gb3,G3,A3]; var m2Ln=[2,1,0,1,3,0,3,1,0,1,3,0,3,2,3,0]; for(var rep=0;rep<4;rep++){ @@ -3013,10 +3081,10 @@ const CLASSICAL_PIECES=(function(){ var hungarian=(function(){ var bg=[],mel=[],t=0; function orch(t,f,d,v,i){bg.push({t:t,f:f,d:d,i:i||'strings',v:v||0.4});} - var fast=[A4,G4,A4,E4,A4,G4,A4,E4,F4,E4,D4,C4,B3,A3,B3,C4,D4,E4,F4,E4]; - var fLn=[0,3,0,2,0,3,0,2,1,2,0,1,3,0,3,1,0,2,1,2]; - var slow=[A4,A4,G4,F4,E4,D4,E4,F4,G4,A4]; - var sLn=[0,0,3,1,2,0,2,1,3,0]; + var fast=[A4,A4,A4,A4,Bb4,A4,G4,F4,F4,E4,F4,G4,A4,A4,Bb4,A4,G4,F4,E4,D4]; + var fLn=[0,0,0,0,2,0,3,1,1,2,1,3,0,0,2,0,3,1,2,0]; + var slow=[D4,D4,E4,F4,F4,E4,D4,E4,F4,A4]; + var sLn=[0,0,2,1,1,2,0,2,1,0]; // Fast section 1 [0.20,0.18].forEach(function(qf,qi){ var v=0.35+qi*0.1; @@ -3051,11 +3119,11 @@ const CLASSICAL_PIECES=(function(){ t+=0.3; }); for(var c=0;c<4;c++){ - [A3,C4,E4,A4].forEach(function(f){orch(t,f,0.35,0.65,'brass');}); - bg.push({t:t,f:A3/2,d:0.35,i:'timpani',v:0.65});mel.push({t:t,l:4});t+=0.45; + [D3,A3,D4,F4].forEach(function(f){orch(t,f,0.35,0.65,'brass');}); + bg.push({t:t,f:D3/2,d:0.35,i:'timpani',v:0.65});mel.push({t:t,l:4});t+=0.45; } - [A3,C4,E4,A4].forEach(function(f){orch(t,f,2.0,0.6,'brass');orch(t,f,2.0,0.5);}); - bg.push({t:t,f:A3/2,d:1.5,i:'timpani',v:0.7});mel.push({t:t,l:4}); + [D3,A3,D4,F4,A4].forEach(function(f){orch(t,f,2.0,0.6,'brass');orch(t,f,2.0,0.5);}); + bg.push({t:t,f:D3/2,d:1.5,i:'timpani',v:0.7});mel.push({t:t,l:4}); return {n:"Hungarian Dance No. 5",composer:"Brahms",bpm:140,duration:Math.ceil(t+2.5),isClassical:true,bg:bg,melody:mel}; })(); @@ -3528,7 +3596,7 @@ const FOLK_PIECES=(function(){ // ── CHRISTMAS (public domain carols) ── const CHRISTMAS_PIECES=(function(){ var C3=NT.C3,D3=NT.D3,E3=NT.E3,F3=NT.F3,G3=NT.G3,A3=NT.A3,B3=NT.B3, - C4=NT.C4,D4=NT.D4,Eb4=NT.Eb4,E4=NT.E4,F4=NT.F4,G4=NT.G4,Ab4=NT.Ab4,A4=NT.A4,Bb4=NT.Bb4,B4=NT.B4, + C4=NT.C4,D4=NT.D4,Eb4=NT.Eb4,E4=NT.E4,F4=NT.F4,Gb4=NT.Gb4,G4=NT.G4,Ab4=NT.Ab4,A4=NT.A4,Bb4=NT.Bb4,B4=NT.B4, C5=NT.C5,D5=NT.D5,Eb5=NT.Eb5,E5=NT.E5,F5=NT.F5,G5=NT.G5; function carol(name,origin,bpm,theme,lanes,durations,passes,root){ var bg=[],mel=[],t=0,q=0.25; @@ -3609,7 +3677,7 @@ const CHRISTMAS_PIECES=(function(){ // ── God Rest Ye Merry Gentlemen (E minor / A minor) ── var godrest=carol("God Rest Ye Merry Gentlemen","English (1500s)",120, - [E4,E4,E4,D4,C4,D4,E4,F4,G4,A4,Bb4,A4,G4,F4,E4,D4,C4,D4,E4,F4,E4,D4,C4,B3,C4,G4,G4,F4,E4,F4,G4,A4,Bb4,A4,G4,F4,E4], + [E4,E4,E4,D4,C4,D4,E4,Gb4,G4,A4,B4,A4,G4,Gb4,E4,D4,C4,D4,E4,Gb4,E4,D4,C4,B3,C4,G4,G4,Gb4,E4,Gb4,G4,A4,B4,A4,G4,Gb4,E4], [2,2,2,1,0,1,2,1,3,0,2,0,3,1,2,1,0,1,2,1,2,1,0,3,0,3,3,1,2,1,3,0,2,0,3,1,2], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,4], 4,E4); @@ -3623,10 +3691,10 @@ const CHRISTMAS_PIECES=(function(){ // ── Angels We Have Heard on High ── var angels=carol("Angels We Have Heard on High","French (1862)",110, - [E4,E4,E4,E4,F4,D4,E4,F4,E4,E4,F4,D4,E4,F4,G4,F4,E4,D4,E4,C4,D4,E4,F4,D4,E4,F4,G4,F4,E4,D4,E4,C4,C4], - [2,2,2,2,1,1,2,1,2,2,1,1,2,1,3,1,2,1,2,0,1,2,1,1,2,1,3,1,2,1,2,0,0], - [1,1,1,1,1,2,1,1,1,1,1,2,1,1,2,1,1,1,1,2,1,1,1,2,1,1,2,1,1,1,1,2,4], - 4,C4); + [F4,F4,F4,F4,A4,G4,F4,F4,G4,A4,F4,D4,C4,D4,F4,G4,A4,G4,F4,E4,F4,G4,A4,G4,F4,E4,F4,G4,A4,G4,F4,G4,F4], + [1,1,1,1,0,3,1,1,3,0,1,1,0,1,1,3,0,3,1,2,1,3,0,3,1,2,1,3,0,3,1,3,1], + [1,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,2,4], + 4,F4); // ── O Holy Night (in C major) ── var oholynight=carol("O Holy Night","A. Adam (1847)",72, @@ -3718,8 +3786,8 @@ const SINGALONG_PIECES=(function(){ [1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,2,1,1,2,1,1,1,2,1,1,1,2,1,1,1,2,3], 4,E4); var amazing=pub("Amazing Grace","J. Newton (1779)",80, - [G4,C5,E5,C5,E5,D5,C5,A4,G4,G4,C5,E5,C5,E5,D5,G5,G5,E5,C5,C5,A4,G4,G4,C5,E5,C5,E5,D5,C5], - [3,0,2,0,2,1,0,0,3,3,0,2,0,2,1,3,3,2,0,0,0,3,3,0,2,0,2,1,0], + [G4,C5,E5,C5,E5,D5,C5,A4,G4,G4,C5,E5,C5,E5,D5,E5,E5,C5,A4,A4,G4,E4,G4,C5,E5,C5,E5,D5,C5], + [3,0,2,0,2,1,0,0,3,3,0,2,0,2,1,2,2,0,0,0,3,2,3,0,2,0,2,1,0], [1,2,1,1,2,2,1,2,2,1,2,1,1,2,4,2,1,2,1,2,1,2,1,2,1,1,2,2,4], 4,C4); var auld=pub("Auld Lang Syne","R. Burns (1788)",95, @@ -3743,8 +3811,8 @@ const SINGALONG_PIECES=(function(){ [3,3,2,1,3,1,1,1,3,2,1,1,1,1,2,1,3,3,1,2,1,1,1,1,2,1,3,3,1,1,1,3,1,1,1,4], 4,D4); var bonnie=pub("My Bonnie Lies Over the Ocean","Scottish (1881)",120, - [G4,C5,C5,D5,E5,E5,D5,C5,A4,G4,C5,C5,D5,E5,G5,E5,D5,G4,C5,C5,D5,E5,E5,D5,C5,A4,A4,G4,F4,E4,F4,G4,E4,C4,E5,G5,G5,G5,E5,C5,C5,D5,E5,G5,G5,G5,F5,E5,D5,C5], - [3,0,0,1,2,2,1,0,0,3,0,0,1,2,3,2,1,3,0,0,1,2,2,1,0,0,0,3,1,2,1,3,2,0,2,3,3,3,2,0,0,1,2,3,3,3,1,2,1,0], + [G4,C5,C5,D5,E5,E5,D5,C5,A4,G4,C5,C5,D5,E5,E5,D5,C5,G4,C5,C5,D5,E5,E5,D5,C5,A4,A4,G4,F4,E4,F4,G4,E4,C4,E5,E5,E5,E5,D5,C5,C5,D5,E5,E5,E5,E5,D5,C5,A4,C5], + [3,0,0,1,2,2,1,0,0,3,0,0,1,2,2,1,0,3,0,0,1,2,2,1,0,0,0,3,1,2,1,3,2,0,2,2,2,2,1,0,0,1,2,2,2,2,1,0,0,0], [1,1,1,1,1,2,1,1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,2,1,1,2,1,1,1,1,1,2,1,4,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,4], 4,C4); // ── Wellerman (accurate melody with driving stomp beat) ── From 826b81c00773dfb40d5e45f2c97662f16d86d22c Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 11:52:32 +0000 Subject: [PATCH 19/22] Fix rhythm timing across all synth genre pieces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Changed all 7 helper functions (folk, carol, pub, spirit, world, rhyme, rag) from hardcoded q values to BPM-based timing (q=30/bpm), making duration units represent eighth notes at the given BPM - Scaled all ~93 duration arrays to work correctly with new timing system - Fixed specific rhythm patterns for well-known songs: - Happy Birthday: correct 3/4 pickup rhythm (1,1,2,2,2,4 pattern) - Greensleeves/What Child Is This: proper 3/4 dotted rhythm (3,1,2 pattern) - Joy to the World: correct descending scale rhythm with dotted values - Home on the Range: proper waltz-style quarter/half note rhythm - She'll Be Coming Round the Mountain: correct 2/4 march rhythm - Jingle Bells: corrected verse/chorus rhythm - Fixed Video Game pieces: Turkish March q=0.18→0.227, Can-Can q=0.16→0.197 to match their listed BPM tempos - Fixed duplicate Happy Birthday definition in "Classics from Prime" section https://claude.ai/code/session_01MhCcEPfX3JqAk8zmvLXZ1g --- index.html | 206 ++++++++++++++++++++++++++--------------------------- 1 file changed, 103 insertions(+), 103 deletions(-) diff --git a/index.html b/index.html index cb725ea..d0ae460 100644 --- a/index.html +++ b/index.html @@ -3320,7 +3320,7 @@ const VIDEOGAME_PIECES=(function(){ // ── Turkish March (Mozart) ── var turkish=(function(){ - var bg=[],mel=[],t=0,q=0.18; + var bg=[],mel=[],t=0,q=0.227; var theme=[B3,A3,Ab3,A3,C4,D4,C4,B3,A3,B3,C4,D4,E4,D4,C4,B3,A3,B3,A3,A3]; var tLn= [3,0,1,0,2,1,2,3,0,3,0,1,2,1,0,3,0,3,0,0]; for(var rep=0;rep<6;rep++){ @@ -3382,7 +3382,7 @@ const VIDEOGAME_PIECES=(function(){ // ── Can-Can (Offenbach) ── var cancan=(function(){ - var bg=[],mel=[],t=0,q=0.16; + var bg=[],mel=[],t=0,q=0.197; var theme=[C4,D4,E4,C4,E4,C4,E4,D4,E4,F4,E4,D4,C4,D4,E4,F4,G4,A4,G4,E4,C4,D4,E4,C4]; var tLn= [0,1,2,0,2,0,2,1,2,3,2,1,0,1,2,3,0,1,0,2,0,1,2,0]; for(var rep=0;rep<6;rep++){ @@ -3514,7 +3514,7 @@ const FOLK_PIECES=(function(){ // Folk piece helper function folk(name,origin,bpm,theme,lanes,durations,passes,root){ - var bg=[],mel=[],t=0,q=0.25; + var bg=[],mel=[],t=0,q=30/bpm; for(var rep=0;rep Date: Tue, 31 Mar 2026 11:55:06 +0000 Subject: [PATCH 20/22] Add dotted rhythms to iconic songs for musical accuracy - Silent Night: proper 6/8 feel with dotted-quarter + eighth (3,1,2) pattern - Deck the Halls: dotted pickup on "Deck the halls" and "Fa la la" phrases - Amazing Grace: dotted quarter-eighth pairs in "A-MAZ-ing Grace" phrasing - Auld Lang Syne: characteristic dotted Scots snap rhythm (3,1 pattern) https://claude.ai/code/session_01MhCcEPfX3JqAk8zmvLXZ1g --- index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index d0ae460..0ee79dd 100644 --- a/index.html +++ b/index.html @@ -3626,12 +3626,12 @@ const CHRISTMAS_PIECES=(function(){ var silent=carol("Silent Night","F. Gruber (1818)",72, [G4,A4,G4,E4,G4,A4,G4,E4,D5,D5,B4,C5,C5,G4,A4,A4,C5,B4,A4,G4,A4,G4,E4,A4,A4,C5,B4,A4,G4,A4,G4,E4,D5,D5,F5,D5,B4,C5,E5,C5,G4,E4,G4,F4,D4,C4], [3,0,3,2,3,0,3,2,0,0,3,0,0,3,0,0,0,3,0,3,0,3,2,0,0,0,3,0,3,0,3,2,0,0,1,0,3,0,2,0,3,2,3,1,1,0], - [2,2,2,4,2,2,2,4,2,2,4,2,2,4,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,4,2,2,2,2,4,2,2,2,2,2,2,2,2,4], + [3,1,2,6,3,1,2,6,2,2,6,2,2,6,2,2,3,1,2,3,1,2,6,2,2,3,1,2,3,1,2,6,2,2,3,1,6,2,2,2,2,2,3,1,2,6], 3,C4); var deck=carol("Deck the Halls","Welsh (1862)",130, [C5,Bb4,A4,G4,F4,G4,A4,F4,G4,A4,Bb4,G4,A4,G4,F4,E4,D4,E4,F4,G4,A4,G4,F4,E4,F4,G4,A4,Bb4,C5,A4,G4,F4], [0,3,0,3,1,3,0,1,3,0,2,3,0,3,1,2,1,2,1,3,0,3,1,2,1,3,0,2,0,0,3,1], - [4,2,2,4,2,2,2,4,2,2,2,4,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,4,2,2,8], + [3,1,2,2,3,1,2,2,2,2,2,2,3,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,1,2,4], 4,F4); var wish=carol("We Wish You a Merry Christmas","English (1500s)",140, [G4,C5,C5,D5,C5,B4,A4,A4,D5,D5,E5,D5,C5,B4,G4,E5,E5,F5,E5,D5,C5,A4,G4,G4,A4,D5,B4,C5], @@ -3788,12 +3788,12 @@ const SINGALONG_PIECES=(function(){ var amazing=pub("Amazing Grace","J. Newton (1779)",80, [G4,C5,E5,C5,E5,D5,C5,A4,G4,G4,C5,E5,C5,E5,D5,E5,E5,C5,A4,A4,G4,E4,G4,C5,E5,C5,E5,D5,C5], [3,0,2,0,2,1,0,0,3,3,0,2,0,2,1,2,2,0,0,0,3,2,3,0,2,0,2,1,0], - [2,2,2,2,2,2,2,2,2,2,2,2,2,2,6,2,2,2,2,2,2,2,2,2,2,2,2,2,6], + [2,4,3,1,2,2,2,4,4,2,4,3,1,2,2,4,4,3,1,2,2,4,2,4,3,1,2,2,6], 4,C4); var auld=pub("Auld Lang Syne","R. Burns (1788)",95, [C4,F4,F4,F4,A4,G4,F4,G4,A4,F4,F4,A4,C5,D5,D5,D5,C5,A4,F4,F4,G4,A4,G4,F4,D4,C4], [0,1,1,1,0,3,1,3,0,1,1,0,0,1,1,1,0,0,1,1,3,0,3,1,1,0], - [2,4,2,2,2,4,2,2,2,4,2,2,2,6,2,2,2,4,2,2,2,4,2,4,2,6], + [2,3,1,2,3,1,2,2,3,1,2,2,2,6,2,3,1,2,3,1,2,3,1,2,2,6], 4,F4); var saints=pub("When the Saints Go Marching In","Spiritual (Trad.)",120, [C4,E4,F4,G4,C4,E4,F4,G4,C4,E4,F4,G4,E4,C4,E4,D4,E4,E4,D4,C4,C4,E4,G4,G4,F4,E4,F4,G4,E4,C4,D4,C4], From 0229242ff83768eb0d729c4d949475bc99416806 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 13:34:24 +0000 Subject: [PATCH 21/22] Fix Danny Boy, Red River Valley, Parting Glass rhythms Danny Boy (Londonderry Air): Replace all-quarter encoding with proper flowing Irish dotted rhythm. Phrases now use dotted-quarter+eighth pairs (3,1) for melodic motion, half notes (4) on stressed syllables like "Boy", and dotted-half (6) or whole (8) for held phrase-end notes like "-ing", "side", "bide". Total duration increases from ~43s/pass to ~50s/pass reflecting the song's true character. Red River Valley: Slow American ballad now has dotted-quarter+eighth motion with half-note phrase endings instead of uniform quarter notes. The Parting Glass: Irish 4/4 ballad now uses proper dotted feel with stressed syllables held as half/dotted-half notes. https://claude.ai/code/session_016yrXXcwbdXGoSXkNX8UcP2 --- index.html | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 0ee79dd..1e72937 100644 --- a/index.html +++ b/index.html @@ -3555,10 +3555,12 @@ const FOLK_PIECES=(function(){ 3,C4); // ── Red River Valley ── + // Slow American ballad in 4/4. "From this val-ley they say you are go-ing" + // Uses dotted-quarter + eighth for the flowing melodic phrases. var redriver=folk("Red River Valley","American Traditional (1870s)",85, [C4,D4,E4,G4,G4,E4,D4,C4,D4,E4,F4,E4,D4,C4,E4,G4,A4,G4,E4,D4,C4,D4,E4,C4], [0,1,2,3,3,2,1,0,1,2,1,2,1,0,2,3,0,3,2,1,0,1,2,0], - [2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4], + [2,3,1,4,1,3,2,4, 2,3,1,3,1,4,2,4, 2,3,1,3,1,3,1,8], 4,C4); // ── Home on the Range ── @@ -3583,10 +3585,16 @@ const FOLK_PIECES=(function(){ 5,G4); // ── Danny Boy ── + // Londonderry Air: flowing Irish ballad, famous "long-short" dotted feel. + // Phrase A: "Oh Dan-ny Boy, the pipes, the pipes are call-ing" (notes 0-10) + // Phrase B: "From glen to glen and down the moun-tain side" (notes 11-24) + // Phrase C: High passage, peaks at E5 (notes 25-37) + // Phrase D: Final resolution back to tonic C (notes 38-48) + // Duration units: 1=eighth, 2=quarter, 3=dotted-quarter, 4=half, 6=dotted-half, 8=whole var dannyboy=folk("Danny Boy","Irish Traditional (1910s)",72, [C4,E4,F4,G4,A4,G4,A4,C5,B4,A4,G4,F4,G4,C4,E4,F4,G4,A4,G4,A4,C5,D5,C5,A4,G4,A4,A4,C5,D5,E5,D5,C5,A4,C5,B4,A4,G4,A4,G4,E4,C4,E4,F4,G4,A4,G4,F4,E4,C4], [0,2,1,3,0,3,0,0,3,0,3,1,3,0,2,1,3,0,3,0,0,1,0,0,3,0,0,0,1,2,1,0,0,0,3,0,3,0,3,2,0,2,1,3,0,3,1,2,0], - [2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4], + [2,3,1,4,1,3,1,3,1,3,6, 2,3,1,3,1,4,1,3,1,3,1,3,1,6, 2,1,3,1,4,1,3,1,3,1,3,1,6, 2,3,1,3,1,4,1,3,1,3,8], 3,C4); return [ohsusanna,greensleeves,camptown,redriver,homerange,yankee,turkey,dannyboy]; @@ -3783,7 +3791,9 @@ const SINGALONG_PIECES=(function(){ 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], - [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,4], + // "Of all the mon-ey that e'er I had / I spent it in good com-pa-ny" + // Flowing Irish 4/4 with dotted-quarter+eighth pairs and half-notes on stressed syllables + [2,3,1,4,1,3,2,4, 2,3,1,2,6,2,2,6, 2,3,1,4,1,3,2,4, 2,3,1,2,6,2,2,6], 4,E4); var amazing=pub("Amazing Grace","J. Newton (1779)",80, [G4,C5,E5,C5,E5,D5,C5,A4,G4,G4,C5,E5,C5,E5,D5,E5,E5,C5,A4,A4,G4,E4,G4,C5,E5,C5,E5,D5,C5], From 75057926c19dba18873a56c85dbae34fcb4291db Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 31 Mar 2026 13:39:36 +0000 Subject: [PATCH 22/22] Fix Away in a Manger, O Holy Night, Kumbaya, Nobody Knows rhythms Away in a Manger: 3/4 waltz now has beat-1 emphasis with half-notes on sustained syllables ("manger", "bed"), proper waltz feel instead of uniform quarter notes. O Holy Night: Encodes the characteristic 12/8 compound feel with dotted-quarter+eighth pairs (3,1) matching the lilting "O ho-ly night" rhythm and half-note phrase endings. Kumbaya: Slow meditative spiritual now uses dotted-quarter+eighth (3,1) for the 3-syllable "Kum-ba-ya" pattern with half-note on "Lord", matching the gentle rocking feel of the original. Nobody Knows the Trouble I've Seen: Gospel dotted phrasing with longer held notes on key phrases, replacing uniform quarter notes. https://claude.ai/code/session_016yrXXcwbdXGoSXkNX8UcP2 --- index.html | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 1e72937..2586712 100644 --- a/index.html +++ b/index.html @@ -3664,7 +3664,9 @@ const CHRISTMAS_PIECES=(function(){ var away=carol("Away in a Manger","J.Murray (1885)",80, [C4,F4,F4,F4,G4,A4,F4,F4,A4,G4,F4,G4,F4,D4,C4,C4,F4,F4,F4,G4,A4,F4,F4,A4,G4,F4,G4,F4,D4,C4,Bb4,A4,F4], [0,1,1,1,3,0,1,1,0,3,1,3,1,1,0,0,1,1,1,3,0,1,1,0,3,1,3,1,1,0,2,0,1], - [2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,6], + // 3/4 waltz. "A-way in a man-ger no crib for a bed": + // beat 1 of each bar gets a longer note, phrase ends get dotted-half + [2,2,2,2,2,4, 2,2,2,2,6, 2,2,2,4, 2,2,2,2,2,4, 2,2,2,2,6, 2,2,2,4, 2,4,8], 4,F4); var twelve=carol("12 Days of Christmas","English (1780)",110, [C4,F4,F4,F4,F4,E4,F4,G4,A4,Bb4,A4,G4,F4,G4,A4,Bb4,A4,G4,F4,G4,A4,Bb4,C5,A4,Bb4,G4,A4,F4], @@ -3708,7 +3710,9 @@ const CHRISTMAS_PIECES=(function(){ var oholynight=carol("O Holy Night","A. Adam (1847)",72, [C4,F4,F4,F4,E4,F4,A4,A4,G4,F4,F4,Bb4,A4,G4,F4,G4,A4,G4,F4,E4,F4,C5,C5,Bb4,A4,G4,A4,Bb4,A4,G4,F4], [0,1,1,1,2,1,0,0,3,1,1,2,0,3,1,3,0,3,1,2,1,0,0,2,0,3,0,2,0,3,1], - [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2,2,4], + // 12/8 compound feel: "O ho-ly night! The stars are bright-ly shi-ning" + // Characteristic dotted-quarter+eighth pairs and long phrase-end notes + [2,3,1,4,1,3,1,3,1,3,1, 2,3,1,4,1,3,1,3,1,4, 2,3,1,3,1,2,2,3,1,4], 3,F4); // ── Rudolph the Red-Nosed Reindeer (in C major) ── @@ -3992,7 +3996,9 @@ const SPIRITUAL_PIECES=(function(){ var kumbaya=spirit("Kumbaya","Spiritual (Trad.)",75, [C4,E4,F4,G4,G4,F4,E4,C4,C4,E4,F4,G4,A4,G4,E4,C4,E4,F4,G4,G4,F4,E4,D4,C4], [0,2,1,3,3,1,2,0,0,2,1,3,0,3,2,0,2,1,3,3,1,2,1,0], - [2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,6], + // Slow meditative spiritual. "Kum-ba-ya my Lord Kum-ba-ya" + // Dotted-quarter+eighth for the 3-syllable "Kum-ba-ya" feel, half-note on "Lord" + [3,1,2,4, 3,1,2,4, 3,1,2,4, 3,1,2,4, 3,1,2,4, 3,1,2,8], 5,C4); var michael=spirit("Michael Row the Boat Ashore","Spiritual (1860s)",90, [C4,E4,F4,G4,A4,A4,G4,E4,C4,C4,E4,F4,G4,A4,A4,G4,E4,C4,D4,E4,F4,E4,D4,C4,D4,C4], @@ -4007,7 +4013,8 @@ const SPIRITUAL_PIECES=(function(){ var nobody=spirit("Nobody Knows the Trouble I've Seen","Spiritual (Trad.)",75, [C4,E4,G4,A4,G4,E4,C4,D4,E4,G4,C5,A4,G4,E4,D4,C4,E4,G4,A4,C5,A4,G4,E4,D4,C4], [0,2,3,0,3,2,0,1,2,3,0,0,3,2,1,0,2,3,0,0,0,3,2,1,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,6], + // Slow gospel: "No-bo-dy knows the trou-ble I've seen" — dotted-feel on key words + [2,3,1,3,1,3,2,4, 3,1,4,2,2,2,2,6, 3,1,4,2,2,2,2,2,8], 4,C4); var battle=spirit("Battle Hymn of the Republic","J.W. Howe (1861)",115, [C4,C4,C4,E4,E4,D4,C4,D4,E4,F4,E4,D4,C4,C4,E4,G4,G4,F4,E4,F4,G4,A4,G4,E4,C4,E4,D4,C4],