Basically, my project is a Piezo music player, for which I've arranged four songs for so far (Only one is shown here, however, because character limits). I ran into some serious memory issues with arranging each one for the Piezo, but I was able to get around this after some users on the Arduino Discord told me about PROGMEM.
Problem is, something's wrong with the process of loading the song back in to actually play it. According to the serial monitor, 75 notes into loading a song, the loop's index just loops back around and gets stuck on the very first index for all eternity. What's going on here?
#include <LiquidCrystal.h>
#include <List.hpp>
const int upPin = 10;
const int downPin = 9;
const int playPin = 8;
const int piezoPin = 7;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
// These variables sanitize the inputs.
int upState;
int downState;
int playState;
int prevUpState = 0;
int prevDownState = 0;
int prevPlayState = 0;
// These variables are all the note frequencies the Piezo can play.
const int NOTE_B0 = 31;
const int NOTE_C1 = 33;
const int NOTE_CS1 = 35;
const int NOTE_D1 = 37;
const int NOTE_DS1 = 39;
const int NOTE_E1 = 41;
const int NOTE_F1 = 44;
const int NOTE_FS1 = 46;
const int NOTE_G1 = 49;
const int NOTE_GS1 = 52;
const int NOTE_A1 = 55;
const int NOTE_AS1 = 58;
const int NOTE_B1 = 62;
const int NOTE_C2 = 65;
const int NOTE_CS2 = 69;
const int NOTE_D2 = 73;
const int NOTE_DS2 = 78;
const int NOTE_E2 = 82;
const int NOTE_F2 = 87;
const int NOTE_FS2 = 93;
const int NOTE_G2 = 98;
const int NOTE_GS2 = 104;
const int NOTE_A2 = 110;
const int NOTE_AS2 = 117;
const int NOTE_B2 = 123;
const int NOTE_C3 = 131;
const int NOTE_CS3 = 139;
const int NOTE_D3 = 147;
const int NOTE_DS3 = 156;
const int NOTE_E3 = 165;
const int NOTE_F3 = 175;
const int NOTE_FS3 = 185;
const int NOTE_G3 = 196;
const int NOTE_GS3 = 208;
const int NOTE_A3 = 220;
const int NOTE_AS3 = 233;
const int NOTE_B3 = 247;
const int NOTE_C4 = 262;
const int NOTE_CS4 = 277;
const int NOTE_D4 = 294;
const int NOTE_DS4 = 311;
const int NOTE_E4 = 330;
const int NOTE_F4 = 349;
const int NOTE_FS4 = 370;
const int NOTE_G4 = 392;
const int NOTE_GS4 = 415;
const int NOTE_A4 = 440;
const int NOTE_AS4 = 466;
const int NOTE_B4 = 494;
const int NOTE_C5 = 523;
const int NOTE_CS5 = 554;
const int NOTE_D5 = 587;
const int NOTE_DS5 = 622;
const int NOTE_E5 = 659;
const int NOTE_F5 = 698;
const int NOTE_FS5 = 740;
const int NOTE_G5 = 784;
const int NOTE_GS5 = 831;
const int NOTE_A5 = 880;
const int NOTE_AS5 = 932;
const int NOTE_B5 = 988;
const int NOTE_C6 = 1047;
const int NOTE_CS6 = 1109;
const int NOTE_D6 = 1175;
const int NOTE_DS6 = 1245;
const int NOTE_E6 = 1319;
const int NOTE_F6 = 1397;
const int NOTE_FS6 = 1480;
const int NOTE_G6 = 1568;
const int NOTE_GS6 = 1661;
const int NOTE_A6 = 1760;
const int NOTE_AS6 = 1865;
const int NOTE_B6 = 1976;
const int NOTE_C7 = 2093;
const int NOTE_CS7 = 2217;
const int NOTE_D7 = 2349;
const int NOTE_DS7 = 2489;
const int NOTE_E7 = 2637;
const int NOTE_F7 = 2794;
const int NOTE_FS7 = 2960;
const int NOTE_G7 = 3136;
const int NOTE_GS7 = 3322;
const int NOTE_A7 = 3520;
const int NOTE_AS7 = 3729;
const int NOTE_B7 = 3951;
const int NOTE_C8 = 4186;
const int NOTE_CS8 = 4435;
const int NOTE_D8 = 4699;
const int NOTE_DS8 = 4978;
int currSong = 0;
bool songPlaying = false;
// NOTES_[Song number] arrays store the notes of a song. 0 means there's a rest at that location.
// BEATS_[Song number] arrays store the beat lengths of a song.
// Essentially, playSong will run through the notes array, then play whatever is at each location for however long the number in the beats array at the same spot says.
// The arrays for MEGALOVANIA (You probably know this one):
const int PROGMEM NOTES_C[] = { NOTE_D3,
NOTE_D3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_C3,
NOTE_C3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_B2,
NOTE_B2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_AS2,
NOTE_AS2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_D3,
NOTE_D3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_C3,
NOTE_C3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_B2,
NOTE_B2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_AS2,
NOTE_AS2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_D4,
NOTE_D4,
NOTE_D5,
0,
NOTE_A4,
0,
NOTE_GS4,
0,
NOTE_G4,
0,
NOTE_F4,
NOTE_D4,
NOTE_F4,
NOTE_G4,
NOTE_C4,
NOTE_C4,
NOTE_D5,
0,
NOTE_A4,
0,
NOTE_GS4,
0,
NOTE_G4,
0,
NOTE_F4,
NOTE_D4,
NOTE_F4,
NOTE_G4,
NOTE_B3,
NOTE_B3,
NOTE_D5,
0,
NOTE_A4,
0,
NOTE_GS4,
0,
NOTE_G4,
0,
NOTE_F4,
NOTE_D4,
NOTE_F4,
NOTE_G4,
NOTE_AS3,
NOTE_AS3,
NOTE_D5,
0,
NOTE_A4,
0,
NOTE_GS4,
0,
NOTE_G4,
0,
NOTE_F4,
NOTE_D4,
NOTE_F4,
NOTE_G4,
NOTE_D4,
NOTE_D4,
NOTE_D5,
0,
NOTE_A4,
0,
NOTE_GS4,
0,
NOTE_G4,
0,
NOTE_F4,
NOTE_D4,
NOTE_F4,
NOTE_G4,
NOTE_C4,
NOTE_C4,
NOTE_D5,
0,
NOTE_A4,
0,
NOTE_GS4,
0,
NOTE_G4,
0,
NOTE_F4,
NOTE_D4,
NOTE_F4,
NOTE_G4,
NOTE_B3,
NOTE_B3,
NOTE_D5,
0,
NOTE_A4,
0,
NOTE_GS4,
0,
NOTE_G4,
0,
NOTE_F4,
NOTE_D4,
NOTE_F4,
NOTE_G4,
NOTE_AS3,
NOTE_AS3,
NOTE_D5,
0,
NOTE_A4,
0,
NOTE_GS4,
0,
NOTE_G4,
0,
NOTE_F4,
NOTE_D4,
NOTE_F4,
NOTE_G4,
NOTE_F5,
NOTE_F5,
NOTE_F5,
NOTE_F5,
NOTE_F5,
NOTE_D5,
NOTE_D5,
NOTE_F5,
NOTE_F5,
NOTE_F5,
NOTE_G5,
NOTE_GS5,
NOTE_GS5,
NOTE_G5,
NOTE_F5,
NOTE_D5,
NOTE_F5,
NOTE_G5,
0,
NOTE_F5,
NOTE_F5,
NOTE_F5,
0,
NOTE_G5,
0,
NOTE_GS5,
0,
NOTE_A5,
0,
NOTE_C6,
0,
NOTE_A5,
NOTE_D6,
0,
NOTE_D6,
0,
NOTE_D6,
NOTE_A5,
NOTE_D6,
NOTE_D6,
NOTE_A5,
NOTE_A5,
NOTE_A5,
NOTE_A5,
NOTE_A5,
NOTE_G5,
NOTE_G5,
NOTE_A5,
NOTE_A5,
NOTE_A5,
NOTE_A5,
NOTE_G5,
NOTE_A5,
NOTE_D6,
0,
NOTE_A5,
NOTE_G5,
NOTE_D6,
NOTE_A5,
NOTE_G5,
NOTE_F5,
NOTE_C6,
NOTE_G5,
NOTE_F5,
NOTE_E5,
NOTE_AS4,
0,
NOTE_D5,
NOTE_E5,
0,
NOTE_F5,
0,
NOTE_C6,
0,
NOTE_F5,
NOTE_D5,
NOTE_F5,
NOTE_G5,
NOTE_GS5,
NOTE_G5,
NOTE_F5,
NOTE_D5,
NOTE_F5,
NOTE_E5,
NOTE_D5,
NOTE_F5,
NOTE_G5,
NOTE_GS5,
NOTE_A5,
NOTE_C6,
0,
NOTE_A5,
NOTE_GS5,
NOTE_G5,
NOTE_F5,
NOTE_D5,
NOTE_E5,
NOTE_F5,
NOTE_G5,
NOTE_A5,
NOTE_C6,
NOTE_CS6,
NOTE_GS5,
0,
NOTE_GS5,
NOTE_G5,
NOTE_F5,
NOTE_G5,
NOTE_F4,
NOTE_G4,
NOTE_A4,
NOTE_F5,
NOTE_E5,
NOTE_D5,
NOTE_E5,
NOTE_F5,
NOTE_G5,
NOTE_E5,
NOTE_A5,
0,
NOTE_A5,
NOTE_GS5,
NOTE_G5,
NOTE_FS5,
NOTE_F5,
NOTE_E5,
NOTE_DS5,
NOTE_D5,
NOTE_CS5,
NOTE_D5,
NOTE_DS5,
0,
NOTE_F5,
NOTE_D5,
NOTE_F5,
NOTE_G5,
NOTE_GS5,
NOTE_G5,
NOTE_F5,
NOTE_D5,
NOTE_F5,
NOTE_E5,
NOTE_D5,
NOTE_F5,
NOTE_G5,
NOTE_GS5,
NOTE_A5,
NOTE_C6,
0,
NOTE_A5,
NOTE_GS5,
NOTE_G5,
NOTE_F5,
NOTE_D5,
NOTE_E5,
NOTE_F5,
NOTE_G5,
NOTE_A5,
NOTE_C6,
NOTE_CS6,
NOTE_GS5,
0,
NOTE_GS5,
NOTE_G5,
NOTE_F5,
NOTE_G5,
NOTE_F4,
NOTE_G4,
NOTE_A4,
NOTE_F5,
NOTE_E5,
NOTE_D5,
NOTE_E5,
NOTE_F5,
NOTE_G5,
NOTE_E5,
NOTE_A5,
0,
NOTE_A5,
NOTE_GS5,
NOTE_G5,
NOTE_FS5,
NOTE_F5,
NOTE_E5,
NOTE_DS5,
NOTE_D5,
NOTE_CS5,
NOTE_D5,
NOTE_DS5,
NOTE_AS2,
NOTE_F3,
NOTE_E3,
NOTE_D3,
NOTE_F3,
NOTE_AS2,
NOTE_F3,
NOTE_E3,
NOTE_D3,
NOTE_D3,
NOTE_AS2,
NOTE_AS2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_C3,
NOTE_C3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_B2,
NOTE_B2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_B2,
NOTE_B2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_AS2,
NOTE_AS2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_C3,
NOTE_C3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
0,
NOTE_F5,
0,
NOTE_E5,
0,
NOTE_C5,
0,
NOTE_E5,
0,
NOTE_D5,
NOTE_G4,
NOTE_A4,
NOTE_C5,
0,
NOTE_F5,
0,
NOTE_E5,
0,
NOTE_C5,
0,
NOTE_E5,
0,
NOTE_D5,
NOTE_G4,
NOTE_A4,
NOTE_C5,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_CS2,
NOTE_CS2,
NOTE_CS2,
NOTE_CS2,
NOTE_CS2,
NOTE_CS2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_B2,
NOTE_B2,
NOTE_B2,
NOTE_B2,
NOTE_B2,
NOTE_B2,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_D2,
NOTE_CS2,
NOTE_CS2,
NOTE_CS2,
NOTE_CS2,
NOTE_CS2,
NOTE_CS2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_B2,
NOTE_B2,
NOTE_B2,
NOTE_B2,
NOTE_B2,
NOTE_B2,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_AS1,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_C2,
NOTE_D3,
NOTE_D3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_D3,
NOTE_D3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_AS2,
NOTE_AS2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_C3,
NOTE_C3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_D3,
NOTE_D3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_D3,
NOTE_D3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_AS2,
NOTE_AS2,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_C3,
NOTE_C3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_D3,
NOTE_D3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3,
NOTE_D3,
NOTE_D3,
NOTE_D4,
0,
NOTE_A3,
0,
NOTE_GS3,
0,
NOTE_G3,
0,
NOTE_F3,
NOTE_D3,
NOTE_F3,
NOTE_G3 };
const float PROGMEM BEATS_C[] = { 0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
1,
0.5,
1,
1,
1,
1,
2.5,
1,
0.5,
1,
1,
1,
0.25,
0.25,
0.5,
0.5,
0.5,
0.5,
1,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
4.5,
1,
0.5,
1,
1,
1,
1,
2.5,
1,
0.5,
1,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
4.5,
4,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.25,
0.25,
0.5,
1,
5,
1,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
1,
1,
1,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
4.5,
1,
1,
1,
1,
2,
2,
2,
2,
2,
2,
3,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
3.75,
0.25,
4,
4,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.25,
0.25,
0.5,
1,
5,
1,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
1,
1,
1,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
4.5,
1,
1,
1,
1,
2,
2,
2,
2,
2,
2,
3,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
3.75,
0.25,
4,
6,
2,
4,
4,
16,
6,
2,
4,
4,
16,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
1,
1,
0.5,
1,
1,
1,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5,
0.5,
1,
0.5,
0.5,
0.5 };
// We just set up the serial monitor, pins, and LCD here, then have the LCD print the first song.
void setup() {
Serial.begin(9600);
pinMode(upPin, INPUT);
pinMode(downPin, INPUT);
pinMode(playPin, INPUT);
pinMode(piezoPin, OUTPUT);
lcd.begin(16, 2);
printSong(0);
}
void loop() {
// We grab the state of each pin.
upState = digitalRead(upPin);
downState = digitalRead(downPin);
playState = digitalRead(playPin);
// The up and down buttons scroll through the list of songs, printing them to the screen.
if (upState == 1 && prevUpState == 0) {
if (currSong == 3) {
// If the user is already at the last song, scrolling up any further will loop them back around.
Serial.println("Looping back to the start.");
currSong = 0;
Serial.println(currSong);
printSong(0);
} else {
Serial.println("Moving back.");
currSong++;
Serial.println(currSong);
printSong(0);
}
}
if (downState == 1 && prevDownState == 0) {
if (currSong == 0) {
// If the user is already at the last song, scrolling down any further will loop them back around.
Serial.println("Looping back to the end.");
currSong = 3;
Serial.println(currSong);
printSong(0);
} else {
Serial.println("Moving forward.");
currSong--;
Serial.println(currSong);
printSong(0);
}
}
// Once the play button is hit, it sets songPlaying to true first, then plays the song corresponding to currSong. If a song is already playing, you cannot start a new one until it finishes.
if (playState == 1 && prevPlayState == 0 && songPlaying == false) {
songPlaying = true;
switch (currSong) {
// 0 - Eien no Ashita
case 0:
playSong(NOTES_A, 250, BEATS_A, 120);
break;
// 1 - KARMA
case 1:
playSong(NOTES_B, 555, BEATS_B, 155);
break;
// 2 - MEGALOVANIA
case 2:
playSong(NOTES_C, 813, BEATS_C, 240);
break;
// 3 - ASGORE
case 3:
playSong(NOTES_D, 705, BEATS_D, 115);
break;
case 4:
break;
}
}
// The previous button states are all plugged in.
prevUpState = upState;
prevDownState = downState;
prevPlayState = playState;
}
// This helper function plays a note of a specified frequency.
void playNote(int frequency, float beatCount, int tempo) {
// First, we calculate the duration; we start with 60000ms, which would be the length of a quarter note at 1 beat per minute. We calculate the amount of time the note should play for by dividing this number by the tempo, then multiplying it by the beats the note should last for.
float duration = (float)(60000 / tempo) * beatCount;
// With the duration calculated, we can finally play the note.
tone(piezoPin, frequency, duration);
// tone() does not wait for the note to finish, so we need a delay for the same amount of time the note lasts, that way the note is allowed to play out before the next one comes in.
delay(duration);
}
// This helper function manages rests.
void rest(float beatCount, int tempo) {
// We calculate the duration just like we did in playNote.
float duration = (float)(60000 / tempo) * beatCount;
// Here, we just delay for that duration.
delay(duration);
}
// This is where the magic happens. The function takes in a notes array, beat count array, tempo, and the length of the arrays (Which will both be equal).
void playSong(int notes[], int noteCount, float beatCounts[], int tempo) {
SingleLinkedList<int> song = SingleLinkedList<int>(true);
SingleLinkedList<float> beats = SingleLinkedList<float>(true);
for (byte i = 0; i < noteCount; i++) {
int currNote = pgm_read_word_near(notes + i);
float currBeatCount = pgm_read_float_near(beatCounts + i);
Serial.print("Note ");
Serial.print(i);
Serial.print(": ");
Serial.print(currNote);
Serial.print("(");
Serial.print(currBeatCount);
Serial.println(" beats)");
song.add(currNote);
beats.add(currBeatCount);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Loading...");
lcd.setCursor(0, 1);
lcd.print(i / noteCount);
lcd.print("%");
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Now Playing: ");
printSong(1);
for (int i = 0; i < noteCount; i++) {
// A 0 in the notes array indicates a rest. Otherwise, we plug the note frequency into playNote, along with the tempo and whatever number is in the beat count array at the same index.
Serial.println(i);
if (song[i] == 0) {
rest(beats[i], tempo);
} else {
playNote(song[i], beats[i], tempo);
}
}
}
void printSong(int line) {
if (line == 0) {
lcd.clear();
lcd.setCursor(0, 0);
} else {
lcd.setCursor(0, 1);
}
switch (currSong) {
case 0:
lcd.print("Eien no Ashita");
break;
case 1:
lcd.print("KARMA");
break;
case 2:
lcd.print("MEGALOVANIA");
break;
case 3:
lcd.print("ASGORE");
break;
}
}