Multiple WAV files on SD card not working.

Not open for further replies.


I cobbled together this code on another thread and it basically does what I want. It works with 4 or 5 files, but i thought I could just add my own many as I like...20 wav files...nothing very long or big in size. And it doesn't really work. It plays a couple of files but only sometimes. I also had a real hard time with SD cards. I had three and only one would work. Formatted to FAT32. These were SanDisk Ultra 32G. It wasn't until I switched to a Pioneer 16G that I got it to work. Is it something with the SD cards? the formatting? the WAV files? or is it the code?

I thought I could just change the filenames and the wavnum and I could run a bunch of only seems to work with the original 4 or 5 files.

thanks, steve

  #include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>

// create audio component objects
AudioPlaySdWav           playWav1;           // SD card wav file player
AudioInputI2S            audioInput;         // audio shield input, mic or line-in selectable
AudioMixer4              mixer1;             // mixers to combine wav file and audio shield inputs
AudioMixer4              mixer2;

// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
AudioOutputI2S           audioOutput;
//AudioOutputSPDIF       audioOutput;
//AudioOutputAnalog      audioOutput;

// wire up the interfaces between audio components with patch cords
// mixer inputs
AudioConnection          patchCord1(playWav1, 0, mixer1, 0);          // left  channels into mixer 1
AudioConnection          patchCord2(audioInput, 0, mixer1, 1);

AudioConnection          patchCord3(playWav1, 1, mixer2, 0);          // right channels into mixer 2
AudioConnection          patchCord4(audioInput, 1, mixer2, 1);

// mixer outputs
AudioConnection          patchCord5(mixer1, 0, audioOutput, 0);
AudioConnection          patchCord6(mixer2, 0, audioOutput, 1);

// object to allow control of the SGTL5000 audio shield settings
AudioControlSGTL5000     audioShield;

// buttons and potentiometers
#define pot0             A1
#define pot1             A2
#define pot2             A3
#define button0          0
#define button1          1
#define button2          2
//#define button3          27

// attach button debouncers to input buttons
Bounce db_button0 = Bounce(button0, 30);
Bounce db_button1 = Bounce(button1, 30);
Bounce db_button2 = Bounce(button2, 30);
//Bounce db_button3 = Bounce(button3, 30);

// choose mic or line input for audio shield input path
const int inputChSelect = AUDIO_INPUT_MIC;
//const int inputChSelect = AUDIO_INPUT_LINEIN;

// audio shield volume
int masterVolume        = 0;

// uncomment one set of SD card SPI pins to use
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN     10
#define SDCARD_MOSI_PIN   7
#define SDCARD_SCK_PIN    14

// wav filenames on SD card for playback
char *wavFiles[]       = {"CM.000.WAV", "SDTEST1.WAV", "SDTEST2.WAV", "SDTEST3.WAV", "SDTEST4.WAV"};
byte wavNum            = 0;      // current wav file index playing from array list
bool wavIsPlaying      = false;  // track if a wav file is currently playing or not

void setup() {
  Serial.println("SD Player Demo\n");

  // buttons are inputs with pullups
  pinMode(button0, INPUT_PULLUP);
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  //pinMode(button3, INPUT_PULLUP);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example

  // comment these out if not using the audio adaptor board.
  Serial.print("init audio shield...");
  audioShield.inputSelect(inputChSelect);  // select mic or line-in for audio shield input source

  mixer1.gain(0, 0.5);
  mixer1.gain(1, 0.5);
  mixer1.gain(2, 0);
  mixer1.gain(3, 0);

  mixer2.gain(0, 0.5);
  mixer2.gain(1, 0.5);
  mixer2.gain(2, 0);
  mixer2.gain(3, 0);

  Serial.print("init SD card...");
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here, but print a message
    Serial.println("Unable to access the SD card.  Program halted.");
    while (1);
  Serial.println("Waiting for control input...");

  // reset audio resource usage stats.
  // useful if tracking max usage in main program

void playFile(const char *filename)
  Serial.print("Start playing file: ");

  // start playing the file.
  // sketch continues to run while the file plays.;

  // A brief delay for the library to read WAV header info

void loop() {

  // auto select next wav file if current file finishes playing
  // and if playback is enabled
  if ((!(playWav1.isPlaying())) && (wavIsPlaying)) {
    if (wavNum > 4) {
      wavNum = 0;

  // read volume control pot and set audio shield volume if required
  int vol = analogRead(pot0);
  if (vol != masterVolume) {
    masterVolume = vol;
    audioShield.volume((float)vol / 1023);  // audio shield headphone out volume (optional)
    mixer1.gain(0, (float)vol / 1023);      // software mixer input channel volume
    mixer1.gain(1, (float)vol / 1023);
    mixer2.gain(0, (float)vol / 1023);
    mixer2.gain(1, (float)vol / 1023);

  // update the button debounce status so falling edges
  // can be detected and processed

  // button 0 pressed - toggle playback start/stop for current wav file
  if (db_button0.fallingEdge()) {
    if (playWav1.isPlaying()) {
      wavIsPlaying = false;
      Serial.println("Playback stopped\n");
    else {
      wavIsPlaying = true;
      Serial.println("Playback started");
    //Serial.print("Audio memory usage max: ");

  // button 1 pressed - skip track forward
  if (db_button1.fallingEdge()) {
    Serial.println("Skip track forward");
    if (wavNum == 4)
      wavNum = 0;
    wavIsPlaying = true;

  // button 2 pressed - skip track backward
  if (db_button2.fallingEdge()) {
    Serial.println("Skip track backward");
    if (wavNum == 0)
      wavNum = 4;
    wavIsPlaying = true;

No it's not. I didn't even know what that was. I had to look it up. I just thought they had to be all caps. That file did work sometimes. Is there something wrong with the code that I can't seem to play more than 5 files?
possibly five tracks has been hard coded into the code? you have several places where button count is reset to zero or four if it crosses those thresholds in the incremental loops. I suggest changing the hard code "4" into a variable that you set to agree with the number of files to be played.
see your code here:
 if (wavNum > 4) {
      wavNum = 0;
and here:
 if (db_button1.fallingEdge()) {
    Serial.println("Skip track forward");
    if (wavNum == 4)
ok, thanks I set a variable for fileNum (number of files) instead of the hard code. It seems to work if everything is just right with twenty files. I made numbers saying one, two, three, etc. so I could tell what was playing. I couldn't really tell before if everything was playing. These are short length tho, so I need to put my other longer files back and try again.
Glad it's working. Also, just a reminder, that zerois counted as the first file in your loop, so 20 files would count 0 to 19 as your loops are written starting from zero.

You can also write code that counts the number of files on the sd card, so in theory, in setup, you could scan the sd card, count the files, and then set your fileNum with that.
Not open for further replies.