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(){