Stopping a song mid-play with button

So I just started playing with a piezo buzzer and the tone() function and I managed to write some songs with it. Basically the song starts at the press of a button, but I was wondering if I could stop it while it's playing with a press of the same button. Here is the code:

#define B0  31
#define C1  33
#define CS1 35
#define D1  37
#define DS1 39
#define E1  41
#define F1  44
#define FS1 46
#define G1  49
#define GS1 52
#define A1  55
#define AS1 58
#define B1  62
#define C2  65
#define CS2 69
#define D2  73
#define DS2 78
#define E2  82
#define F2  87
#define FS2 93
#define G2  98
#define GS2 104
#define A2  110
#define AS2 117
#define B2  123
#define C3  131
#define CS3 139
#define D3  147
#define DS3 156
#define E3  165
#define F3  175
#define FS3 185
#define G3  196
#define GS3 208
#define A3  220
#define AS3 233
#define B3  247
#define C4  262
#define CS4 277
#define D4  294
#define DS4 311
#define E4  330
#define F4  349
#define FS4 370
#define G4  392
#define GS4 415
#define A4  440
#define AS4 466
#define B4  494
#define C5  523
#define CS5 554
#define D5  587
#define DS5 622
#define E5  659
#define F5  698
#define FS5 740
#define G5  784
#define GS5 831
#define A5  880
#define AS5 932
#define B5  988
#define C6  1047
#define CS6 1109
#define D6  1175
#define DS6 1245
#define E6  1319
#define F6  1397
#define FS6 1480
#define G6  1568
#define GS6 1661
#define A6  1760
#define AS6 1865
#define B6  1976
#define C7  2093
#define CS7 2217
#define D7  2349
#define DS7 2489
#define E7  2637
#define F7  2794
#define FS7 2960
#define G7  3136
#define GS7 3322
#define A7  3520
#define AS7 3729
#define B7  3951
#define C8  4186
#define CS8 4435
#define D8  4699
#define DS8 4978

 int button = 2;
#define melodyPin 3

int melody[] = {
  D4, E4, F4, E4, D4, A4, A4, G4, F4, E4, D4, E4, F4, G4, A4, D5, CS5, D5, E5, D4, E4, F4, E4, D4, A4, A4, G4, F4, E4, D4, E4, F4, G4, A4, D5, CS5, D5, E5, CS5, D5, 
  
};

int tempo[] = {
  16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 8, 8, 8, 8, 4, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 8, 8, 16, 16, 16, 16, 2, 
};

int underworld_melody[] = {
  D5, E5, F5, E5, D5, A4, AS4, A4, AS4, A4, D5, E5, F5, E5, D5, A4, AS4, A4, AS4, A4, F5, D5, AS4, A4, F5, D5, AS4, A4, F5, D5, AS4, A4, G4, A4, F4, E4,
};
//Underwolrd tempo
int underworld_tempo[] = {
  16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 5, 5,  
};
 
void setup(void)
{
 Serial.begin(9600);
  pinMode(3, OUTPUT);//buzzer
  pinMode(2, INPUT);//led indicator when singing a note

}
void loop()
{
 
 if (digitalRead(button) == 1) {
 //sing the tunes
  sing(1);
 delay(25);
 sing(2);
 delay(25);
 sing(1); 
 } 
}
int song = 0;
 
void sing(int s) {
  // iterate over the notes of the melody:
  song = s;
  if (song == 2) {
    Serial.println(" 'Underworld Theme'");
    int size = sizeof(underworld_melody) / sizeof(int);
    for (int thisNote = 0; thisNote < size; thisNote++) {
 
      // to calculate the note duration, take one second
      // divided by the note type.
      //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
      int noteDuration = 1000 / underworld_tempo[thisNote];
 
      buzz(melodyPin, underworld_melody[thisNote], noteDuration);
 
      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
 
      // stop the tone playing:
      buzz(melodyPin, 0, noteDuration);
 
    }
 
  } else {
 
    Serial.println(" 'Mario Theme'");
    int size = sizeof(melody) / sizeof(int);
    for (int thisNote = 0; thisNote < size; thisNote++) {
 
      // to calculate the note duration, take one second
      // divided by the note type.
      //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
      int noteDuration = 1000 / tempo[thisNote];
 
      buzz(melodyPin, melody[thisNote], noteDuration);
 
      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
 
      // stop the tone playing:
      buzz(melodyPin, 0, noteDuration);
 
    }
  }
}
 
void buzz(int targetPin, long frequency, long length) {
  digitalWrite(13, HIGH);
  long delayValue = 1000000 / frequency / 2; // calculate the delay value between transitions
  //// 1 second's worth of microseconds, divided by the frequency, then split in half since
  //// there are two phases to each cycle
  long numCycles = frequency * length / 1000; // calculate the number of cycles for proper timing
  //// multiply frequency, which is really cycles per second, by the number of seconds to
  //// get the total number of cycles to produce
  for (long i = 0; i < numCycles; i++) { // for the calculated length of time...
    digitalWrite(targetPin, HIGH); // write the buzzer pin high to push out the diaphram
    delayMicroseconds(delayValue); // wait for the calculated delay value
    digitalWrite(targetPin, LOW); // write the buzzer pin low to pull back the diaphram
    delayMicroseconds(delayValue); // wait again or the calculated delay value
  }
  digitalWrite(13, LOW);
 
}

So... any help on doing that? Any bit of help is appreciated.
Thanks in advance.

Before you ask, the code is "semi-stolen" from a Super Mario theme, hence the "overworld" and "underworld" titles :slight_smile:

The proper answer is to write the code as a state machine using the technique shown in the blink without delay example in the IDE.

The problem is that while you are using the delay function nothing happens. Also their is not a single place where the button can be looked at.

Another way is to replace the delay function with one of your own functions that returns when the time is up or it sees the button is pressed. Then at the end of the loop function have a small loop that holds until the button is released.