Skip to content

Examples

Required Audio Files

The examples included in the WAV Trigger Pro Qwiic library assume users have an SD card with the demo tracks loaded onto it. You can download a copy of the audio tracks from the link below:

WAV Trigger Pro Arduino Example Sounds

The Arduino examples do not require a preset, just the specific tracks included in the link above. Just download these tracks, unzip the files and load them onto your µSD card and you're ready to get started with the Aruino examples.

Code to Note

All four examples include similar setups to initialize the WAV Trigger Pro on the I2C bus, return the firmware version string and number of available audio tracks. All of these steps have a message printed out over serial so to view them open the Arduino serial monitor with the baud set to 9600 to see these messages. If any of these fail, the code will print out "WAV Trigger Pro response not available".

Example 1 - Loop Track

The first example demonstrates how to loop a single track (in this case, a 440Hz sine wave) continuously. Open the example by navigating in Arduino to "File > Examples > SparkFun WAV Trigger Pro Qwiic > Example_01_Loop_Track" or copy the code below into a blank sketch.

Example 1 - Loop Track
// ****************************************************************************
//       Sketch: WAV Trigger Pro Qwiic Library Example 1
//               Loop a track
// Date Created: 1/6/2025
//
//     Comments: This example starts a single track looping.
//
//     Requires: The WAV Trigger Pro Arduino example tracks should be
//               installed on the microSD card:
//
//        Tracks  1 - 8: Spoken numbers
//       Tracks 48 - 84: Piano notes
//            Track 100: Stereo A440 Sine Wave, 8 secs
//            Track 101: Mono 1K Sine Wave, 8 secs
//            Track 102: Stereo ambient music
//            Track 103: Stereo acoustic guitar
//            Track 104: Dialog 1
//            Track 105: Dialog 2
//     Tracks 200 - 208: EDM percussion
//
// ****************************************************************************

#include "WAVTriggerPro.h"

#define LED 13  // Our LED

#define HEARTBEAT_PERIOD_MS 2000
#define POLLING_PERIOD_MS 500

// ****************************************************************************
// Global variables

WAVTriggerPro wtp;  // Our WAV Trigger Pro object

unsigned long gMsTick;
unsigned long gLastFlashMs;
int gLedTimeout = 0;
int gNumTracks = 0;

// Allocate a buffer for the version string
char gVersion[VERSION_STRING_LEN + 2];

// ****************************************************************************
// setup
// ****************************************************************************
void setup() {

  // Initialize the LED pin
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);

  Wire.begin();
  Serial.begin(9600);

  // Provide time for the WAV Trigger Pro to finish reset before trying to send
  //  any commands.
  delay(10);

  // WAV Trigger Pro initialization
  if (!wtp.begin()) {
    Serial.print("Could not start the WAV Trigger Pro\n");
  } else {
    Serial.print("\n*******************\n");
    Serial.print("Qwiic device found\n");
    Serial.print("Address: ");
    Serial.print(wtp.getAddress());
    Serial.print("\n");
  }

  // Issue a stop all tracks
  wtp.stopAll();
  delay(5);

  // Get the version string and number of available tracks
  if (wtp.getVersion(gVersion)) {
    Serial.print("Version: ");
    Serial.print(gVersion);
    Serial.print("\n");
    //delay(5);
    gNumTracks = wtp.getNumTracks();
    Serial.print("Number of tracks: ");
    Serial.print(gNumTracks);
    Serial.print("\n");
    //delay(5);
  } else
    Serial.print("WAV Trigger Pro response not available");

  gMsTick = millis();
  gLastFlashMs = gMsTick;

  // Start the A440 sine wave looping, -20dB, center, 1 second attack.
  wtp.trackPlayPoly(100, -20, BALANCE_MID, 1000, 0, LOOP_FLAG);

}

// ****************************************************************************
// loop
// ****************************************************************************
void loop() {

  // ================== MAIN LOOP TASK 1 ===================
  // Flash the hearbeat LED
  if ((gMsTick - gLastFlashMs) > HEARTBEAT_PERIOD_MS) {
    gLastFlashMs = gMsTick;
    gLedTimeout = 25;
    digitalWrite(LED, 1);
  }


  // ================== MAIN LOOP TASK 2 ===================
  // Keep gMsTick up to date
  if (millis() > gMsTick) {
    gMsTick = millis();
    if (gLedTimeout > 0) {
      if (--gLedTimeout == 0) {
        digitalWrite(LED, 0);
      }
    }
  }
}

The example initializes the WAV Trigger Pro over I2C along with the other checks outlined above and then plays the sine wave file on loop at -20dB in stereo (centered), with a 1 second attack using the command: wtp.trackPlayPoly(100, -20, BALANCE_MID, 1000, 0, LOOP_FLAG);

Example 2 - Play Tracks

The second example demonstrates how to loop through a sequence of tracks. It continuously plays the eight spoken number tracks in sequential order alternating output between the left and right audio channels.

Example 2 - Play Tracks
// ****************************************************************************
//       Sketch: WAV Trigger Pro Qwiic Library Example 2
//               Playing tracks
// Date Created: 1/3/2025
//
//     Comments: This example continuously plays the eight spoken number
//               tracks in order, to alternating left right output channels.
//
//     Requires: The WAV Trigger Pro Arduino example tracks should be
//               installed on the microSD card:
//
//        Tracks  1 - 8: Spoken numbers
//       Tracks 48 - 84: Piano notes
//            Track 100: Stereo A440 Sine Wave, 8 secs
//            Track 101: Mono 1K Sine Wave, 8 secs
//            Track 102: Stereo ambient music
//            Track 103: Stereo acoustic guitar
//            Track 104: Dialog 1
//            Track 105: Dialog 2
//     Tracks 200 - 208: EDM percussion
//
// ****************************************************************************

#include "WAVTriggerPro.h"

#define LED 13  // Our LED

#define HEARTBEAT_PERIOD_MS 2000
#define POLLING_PERIOD_MS 500

// ****************************************************************************
// Global variables

WAVTriggerPro wtp;  // Our WAV Trigger Pro object

unsigned long gMsTick;
unsigned long gLastFlashMs;
unsigned long gLastPollMs;
int gLedTimeout = 0;
int gNumTracks = 0;
int gNumActiveVoices = 0;
int gTrackNum;
int gBalance;

// Allocate a buffer for the version string
char gVersion[VERSION_STRING_LEN + 2];

// ****************************************************************************
// setup
// ****************************************************************************
void setup() {

  // Initialize the LED pin
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);

  Wire.begin();
  Serial.begin(9600);

  // Provide time for the WAV Trigger Pro to finish reset before trying to send
  //  any commands.
  delay(10);

  // WAV Trigger Pro initialization
  if (!wtp.begin()) {
    Serial.print("Could not start the WAV Trigger Pro\n");
  } else {
    Serial.print("\n*******************\n");
    Serial.print("Qwiic device found\n");
    Serial.print("Address: ");
    Serial.print(wtp.getAddress());
    Serial.print("\n");
  }

  // Issue a stop all tracks
  wtp.stopAll();
  delay(5);

  // Get the version string and number of available tracks
  if (wtp.getVersion(gVersion)) {
    Serial.print("Version: ");
    Serial.print(gVersion);
    Serial.print("\n");
    //delay(5);
    gNumTracks = wtp.getNumTracks();
    Serial.print("Number of tracks: ");
    Serial.print(gNumTracks);
    Serial.print("\n");
    //delay(5);
  } else
    Serial.print("WAV Trigger Pro response not available");

  gMsTick = millis();
  gLastFlashMs = gMsTick;
  gLastPollMs = gMsTick;
  gTrackNum = 0;
  gBalance = 0;
}

// ****************************************************************************
// loop
// ****************************************************************************
void loop() {

  // ================== MAIN LOOP TASK 1 ===================
  // Play next track when the previous is finished
  if ((gMsTick - gLastPollMs) > POLLING_PERIOD_MS) {
    gLastPollMs = gMsTick;

    // Wait for no tracks playing
    gNumActiveVoices = wtp.getNumActiveVoices();
    if (gNumActiveVoices == 0) {
      if (++gTrackNum > 8)
        gTrackNum = 1;

      Serial.print("Play track: ");
      Serial.print(gTrackNum);
      Serial.print("\n");

      wtp.trackPlayPoly(gTrackNum, 0, gBalance, 0, 0, 0);

      // Next track should be to the opposite channel
      if (gBalance > 0)
        gBalance = 0;
      else
        gBalance = 127;
    }
  }

  // ================== MAIN LOOP TASK 2 ===================
  // Flash the hearbeat LED
  if ((gMsTick - gLastFlashMs) > HEARTBEAT_PERIOD_MS) {
    gLastFlashMs = gMsTick;
    gLedTimeout = 25;
    digitalWrite(LED, 1);
  }


  // ================== MAIN LOOP TASK 3 ===================
  // Keep gMsTick up to date
  if (millis() > gMsTick) {
    gMsTick = millis();
    if (gLedTimeout > 0) {
      if (--gLedTimeout == 0) {
        digitalWrite(LED, 0);
      }
    }
  }
}

Example 3 - Mix Tracks

The third example shows how to mix several tracks to play together. It starts the mix with an ambient music track, then plays a dialog track followed by a fade into a second music track.

Example 3 - Mix Tracks
// ****************************************************************************
//       Sketch: WAV Trigger Pro Qwiic Library Example 3
//               Mixing tracks
// Date Created: 1/3/2025
//
//     Comments: This example combines music and dialog tracks.
//
//     Requires: The WAV Trigger Pro Arduino example tracks should be
//               installed on the microSD card:
//
//        Tracks  1 - 8: Spoken numbers
//       Tracks 48 - 84: Piano notes
//            Track 100: Stereo A440 Sine Wave, 8 secs
//            Track 101: Mono 1K Sine Wave, 8 secs
//            Track 102: Stereo ambient music
//            Track 103: Stereo acoustic guitar
//            Track 104: Dialog 1
//            Track 105: Dialog 2
//     Tracks 200 - 208: EDM percussion
//
// ****************************************************************************

#include "WAVTriggerPro.h"

#define LED 13  // Our LED

#define HEARTBEAT_PERIOD_MS 2000
#define POLLING_PERIOD_MS 100

// ****************************************************************************
// Global variables

WAVTriggerPro wtp;  // Our WAV Trigger Pro object

unsigned long gMsTick;
unsigned long gLastFlashMs;
unsigned long gLastPollMs;
int gLedTimeout = 0;
int gNumTracks = 0;
int gNumActiveVoices = 0;
int gDelayCount = 0;
int gState = 0;

// Allocate a buffer for the version string
char gVersion[VERSION_STRING_LEN + 2];

// ****************************************************************************
// setup
// ****************************************************************************
void setup() {

  // Initialize the LED pin
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);

  Wire.begin();
  Serial.begin(9600);

  // Provide time for the WAV Trigger Pro to finish reset before trying to send
  //  any commands.
  delay(10);

  // WAV Trigger Pro initialization
  if (!wtp.begin()) {
    Serial.print("Could not start the WAV Trigger Pro\n");
  } else {
    Serial.print("\n*******************\n");
    Serial.print("Qwiic device found\n");
    Serial.print("Address: ");
    Serial.print(wtp.getAddress());
    Serial.print("\n");
  }

  // Issue a stop all tracks
  wtp.stopAll();
  delay(5);

  // Get the version string and number of available tracks
  if (wtp.getVersion(gVersion)) {
    Serial.print("Version: ");
    Serial.print(gVersion);
    Serial.print("\n");
    //delay(5);
    gNumTracks = wtp.getNumTracks();
    Serial.print("Number of tracks: ");
    Serial.print(gNumTracks);
    Serial.print("\n");
    //delay(5);
  } else
    Serial.print("WAV Trigger Pro response not available");

  gMsTick = millis();
  gLastFlashMs = gMsTick;
  gLastPollMs = gMsTick;
  gDelayCount = 10;
  gState = 0;
}

// ****************************************************************************
// loop
// ****************************************************************************
void loop() {

  // ================== MAIN LOOP TASK 1 ===================
  // Proceed to the next state when the time comes
  if ((gMsTick - gLastPollMs) > POLLING_PERIOD_MS) {
    gLastPollMs = gMsTick;

    // Process according to state
    switch (gState) {

      // State 0: start the ambient music
      case 0:
        if (gDelayCount > 0)
          gDelayCount--;
        else {
          Serial.println("Starting music 1");
          wtp.trackPlayPoly(102, 0, BALANCE_MID, 0, 0, 0);
          gState++;
          gDelayCount = 60;  // Delay 6 seconds
        }
        break;

      // State 1: start dialog 2 track
      case 1:
        if (gDelayCount > 0)
          gDelayCount--;
        else {
          Serial.println("Starting dialog 1");
          wtp.trackPlayPoly(105, 0, BALANCE_MID, 0, 0, 0);
          gState++;
        }
        break;

      // State 2: wait for dialog track to finish
      case 2:
        if (wtp.trackGetStatus(105) == 0) {
          Serial.println("Cross-fading to music 2 ");
          wtp.trackPlayPoly(103, 0, BALANCE_MID, 4000, 0, 0);
          gState++;
          gDelayCount = 20;  // Delay 1 second
        }
        break;

      // State 3: crossfade to music 2
      case 3:
        if (gDelayCount > 0)
          gDelayCount--;
        else {
          wtp.trackStop(102, 4000);
          gState++;
          gDelayCount = 30;
        }
        break;

      // Do nothing
      default:
        break;
    }
  }

  // ================== MAIN LOOP TASK 2 ===================
  // Flash the hearbeat LED
  if ((gMsTick - gLastFlashMs) > HEARTBEAT_PERIOD_MS) {
    gLastFlashMs = gMsTick;
    gLedTimeout = 25;
    digitalWrite(LED, 1);
  }


  // ================== MAIN LOOP TASK 3 ===================
  // Keep gMsTick up to date
  if (millis() > gMsTick) {
    gMsTick = millis();
    if (gLedTimeout > 0) {
      if (--gLedTimeout == 0) {
        digitalWrite(LED, 0);
      }
    }
  }
}

Example 4 - MIDI

The fourth example demonstrates how to use MIDI commands to play tracks on the WAV Trigger Pro. The example cycles between playing a combination of tracks to create a piano chord, percussion tracks and a second piano chord.

Example 4 - MIDI
// ****************************************************************************
//       Sketch: WAV Trigger Pro Qwiic Library Example 3
//               Using MIDI
// Date Created: 1/3/2025
//
//     Comments: This example uses MIDI to play tracks.
//
//     Requires: The WAV Trigger Pro Arduino example tracks should be
//               installed on the microSD card:
//
//        Tracks  1 - 8: Spoken numbers
//       Tracks 48 - 84: Piano notes
//            Track 100: Stereo A440 Sine Wave, 8 secs
//            Track 101: Mono 1K Sine Wave, 8 secs
//            Track 102: Stereo ambient music
//            Track 103: Stereo acoustic guitar
//            Track 104: Dialog 1
//            Track 105: Dialog 2
//     Tracks 200 - 208: EDM percussion
//
// ****************************************************************************

#include "WAVTriggerPro.h"

#define LED 13  // Our LED

#define HEARTBEAT_PERIOD_MS 2000
#define POLLING_PERIOD_MS 100

#define TEMPO_PERIOD 10

#define MIDI_NOTE_ON 0x90
#define MIDI_NOTE_OFF 0x80

#define NOTE_01 50
#define NOTE_02 54
#define NOTE_03 57

#define NOTE_11 49
#define NOTE_12 52
#define NOTE_13 56

#define NOTE_21 115
#define NOTE_22 112


// ****************************************************************************
// Global variables

WAVTriggerPro wtp;  // Our WAV Trigger Pro object

unsigned long gMsTick;
unsigned long gLastFlashMs;
unsigned long gLastPollMs;
int gLedTimeout = 0;
int gNumTracks = 0;
int gNumActiveVoices = 0;
int gDelayCount = 0;
int gState = 0;

// Allocate a buffer for the version string
char gVersion[VERSION_STRING_LEN + 2];

// ****************************************************************************
// setup
// ****************************************************************************
void setup() {

  // Initialize the LED pin
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);

  Wire.begin();
  Serial.begin(9600);

  // Provide time for the WAV Trigger Pro to finish reset before trying to send
  //  any commands.
  delay(10);

  // WAV Trigger Pro initialization
  if (!wtp.begin()) {
    Serial.print("Could not start the WAV Trigger Pro\n");
  } else {
    Serial.print("\n*******************\n");
    Serial.print("Qwiic device found\n");
    Serial.print("Address: ");
    Serial.print(wtp.getAddress());
    Serial.print("\n");
  }

  // Issue a stop all tracks
  wtp.stopAll();
  delay(5);

  // Get the version string and number of available tracks
  if (wtp.getVersion(gVersion)) {
    Serial.print("Version: ");
    Serial.print(gVersion);
    Serial.print("\n");
    //delay(5);
    gNumTracks = wtp.getNumTracks();
    Serial.print("Number of tracks: ");
    Serial.print(gNumTracks);
    Serial.print("\n");
    //delay(5);
  } else
    Serial.print("WAV Trigger Pro response not available");

  gMsTick = millis();
  gLastFlashMs = gMsTick;
  gLastPollMs = gMsTick;
  gDelayCount = 10;
  gState = 0;
}

// ****************************************************************************
// loop
// ****************************************************************************
void loop() {

  // ================== MAIN LOOP TASK 1 ===================
  // Proceed to the next state when the time comes
  if ((gMsTick - gLastPollMs) > POLLING_PERIOD_MS) {
    gLastPollMs = gMsTick;

    // Process according to state
    switch (gState) {

      // State 0: Play the first chord
      case 0:
        if (gDelayCount > 0)
          gDelayCount--;
        else {
          Serial.println("Playing chord 1");
          wtp.sendMidiMsg(MIDI_NOTE_OFF, NOTE_11, 0);
          wtp.sendMidiMsg(MIDI_NOTE_OFF, NOTE_12, 0);
          wtp.sendMidiMsg(MIDI_NOTE_OFF, NOTE_13, 0);
          wtp.sendMidiMsg(MIDI_NOTE_ON, NOTE_01, 100);
          delay(50);
          wtp.sendMidiMsg(MIDI_NOTE_ON, NOTE_02, 100);
          delay(50);
          wtp.sendMidiMsg(MIDI_NOTE_ON, NOTE_03, 100);
          gState++;
          gDelayCount = TEMPO_PERIOD;  // Delay 3
        }
        break;

      case 1:
        if (gDelayCount > 0)
          gDelayCount--;
        else {
          Serial.println("Playing perc 1");
          wtp.sendMidiMsg(MIDI_NOTE_OFF, NOTE_21, 0);
          wtp.sendMidiMsg(MIDI_NOTE_OFF, NOTE_22, 0);
          wtp.sendMidiMsg(MIDI_NOTE_ON, NOTE_21, 100);
          gState++;
          gDelayCount = TEMPO_PERIOD;  // Delay 3
        }
        break;

      // State 1: Play the second chord
      case 2:
        if (gDelayCount > 0)
          gDelayCount--;
        else {
          Serial.println("Playing chord 2");
          wtp.sendMidiMsg(MIDI_NOTE_OFF, NOTE_01, 0);
          wtp.sendMidiMsg(MIDI_NOTE_OFF, NOTE_02, 0);
          wtp.sendMidiMsg(MIDI_NOTE_OFF, NOTE_03, 0);
          wtp.sendMidiMsg(MIDI_NOTE_ON, NOTE_11, 85);
          wtp.sendMidiMsg(MIDI_NOTE_ON, NOTE_12, 85);
          wtp.sendMidiMsg(MIDI_NOTE_ON, NOTE_13, 85);
          gState++;
          gDelayCount = TEMPO_PERIOD;  // Delay
        }
        break;

      case 3:
        if (gDelayCount > 0)
          gDelayCount--;
        else {
          Serial.println("Playing perc 2");
          wtp.sendMidiMsg(MIDI_NOTE_ON, NOTE_22, 100);
          gState = 0;
          gDelayCount = TEMPO_PERIOD;  // Delay
        }
        break;

      // Do nothing
      default:
        break;
    }
  }

  // ================== MAIN LOOP TASK 2 ===================
  // Flash the hearbeat LED
  if ((gMsTick - gLastFlashMs) > HEARTBEAT_PERIOD_MS) {
    gLastFlashMs = gMsTick;
    gLedTimeout = 25;
    digitalWrite(LED, 1);
  }


  // ================== MAIN LOOP TASK 3 ===================
  // Keep gMsTick up to date
  if (millis() > gMsTick) {
    gMsTick = millis();
    if (gLedTimeout > 0) {
      if (--gLedTimeout == 0) {
        digitalWrite(LED, 0);
      }
    }
  }
}

The main loop plays these tracks by sending a MIDI message for the selected tracks using the sendMidiMsg function.