ok I kind of solved this problem. I changed the playSong function to the following:
void playSong(int currentSong){
Serial.println("playing");
TIMSK1 = 0; // turn timer for ir interrupts off initially
delay(200);
for (int i = 0; i < songs[currentSong].totalNotes; i++)
{
TIMSK1 = 1; // before every note check for 6.7 milliseconds if any button is pressed, if so stop playing
IrReceiver.begin(RECEIVER, ENABLE_LED_FEEDBACK);
unsigned long startMicros = micros();
while (micros() - startMicros < 6700) {
if (IrReceiver.decode()) {
Serial.println("received ir while playing");
play = false;
IrReceiver.resume();
return;
}
}
TIMSK1 = 0;
const int currentNoteLeft = songs[currentSong].notesLeft[i];
const int currentNoteRight = songs[currentSong].notesRight[i];
float wait = songs[currentSong].durations[i] / songs[currentSong].speed;
if (currentNoteLeft != 0 && currentNoteRight != 0)
{
play2Notes(buzzerPin1, buzzerPin2, currentNoteLeft, currentNoteRight, wait);
}
else
{
if (currentNoteLeft == 0){
if (currentNoteRight == 0 ){
noNote(buzzerPin1, wait);
} else{
playNote(buzzerPin2, currentNoteRight, wait);
}
} else {
playNote(buzzerPin1, currentNoteLeft, wait);
}
}
}
play = false;
IrReceiver.begin(RECEIVER, ENABLE_LED_FEEDBACK);
}
(im using version 4 of the ir remote library now. it claims to be faster.)
so now, before every note, i only check for a very short amount of time if a button is pressed. if so, the song stops playing.
to do that im only turning on the timer1 (usually the ir library uses timer2 i think, but i changed it to 1) before every note and wait for ir signals for 6.7ms. i dont know why, but I also had to call the IrReceiver.begin function again after turning off the timer. stopping the song can take a few seconds if there are long notes, but it works.
if there is a better solution, hit me up pls.
i dont know if there is one, but if the tone library claims to be compatible with the IR receiver...