WavFilePlayer Clicks, pops and crunchy noises - solved but WHY?!

Status
Not open for further replies.

alrj

Well-known member
After 3 or 4 brutal days of trying, failing and trying some more I started back again at the WavFilePlayer example and built it up into a test sketch to try and work out why I was getting clicks and pops when loading more than 2 wav files at the same time. I was sure this wasn't the case when I started out.

The problem is that if you use folders to put your wavs in the loading performance becomes terrible. This code will happily load and play 8 stereo wavs at 48k on the T4: (impressive!!)

Code:
playSdWav1.play("3BAB1.wav");
  playSdWav2.play("3BAB2.wav");
  playSdWav3.play("3BAB3.wav");
  playSdWav4.play("3BAB4.wav");
  playSdWav5.play("3BAD.wav");
  playSdWav6.play("3BAA.wav");
  playSdWav7.play("3BAS.wav");
  playSdWav8.play("3BAB2.wav");

but this code clicks, pops and sounds terrible on the first couple of wavs

Code:
playSdWav1.play("BA/3BAB1.wav");
  playSdWav2.play("BA/3BAB2.wav");
  playSdWav3.play("BA/3BAB3.wav");
  playSdWav4.play("BA/3BAB4.wav");
  playSdWav5.play("BA/3BAD.wav");
  playSdWav6.play("BA/3BAA.wav");
  playSdWav7.play("BA/3BAS.wav");
  playSdWav8.play("BA/3BAB2.wav");

Why is this? and what can I do to solve the problem? I am using SDIO, T4, SD.h on the latest Teensyduino

edit, full sketch here:

Code:
// Simple WAV file player example

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

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=265,249
AudioPlaySdWav           playSdWav2;     //xy=271,336
AudioPlaySdWav           playSdWav3;     //xy=287,412
AudioPlaySdWav           playSdWav4;     //xy=295,473
AudioPlaySdWav           playSdWav5;     //xy=310,689
AudioPlaySdWav           playSdWav6;     //xy=318,772
AudioPlaySdWav           playSdWav7;     //xy=321,852
AudioPlaySdWav           playSdWav8;     //xy=332,959
AudioMixer4              mixer2;         //xy=581,360
AudioMixer4              mixer4;         //xy=584,597
AudioMixer4              mixer3;         //xy=586,476
AudioMixer4              mixer1;         //xy=590,254
AudioMixer4              mixer6;         //xy=697,845
AudioMixer4              mixer5;         //xy=703,736
AudioOutputI2S           i2s1;           //xy=851,287
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer2, 0);
AudioConnection          patchCord3(playSdWav2, 0, mixer3, 2);
AudioConnection          patchCord4(playSdWav2, 1, mixer4, 2);
AudioConnection          patchCord5(playSdWav3, 0, mixer3, 0);
AudioConnection          patchCord6(playSdWav3, 1, mixer4, 0);
AudioConnection          patchCord7(playSdWav4, 0, mixer3, 1);
AudioConnection          patchCord8(playSdWav4, 1, mixer4, 1);
AudioConnection          patchCord9(playSdWav5, 0, mixer3, 3);
AudioConnection          patchCord10(playSdWav5, 1, mixer4, 3);
AudioConnection          patchCord11(playSdWav6, 0, mixer5, 0);
AudioConnection          patchCord12(playSdWav6, 1, mixer6, 0);
AudioConnection          patchCord13(playSdWav7, 0, mixer5, 1);
AudioConnection          patchCord14(playSdWav7, 1, mixer6, 1);
AudioConnection          patchCord15(playSdWav8, 0, mixer5, 2);
AudioConnection          patchCord16(playSdWav8, 1, mixer6, 3);
AudioConnection          patchCord17(mixer2, 0, i2s1, 1);
AudioConnection          patchCord18(mixer1, 0, i2s1, 0);
// 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

// Use these with the Teensy 3.5 & 3.6 SD card
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13
int inByte = 0;
byte  newDATAin = 1;


void setup() {
  Serial.begin(115200);

  mixer1.gain(1, 0.2);
  mixer1.gain(2, 0.2);
  mixer1.gain(3, 0.2);
  mixer1.gain(4, 0.2);

  mixer2.gain(1, 0.2);
  mixer2.gain(2, 0.2);
  mixer2.gain(3, 0.2);
  mixer2.gain(4, 0.2);

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(150);


  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here, but print a message repetitively
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}



void loop() {
  

  // Simply wait for the file to finish playing.
  //while (playSdWav1.isPlaying()) {

     switch (Serial.read()) {
      
   case 's': {
    //Serial.println("s");
   playSdWav1.stop();
   playSdWav2.stop();
   playSdWav3.stop();
   playSdWav4.stop();
   playSdWav5.stop();
   playSdWav6.stop();
   playSdWav7.stop();
   playSdWav8.stop();
   }
        break;

        case 't': {
  playSdWav1.play("3BAB1.wav");
  playSdWav2.play("3BAB2.wav");
  playSdWav3.play("3BAB3.wav");
  playSdWav4.play("3BAB4.wav");
  playSdWav5.play("3BAD.wav");
  playSdWav6.play("3BAA.wav");
  playSdWav7.play("3BAS.wav");
  playSdWav8.play("3BAB2.wav");
  
  delay(5);
        }
      break;

              case 'u': {
  playSdWav1.play("BA/3BAB1.wav");
  playSdWav2.play("BA/3BAB2.wav");
  playSdWav3.play("BA/3BAB3.wav");
  playSdWav4.play("BA/3BAB4.wav");
  playSdWav5.play("BA/3BAD.wav");
  playSdWav6.play("BA/3BAA.wav");
  playSdWav7.play("BA/3BAS.wav");
  playSdWav8.play("BA/3BAB2.wav");
  
  delay(5);
        }
      break;
   
}



}

only the first wav player is attached to the output for this test to avoid everything playing at once and sounding crazy
 
since writing the above post I have noticed some files load better than others, even if they are the same length file name and same size file :/ I managed to get the Sdfat.h beta to compile with the audio library and although in SDIO mode it doesn't pop or click everything hangs for a moment or two after you start the wavs playing. There must be a setting I can adjust somewhere to get rid of these pops and clicks? A
 
One theory:
The code in the SD library has no caching. It will scan your entire root directory to find the "BA" directory, each time you open something. Then it will scan the "BA" directory it finds, to find each file. It does this by reading the disk, over and over again.
You may be able to split the code into "find and open the file" versus "read the data to play it back" such that the slow scanning happens before any audio needs to be played.
The throughput to the flash, and latency of reading sectors, is limited, and when you hit too many requests at once, it takes too long.
Unfortunately, AudopPlaySdWav doesn't have some way of "pre-loading" without starting playing, and if you pre-load all the files in the middle of loop(), you'll have the same problem anyway.

So, you will get the best performance if the only thing on your card is the eight files, and they are all in the root directory. Anything beyond that, will cause worse performance, and when the "worse performance" hits the necessary per-block time for the audio output, you will get glitching.
 
Thanks for the reply! That makes a lot of sense. A friend of mine pointed out that I can probably solve this problem by using AudioRecordQueue and AudioPlayQueue to create a buffer! Looking forward to giving it a go in the morning.
 
Status
Not open for further replies.
Back
Top