AudioPlaySdWav in an object?

Status
Not open for further replies.

Dionysus

Active member
Good evening! Quickly, I should say how blown away I am by the software and the hardware with the teensy 4—this is just incredible. I've also been spending a lot of time in the forums, and I'm also incredibly impressed by how nice everyone is here! So much so, that it encouraged me to post what is possibly a very silly question, indeed!

I'm writing a drum machine, reading samples form the SD card and playing them. Each sample is an object, which works really well right up until it's time to play the wave file. AudioPlaySdWav playSdWav1 (for example) needs to be declared globally, but I can't figure out how to pass it to the Sample object. My incredibly kludgey "solution" was to have each object call a "playSample()" function, which calls the correct AudioPlaySdWav. That can't be right, right!?

Also, when I have more than 3 files running it will often freeze up and just play that horrible hum. Sometimes I'm able to get four files working, but no more than that. I strongly suspect that this is because I'm reading them all from the SD card, and I plan to write a second question here about alternatives to that. But I did think I should check to see if something about the janky way I'm calling AudioPlaySdWav is also responsible.

I'm attaching my code here, apologies for the mess! Thank you all so much!

Code:
///////////////////////////////////
// copy the Design Tool code here
///////////////////////////////////
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav5;     //xy=151,254
AudioPlaySdWav           playSdWav8;     //xy=155,389
AudioPlaySdWav           playSdWav6;     //xy=161,302
AudioPlaySdWav           playSdWav1;     //xy=162,63
AudioPlaySdWav           playSdWav3;     //xy=169,162
AudioPlaySdWav           playSdWav2;     //xy=173,112
AudioPlaySdWav           playSdWav7;     //xy=180,342
AudioPlaySdWav           playSdWav4;     //xy=181,202
AudioMixer4              mixer4;         //xy=355,332
AudioMixer4              mixer3;         //xy=375,270
AudioMixer4              mixer1;         //xy=397,150
AudioMixer4              mixer2;         //xy=404,209
AudioMixer4              mixer5;         //xy=611,206
AudioAnalyzePeak         peak3;          //xy=690,427
AudioAnalyzePeak         peak1;          //xy=693,312
AudioAnalyzePeak         peak2;          //xy=716,376
AudioAnalyzePeak         peak4;          //xy=720,480
AudioOutputI2S           i2s1;           //xy=878,201
AudioConnection          patchCord1(playSdWav5, 0, mixer3, 0);
AudioConnection          patchCord2(playSdWav5, 1, mixer3, 1);
AudioConnection          patchCord3(playSdWav8, 0, mixer4, 2);
AudioConnection          patchCord4(playSdWav8, 1, mixer4, 3);
AudioConnection          patchCord5(playSdWav6, 0, mixer3, 2);
AudioConnection          patchCord6(playSdWav6, 1, mixer3, 3);
AudioConnection          patchCord7(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord8(playSdWav1, 1, mixer1, 1);
AudioConnection          patchCord9(playSdWav3, 0, mixer2, 0);
AudioConnection          patchCord10(playSdWav3, 1, mixer2, 1);
AudioConnection          patchCord11(playSdWav2, 0, mixer1, 2);
AudioConnection          patchCord12(playSdWav2, 1, mixer1, 3);
AudioConnection          patchCord13(playSdWav7, 0, mixer4, 0);
AudioConnection          patchCord14(playSdWav7, 1, mixer4, 1);
AudioConnection          patchCord15(playSdWav4, 0, mixer2, 2);
AudioConnection          patchCord16(playSdWav4, 1, mixer2, 3);
AudioConnection          patchCord17(mixer4, 0, mixer5, 3);
AudioConnection          patchCord18(mixer4, peak4);
AudioConnection          patchCord19(mixer3, 0, mixer5, 2);
AudioConnection          patchCord20(mixer3, peak3);
AudioConnection          patchCord21(mixer1, 0, mixer5, 0);
AudioConnection          patchCord22(mixer1, peak1);
AudioConnection          patchCord23(mixer2, 0, mixer5, 1);
AudioConnection          patchCord24(mixer2, peak2);
AudioConnection          patchCord25(mixer5, 0, i2s1, 0);
AudioConnection          patchCord26(mixer5, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=346,435
// GUItool: end automatically generated code
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

int bpm=120;
int sampleObjects=0;

#define WHOLENOTE 4
#define HALFNOTE  2
#define QUARTERNOTE 1
#define EIGHTHNOTE .5
#define SIXTEENTHNOTE .25



class Sample{
  float noteType;       // i.e., what percentage of bpm is this note (e.g., a quarternote is 1 bpm, an eigthnote is .5)
  int oldTime=0;
  const char *sampleName;
  File currentDir;
  File currentSample;
  char fullSamplePath[50];
  int id;
  elapsedMillis change;
  
   public:
    void setup(const char *dn,const char *sn,float n, int beats, int rests){
      sampleName=sn;
      noteType=n;
      currentDir=loadDir(dn);
      currentSample=loadSample(sn);
      sampleObjects++;
      id=sampleObjects;
    }  
  void playSample(int id, char *fullSamplePath){
    switch(id){
      case 1:  
        playSdWav1.play(fullSamplePath);
        break;
      case 2:  
        playSdWav2.play(fullSamplePath);
        break;
      case 3:  
        playSdWav3.play(fullSamplePath);
        break;
      case 4:  
        playSdWav4.play(fullSamplePath);
        break;
      case 5:  
        playSdWav5.play(fullSamplePath);
        break;
      case 6:  
        playSdWav6.play(fullSamplePath);
        break;
      case 7:  
        playSdWav7.play(fullSamplePath);
        break;
      case 8:  
        playSdWav8.play(fullSamplePath);
        break;
    }
    delay(50);
  }
    /************************************************************************************************************************************
     *                                                                                                                    loadDir()
    ************************************************************************************************************************************/
    
    File loadDir(const char* dir){
      Serial.println(dir);
      File myFile;
      myFile=SD.open(dir);
      Serial.print("Directory: ");Serial.println(myFile.name());
      return myFile;
    
    }
    /************************************************************************************************************************************
     *                                                                                                                    loadSample()
    ************************************************************************************************************************************/
    
    File loadSample(const char* sampleName){
      File myFile;
      //char fullSamplePath[50];
      sprintf(fullSamplePath, "/%s/%s",currentDir.name(),sampleName);
          Serial.print("Name 1: ");Serial.println(fullSamplePath);
          
      myFile=SD.open(fullSamplePath);
      if(! myFile){
        Serial.println("Can't open file");
        return myFile;
      }
      else{
        return myFile;
      }
    }
    //*******************************************************************************************************************
    //                                                                                               Main Sample Loop
    //*******************************************************************************************************************
    void loop(){    
       if(change>=(noteType*(60000/bpm))){
        // e.g., an eighthnote at 120 bpm should play every 250 milliseconds, which is 4 times a second or 240 times a minute
        change=0;
        playSample(id,fullSamplePath);
      }
    }
};
Sample sample1;
Sample sample2;
Sample sample3;
Sample sample4;
Sample sample5;
Sample sample6;
Sample sample7;
Sample sample8;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  AudioMemory(8);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  delay(1000);
  float vol=.15;
  mixer1.gain(0, vol);
  mixer1.gain(1, vol);
  mixer2.gain(0, vol);
  mixer2.gain(1, vol);
  mixer3.gain(0, vol);
  mixer3.gain(1, vol);
  mixer4.gain(0, vol);
  mixer4.gain(1, vol);
  mixer5.gain(0, .5);
  mixer5.gain(1, .5);

  
  sample1.setup("D_808", "classic.wav", SIXTEENTHNOTE,1,2);
  sample2.setup("D_808", "break.wav", EIGHTHNOTE,1,2);
  sample3.setup("D_808", "bitch.wav", QUARTERNOTE,2,1);  
  sample4.setup("D_organc", "clakclak.wav", WHOLENOTE,2,2);
  sample5.setup("D_organc", "lanaDah.wav", QUARTERNOTE,7,3);
  sample6.setup("D_organc", "lanaDah2.wav", QUARTERNOTE,3,7);
  sample7.setup("D_organc", "meaty.wav", QUARTERNOTE,1,7);
}

void loop() {
  sample1.loop();
  sample2.loop();
  sample3.loop();
//  sample4.loop();
 // sample5.loop();
//sample6.loop();
//  sample7.loop();  
}
 
See the WavFilePlayer in the Audio examples. It plays four WAV files from the SD card one after the other.

Pete
 
I see that, but I will often need to play the files at the same time. I do appreciate that there are limits to how many audio files I can play simultaneously. Actually, according to some older posts it looks like that limit might be 2—is that right? Maybe I've just been getting lucky when I play four files at once, and they simply haven't collided?
 
Oh sorry, I see what you're doing now.
The number of files you can play simultaneously is partly dependent upon the speed of the SD card and how it is formatted.

You can declare an array of the objects and then access them by index. I think it would be something like this, but untested:
Code:
AudioPlaySdWav *arr_play[8] = {&playSdWav1, &playSdWav2, &playSdWav3, &playSdWav4, &playSdWav5, &playSdWav6, &playSdWav7, &playSdWav8};
and then access them like this:
Code:
  arr_play[i]->play(fullSamplePath);
This won't increase the number that can play but should simplify your code somewhat.

Pete
 
Yes, that's exactly what I was hoping for, thank you! It didn't magically let me play a thousand wav files all at once, but it's definitely a better way to handle things.
 
Status
Not open for further replies.
Back
Top