#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