#include <Toggle.h>
#include "melodies.h" // in another file for readability
struct Melody {
int * melody;
size_t noteCnt;
int tempo;
};
Melody songList[] = {
{tetris, (sizeof tetris / sizeof * tetris) / 2, 144},
{zelda, (sizeof zelda / sizeof * zelda) / 2, 88},
{ode, (sizeof ode / sizeof * ode) / 2, 200},
{godfather, (sizeof godfather / sizeof * godfather) / 2, 80},
};
size_t melodyCnt = sizeof songList / sizeof * songList;
size_t currentSong = 0;
const byte buzzerPin = 11;
const byte previousSongPin = A0;
const byte nextSongPin = A1;
Toggle nextSongBtn, previousSongBtn;
int currentNote = 0;
unsigned long previousNoteTime = 0;
unsigned long noteDuration = 0;
bool notePlaying = false;
void playNextNote() {
Melody& activeMelody = songList[currentSong];
int wholenote = (60000L * 4) / activeMelody.tempo;
int divider = 0;
if (currentNote < activeMelody.noteCnt * 2) {
divider = activeMelody.melody[currentNote + 1];
if (divider > 0) {
noteDuration = wholenote / divider;
} else if (divider < 0) {
noteDuration = wholenote / abs(divider);
noteDuration *= 1.5;
}
tone(buzzerPin, activeMelody.melody[currentNote], noteDuration * 0.9);
previousNoteTime = millis();
notePlaying = true;
currentNote += 2;
} else {
// All notes played, stop playing
currentNote = 0;
notePlaying = false;
}
}
void resetMelodyState() {
noTone(buzzerPin);
currentNote = 0;
notePlaying = false;
Serial.print("active Song = ");
Serial.println(currentSong);
}
void setup() {
Serial.begin(115200);
pinMode(buzzerPin, OUTPUT);
nextSongBtn.begin(nextSongPin);
previousSongBtn.begin(previousSongPin);
resetMelodyState();
}
void loop() {
nextSongBtn.poll();
previousSongBtn.poll();
if (nextSongBtn.onPress()) {
currentSong = (currentSong + 1) % melodyCnt;
resetMelodyState();
}
if (previousSongBtn.onPress()) {
currentSong = (currentSong - 1 + melodyCnt) % melodyCnt;
resetMelodyState();
}
if (!notePlaying) {
playNextNote();
} else {
if (millis() - previousNoteTime >= noteDuration) {
noTone(buzzerPin);
notePlaying = false;
}
}
}
NEXT
PREV