Best solution for music and tones?

Hi,

What is the best solution for a simple background tune and some tones?

I guess ArduboyPlaytune is the best fit but I cannot find a way to use a tone with 2 notes like in ArduboyTones, example
freq 900,100 ms ---> silence 20 ms ---> freq 1200, 100 ms

Do I have to handle the timing with millis?

Thanks!

If you can pause the action while the tones are playing, you can use Arduino delay() or Arduboy2 delayShort() to wait for each tone to play.

Arduboy2 arduboy;
ArduboyPlaytune tunes(arduboy.audio.enabled);

tunes.tone(900, 100);
arduboy.delayShort(900 + 20);
tunes.tone(1200, 100);

If you want the action to continue while the tones are playing, you’ll have to use a timer or counter to delay for a certain time before starting the next tone. If your sketch uses Arduboy2 nextFrame() you could create a non-blocking delay function using frameCount, which increments once per frame. You would only be have a time resolution of one frame length but this may be sufficient.

Essentially what you’re doing is creating your own tone playing sequencer within the sketch which reads tones, durations and delays from an array (which could be in PROGMEM).


// global variables
boolean tonesPlaying = false;
unsigned int toneDelay;

void loop() {
  if (!arduboy.nextFrame())
    return;

  if (tonesPlaying && (arduboy.frameCount == toneDelay)) {
    nextTone();
  }

  // play a tone sequence here
  if (needToPlayTones) {
    startTones(toneArray);
  }

  // rest of loop()

}

void startTones(??? * toneSequence) {
  // This function derives a frequency, duration and delay count from toneSequence[].
  // toneSequence[] could have some kind of terminator (such as 0 instead of a
  // frequency value to know that the sequence is done.
  // Global variables created to keep track of the position in toneSequence[] will be
  // initialised here.
  playTone(frequency, duration, delayCount);
  tonesPlaying = true;
}

void nextTone() {
  // Read the next values from toneSequence[] and update the sequence position
  if (/* terminator detected */) {
    tonesPlaying = false;
  }
  else {
    playTone(frequency, duration, delayCount);
  }
    
void playTone(unsigned int frequency, unsigned int duration, unsigned int delayCount) {
  tunes.tone(frequency, duration);
  toneDelay = arduboy.frameCount + delayCount;
}
2 Likes

Thanks, I guess that is why I just find 1 tone sound examples :smile:

Continuing the discussion from Back to the Jungle: Entry for the Jam:

It probably wouldn’t be hard to add a tonePlaying() function, similar to playing(). This would simplify my “in sketch” technique by eliminating the need to do a delay within the sketch for each tone’s duration.

Adding multi-tone sequence capability to ArduboyPlaytune wouldn’t necessarily be difficult either but it may increase the code footprint significantly enough to put some existing sketches which use the library over the limit.

Yes I know, I will check for how much. This would allow the games to use “soundeffects” libraries much like the music now

I think this is just:

boolean ArduboyPlaytune::tonePlaying()
{
  return tone_playing;
}