diff --git a/README.md b/README.md index 7458d26..f2d92f8 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,8 @@ Works with **keyboard**, **Wii Rock Band drums**, **Xbox/PS Rock Band drums**, * ## Features -- **19 Genres** across two modes: synth orchestra songs + drum beat patterns -- **125 synth pieces** with full synthesized orchestra background +- **18 Genres** across two modes: synth orchestra songs + drum beat patterns +- **124 synth pieces** with full synthesized orchestra background - **120 drum patterns** across 8 genres - **Note density toggle** — switch between Full and Simple (fewer notes for beginners) - **Drums or Orchestra mode** — choose whether pad hits play drum sounds or the actual melody note @@ -40,23 +40,20 @@ Works with **keyboard**, **Wii Rock Band drums**, **Xbox/PS Rock Band drums**, * ## Song List -### Prime (6 songs) +### Nursery Rhymes (15 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) - -### Nursery Rhymes (10 songs) -- Baa Baa Black Sheep (English, 1731) +- Hot Cross Buns (English, 1798) - London Bridge Is Falling Down (English, 1744) - Old MacDonald Had a Farm (English, 1706) - Row Row Row Your Boat (English, 1852) - Three Blind Mice (English, 1609) - Itsy Bitsy Spider (English, 1910s) - Pop Goes the Weasel (English, 1850s) -- Hot Cross Buns (English, 1798) +- Chopsticks (Euphemia Allen, 1877) +- Lavender's Blue (English Traditional, 1670s) +- Shortnin' Bread (Traditional, 1900s) - Jack and Jill (English, 1765) - Humpty Dumpty (English, 1797) @@ -245,7 +242,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 (~4900 lines) +- Single `index.html` file (~4850 lines) - Web Audio API for all sound synthesis - Canvas 2D for the note highway - Gamepad API for drum kit input diff --git a/index.html b/index.html index e9e175f..0ef433b 100644 --- a/index.html +++ b/index.html @@ -3431,73 +3431,6 @@ const CHIPTUNE_PIECES=(function(){ return [platformer,spaceshooter,rpg,racing,dungeon,victory]; })(); -// ── PRIME (easy beginner songs, verified from lead sheets) ── -const PRIME_PIECES=(function(){ - 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; - function primer(name,origin,bpm,theme,lanes,durations,passes,root){ - var bg=[],mel=[],t=0,q=0.25; - for(var rep=0;rep1)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(){ @@ -4069,7 +4002,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; @@ -4089,11 +4022,41 @@ const NURSERY_PIECES=(function(){ 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}; } - // ── Baa Baa Black Sheep (same melody as Twinkle but different words) ── - var baa=rhyme("Baa Baa Black Sheep","English (1731)",70, - [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], - [1,1,1,1,1,1,3,1,1,1,1,1,1,4], + // ── Twinkle Twinkle Little Star (same melody as Baa Baa Black Sheep) ── + 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); + // ── Mary Had a Little Lamb ── + 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); + // ── Happy Birthday ── + 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); + // ── Chopsticks ── + 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); + // ── Lavender's Blue ── + 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); + // ── Shortnin' Bread ── + 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); // ── London Bridge ── var london=rhyme("London Bridge Is Falling Down","English (1744)",75, @@ -4149,7 +4112,7 @@ 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]; + return [twinkle,mary,birthday,hotcross,london,macdonald,row,mice,spider,weasel,chopsticks,lavender,shortnin,jack,humpty]; })(); // ── RAGTIME (Scott Joplin & contemporaries, all public domain) ── @@ -4238,7 +4201,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;