Teensy 3.6 audio sample player, some files not playing

Wollie

New member
Hi everyone,

I'm stuck working on the code for an kind of audio sample player device that I'm building for my grandfather and I'm getting some strange results.

The device:
I'm working on a device that consists essentially of 12 pushbuttons that each play a short audio sample when pressed. The files are played from an SD card in a teensy 3.6, using the two DAC pins to drive a small amp. The code generates an array (music_list) containing the names of all the files that are stored on the SD card and sorts them alphabetically. The files are then played from this list. An additional 'menu' button allow the buttons to refer to a different section of the list, thus allowing the device to play several sets of 12 sounds.

What works:
- All hardware
- The files are correctly read from the SD card added to the array music_list, sorted and printed in the serial monitor
- Pressing buttons returns the correct entry from music_list
- All test files play correctly when tested separately (I'm using the teensy test files here just to be sure but my own wav files also work)

The problem:
Consistently, only one file plays correctly using the array. However this is not always the same file or the same button. This problem persist even when files are played directly (playSdWav1.play("SDTEST1.wav");) instead of using the array (playSdWav1.play(music_list[(menu * 12) + 0]);). When generate_music_list(); is commented out, all files play correctly when referenced directly.

It is important to me to be able to put new sounds on my SD card without having to change file names or change my code. Yet, generating the music_list array seems to be conflicting with other parts of my code.

All thoughts and suggestions are very welcome.

Code:
///////////////////////////////////
// code from teensy audio design-tool
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Bounce.h>

AudioPlaySdWav playSdWav1;      //xy=359,316
AudioOutputAnalogStereo dacs1;  //xy=650,313
AudioConnection patchCord1(playSdWav1, 0, dacs1, 0);
AudioConnection patchCord2(playSdWav1, 1, dacs1, 1);

///////////////////////////////////

Bounce button00 = Bounce(33, 15);  // (pin number, ms)
Bounce button01 = Bounce(35, 15);
Bounce button02 = Bounce(34, 15);
Bounce button03 = Bounce(30, 15);
Bounce button04 = Bounce(31, 15);
Bounce button05 = Bounce(32, 15);
Bounce button06 = Bounce(38, 15);
Bounce button07 = Bounce(37, 15);
Bounce button08 = Bounce(36, 15);
Bounce button09 = Bounce(29, 15);
Bounce button10 = Bounce(28, 15);
Bounce button11 = Bounce(27, 15);
Bounce button12 = Bounce(39, 15);


// Use these with the Teensy 3.5 & 3.6 SD card
#define CS BUILTIN_SDCARD
#define MOSI 11  // not actually used
#define SCK 13   // not actually used


// Create one dimensional character array
char music_list[12][48];  //12 characters per entry, 48 entries
void generate_music_list() {
  File dir = SD.open("/");
  int i = 0;
  while (true) {
    File entry = dir.openNextFile();
    if (!entry) {
      for (; i < 48; i++)
        strcpy(music_list[i], "z");  //missing files are entered as "z"
      break;
    }
    // skip standard file from sd card
    if (strcmp(entry.name(), "System Volume Information") != 0)
      strcpy(music_list[i], entry.name());
    else  // prevents skipped file from being counted
      i--;
    entry.close();
    i++;
  }
  // sort list alphabetically
  bool is_sorted = false;
  while (!is_sorted) {
    is_sorted = true;
    for (i = 0; i < 48 - 1; i++) {
      if (strcmp(music_list[i], music_list[i + 1]) > 0 && strcmp(music_list[i], "z") && strcmp(music_list[i + 1], "z")) {
        char temp[12];
        strcpy(temp, music_list[i]);
        strcpy(music_list[i], music_list[i + 1]);
        strcpy(music_list[i + 1], temp);
        is_sorted = false;
      }
    }
  }
}

void setup() {
  Serial.begin(9600);
  AudioMemory(8);
  SPI.setMOSI(MOSI);
  SPI.setSCK(SCK);
  if (!(SD.begin(CS))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  //activate internal pullup resitors of teensy
  pinMode(27, INPUT_PULLUP);
  pinMode(28, INPUT_PULLUP);
  pinMode(29, INPUT_PULLUP);
  pinMode(30, INPUT_PULLUP);
  pinMode(31, INPUT_PULLUP);
  pinMode(32, INPUT_PULLUP);
  pinMode(33, INPUT_PULLUP);
  pinMode(34, INPUT_PULLUP);
  pinMode(35, INPUT_PULLUP);
  pinMode(36, INPUT_PULLUP);
  pinMode(37, INPUT_PULLUP);
  pinMode(38, INPUT_PULLUP);
  pinMode(39, INPUT_PULLUP);
  delay(1000);
  // Generate the music_list
  generate_music_list();  // files can be directly played if this line is commented out
  // Print music list for control
  for (int i = 0; i < 48; i++)
    Serial.println(music_list[i]);
}

void loop() {
  // Create interger to keep count of selected menu
  static int menu = 0;
  // Check blue menu button
  button12.update();
  if (button12.fallingEdge()) {
    Serial.println("BTN 12 Pressed");
    menu++;
    if (menu > 3) {
      menu = 0;
    }
    Serial.println(menu);
  }
  //Check yellow sound buttons
  button00.update();
  if (button00.fallingEdge()) {
    Serial.println("BTN 00 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 0]);
    playSdWav1.play(music_list[(menu * 12) + 0]);
    // playSdWav1.play("SDTEST1.wav"); //testing teensy files
  }
  button01.update();
  if (button01.fallingEdge()) {
    Serial.println("BTN 01 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 1]);
    playSdWav1.play(music_list[(menu * 12) + 1]);
    // playSdWav1.play("SDTEST2.wav");
  }
  button02.update();
  if (button02.fallingEdge()) {
    Serial.println("BTN 02 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 2]);
    playSdWav1.play(music_list[(menu * 12) + 2]);
    // playSdWav1.play("SDTEST3.wav");
  }
  button03.update();
  if (button03.fallingEdge()) {
    Serial.println("BTN 03 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 3]);
    playSdWav1.play(music_list[(menu * 12) + 3]);
    // playSdWav1.play("SDTEST4.wav");
  }
  button04.update();
  if (button04.fallingEdge()) {
    Serial.println("BTN 04 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 4]);
    playSdWav1.play(music_list[(menu * 12) + 4]);
    // playSdWav1.play("1A_TEST.WAV"); //testing one of my own files
  }
  button05.update();
  if (button05.fallingEdge()) {
    Serial.println("BTN 05 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 5]);
    playSdWav1.play(music_list[(menu * 12) + 5]);
  }
  button06.update();
  if (button06.fallingEdge()) {
    Serial.println("BTN 06 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 6]);
    playSdWav1.play(music_list[(menu * 12) + 6]);
  }
  button07.update();
  if (button07.fallingEdge()) {
    Serial.println("BTN 07 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 7]);
    playSdWav1.play(music_list[(menu * 12) + 7]);
  }
  button08.update();
  if (button08.fallingEdge()) {
    Serial.println("BTN 08 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 8]);
    playSdWav1.play(music_list[(menu * 12) + 8]);
  }
  button09.update();
  if (button09.fallingEdge()) {
    Serial.println("BTN 09 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 9]);
    playSdWav1.play(music_list[(menu * 12) + 9]);
  }
  button10.update();
  if (button10.fallingEdge()) {
    Serial.println("BTN 10 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 10]);
    playSdWav1.play(music_list[(menu * 12) + 10]);
  }
  button11.update();
  if (button11.fallingEdge()) {
    Serial.println("BTN 12 Pressed");
    playSdWav1.stop();
    Serial.println(music_list[(menu * 12) + 11]);
    playSdWav1.play(music_list[(menu * 12) + 11]);
  }

  delay(50);

  if (playSdWav1.isPlaying() == true) {
    Serial.println("playing...");
  }
}


View attachment OPA PROJECT.ino
 
All thoughts and suggestions are very welcome.

@Wollie: I did not try to build your code, nor run it in any way, but with just a cursory view, it appears that there are some potential points of confusion (& I don't rule out that said confusion may certainly be purely on my part !!):
- is your music_list[][] array defined as music_list[entry number of 12][title characters of 48] or music_list[title characters of 12][entry number of 48] ??
- there are places where you use a loop index that goes thru 48, but it appears that you are loop thru the first 4 entries of the 12 title characters (using a single array index to reference the entry number, shouldn't that be "i * 12" instead of just "i") ??
- inside your generate_music_list() function, it appears that the variable "i" is intended to count thru the entries, but it is also used as the index for an interior loop for filling the title of the missing files with "z" that goes thru 48 (corrupting the original count along the way) ??
- when the list entries are being sorted, when stepping thru the 48 entries, shouldn't the array index be "i * 12", rather than just "i" ??

Hope that helps . . .

Mark J Culross
KD5RXT
 
Back
Top