Play a tone in the "background"

Hey guys, just wondering if there was a way to play a melody in the background.

At the moment the melody (using "tone") plays (approx. 10 secs) but interrupts the flow of the program - not good for what I want to do.

Is the melody able to be uploaded into memory, then called on without interrupting the rest of the program?

Pointers in the right direction would be appreciated.

Cheers.

Hey guys, just wondering if there was a way to play a melody in the background.

On a single threaded system, there is no "background". So, no.

There ARE ways to notice that a tone has finished playing and that another one needs to start, while doing something else.

At the moment the melody (using "tone") plays (approx. 10 secs) but interrupts the flow of the program - not good for what I want to do.

So, you have some code you didn't share...

Is the melody able to be uploaded into memory, then called on without interrupting the rest of the program?

Not that way.

Pointers in the right direction would be appreciated.

char *pointer1 = "In the right direction";
char *pointer2 = "In the right direction";

Thanks Paul,

It's getting late here, so I will post the code tomorrow because I would like to give a reasonable explanation of the algorithm and programming (right or wrong) behind it.

I think the algorithm is ok, it's just a matter of using the tools at hand (Arduino) to get the job done.

btw. thanks for the pointers :slight_smile:

Cheers.

btw. thanks for the pointers

I'm glad you got the joke.

The closest to doing it "in the background" that I can think of would be to use one of the pins associated with a particular hardware timer. That way you could configure the processor to emit a tone without any software intervention. But to play a melody you would still have to step in at the appropriate time to change what the timer is outputting. To do that you could use a second timer and an interrupt routine to step through a sequence of tones of specified duration. The interruptions would be relatively brief and infrequent.

That way you could play a melody similarly to how you can write a string with Serial. That is, you could send the melody "string" and it would play while your code continued on its merry way.

Not very pretty, but this will check for events during rests and between notes - The "song" is in Flash to save space.

byte playTune(int *tune)
{
  //Non-blocking tune player that waits for a press of the mode button.
  // returns 0 if normal return, -1 if mode button hit.
  int curr_note = 0;
  unsigned long curr_time = 0;
  unsigned long noteDuration = 0;
  
  while ( pgm_read_word_near(tune + curr_note)!= -1)
  {
    // to calculate the note duration, take one second 
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    noteDuration = 1000/pgm_read_word_near(tune + curr_note+1); //+1 to get following duration

    if (pgm_read_word_near(tune + curr_note) == REST_00) {
      curr_time = millis();
      while ((millis() - curr_time) < noteDuration)
      {
        // if mode is pressed, quit
        if (digitalRead(butMode) == LOW)
        {
          return -1;
        }
      }
    } 
    else {
      tone(Speaker, pgm_read_word_near(tune + curr_note), noteDuration);
    }

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 130 / 100;
    curr_time = millis();

    while ((millis() - curr_time) < pauseBetweenNotes)
    {
      // if mode is pressed, quit
      if (digitalRead(butMode) == LOW)
      {
        return -1;
      }
    }


    curr_note = curr_note + 2; // To skip the duration
  }
  
  return 0;
}