Multiple WAV playback problems

AidanRTaylor

Active member
**{FIXED}** Multiple WAV playback problems

-*-*-*-FIXED-*-*-*- :D

Hello, I'm working on a prototype for a toy - it's basically a steering wheel with some switches that activate simple things - but included is a fake radio. The hardware is a Teensy 3.2 and the Teensy Audio Adaptor with an SD Card (more on that below) and some basic panel controls around it. I have a sketch mostly together for it - the radio works by buffering two WAVs at any given time. One WAV is always playing which is a 60 second sample of out-of-tune radio static, and as you adjust a "Tuning" potentiometer, several other WAVs of full length songs (I'm using the Teensy demo audio at the moment) are faded in and out. Only one song is active at a time, so WAVs are being buffered and removed from the buffer as the pot is adjusted. In terms of how it works, it is pretty much identical to the "Mixer" example provided with the Teensy Audio examples, with the exception of buffering new files in the loop.

I've also implemented a volume control - I'm using the line output of the audio shield so I use the .dacVolume() function. The toy also includes some LED indicators and a vibration motor which is controlled with PWM to simulate an engine turning.

So here are the problems...

Sometimes the sketch runs absolutely fine, sometimes it starts fine and then becomes unresponsive with audio still playing, sometimes it starts unresponsive with some things running but no audio starting. Sometimes the audio playback is very glitchy, like the sample rate is inconsistent. One of the most annoying things is that the volume control is very selective, it often won't work at all when most other things are working ok - but I imagine all the problems will boil down to the same issue. When the sketch isn't running properly, it tends to be noticeable in the way the vibration motor behaves as well, I think PWM is running fine, but the analogWrite() updating isn't working as intended. - ah yes just from looking over my code, I can't seem to get any noticeable effect using .dacVolumeRamp() either

As a side note - I also have the same problems running the "Mixer" example, although it is a simpler effect. The audio playback is either absolutely fine or very glitchy, using the provided WAV examples.

I started working with a Kingston 16GB MicroSD HC, but this morning I tried a 32GB SanDisk Ultra as recommended on the PJRC site, but the same problems remain.

Code is posted below, any feedback would be most welcome (even unrelated!) - one parameter I am particularly unclear on is "AudioMemory()" - I have set this quite high (I think it is the same as the WavFilePlayer example) but I don't know where I should be setting it. I think it is pretty resonably commented!

Code:
/*
 * Steering Wheel Haptic Control Sketch for Teensy 3.2 + Audio Adaptor
 * 
 * 2 dials control a pretend radio with tuning and volume. The radio works by
 * looping tracks and one control fades between them. Switches activate 
 * indicator LEDs. A tilt switch activates vibration motors.
 * 
 */

// Additional libraries are required for Audio on the Teensy and the Audio Adaptor
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// Below is automatically generated code from the Teensy Audio System Design Tool
// https://www.pjrc.com/teensy/gui/index.html

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=282,264
AudioPlaySdWav           playSdWav2;     //xy=282,298
AudioPlaySdWav           playSdWav3;     //xy=282,332
AudioPlaySdWav           playSdWav4;     //xy=282,366
AudioMixer4              mixer2;         //xy=492,341
AudioMixer4              mixer1;         //xy=493,277
AudioOutputI2S           i2s1;           //xy=634,310
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer2, 0);
AudioConnection          patchCord3(playSdWav2, 0, mixer1, 1);
AudioConnection          patchCord4(playSdWav2, 1, mixer2, 1);
AudioConnection          patchCord5(playSdWav3, 0, mixer1, 2);
AudioConnection          patchCord6(playSdWav3, 1, mixer2, 2);
AudioConnection          patchCord7(playSdWav4, 0, mixer1, 3);
AudioConnection          patchCord8(playSdWav4, 1, mixer2, 3);
AudioConnection          patchCord9(mixer2, 0, i2s1, 1);
AudioConnection          patchCord10(mixer1, 0, i2s1, 0);
AudioControlSGTL5000     sgtl5000_1;     //xy=118,436
// GUItool: end automatically generated code

// Teensy Audio Shield connections
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

// IO pins used in the sketch:
const byte tunerPin = A2;
const byte ledLPin = 1;
const byte ledRPin = 2;
const byte indicatorLPin = 4;
const byte indicatorRPin = 5;
const byte vibratePin = 3;
const byte tiltPin = 0;

// control state memory variables: 
int tunerVal;
boolean indicatorL, indicatorR, tilt, lastTilt, vibDir, vibEnable, ledL, ledR;
byte vibLevel;
float gain1,gain2,gain3,gain4;

// time management variables:
unsigned long timeMS, ledLMS, ledRMS, tiltMS;
int ledInterval = 500;
int vibInterval = 10000;

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Setup");
  
  AudioMemory(160); // audio buffer memory - may be higher than necessary
  sgtl5000_1.enable(); // sgtl5000 allows for control over audio adaptor 
  // sgtl5000_1.volume(0.5); // volume for headphone output
  sgtl5000_1.dacVolumeRamp(); // exponential volume ramp dac (doesn't seem to work??)
  sgtl5000_1.lineOutLevel(21);

  //SD Card setup
  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);
    }
  }

  // Virtual Mixer initial levels
  mixer1.gain(0, 0.);
  mixer1.gain(1, 0.);
  mixer1.gain(2, 0.);
  mixer1.gain(3, 0.);
  mixer2.gain(0, 0.);
  mixer2.gain(1, 0.);
  mixer2.gain(2, 0.);
  mixer2.gain(3, 0.);
  
  // IO setup:
  pinMode(ledLPin, OUTPUT);
  pinMode(ledRPin, OUTPUT);
  pinMode(vibratePin, OUTPUT);
  pinMode(indicatorLPin, INPUT_PULLUP);
  pinMode(indicatorRPin, INPUT_PULLUP);
  pinMode(tiltPin, INPUT_PULLUP);

  Serial.println("Sketch starts shortly");
  delay(1000);
  Serial.println("Setup Complete, running sketch");
}

void loop() {
  timeMS = millis(); // sample the current internal timer
  tilt = digitalRead(tiltPin); // read from the tilt sensor
  indicatorL = digitalRead(indicatorLPin); // read left indicator switch
  indicatorR = digitalRead(indicatorRPin); // read right indicator switch

  int volPot = analogRead(A3);
  float vol = (float)volPot / 1028.0;
  sgtl5000_1.dacVolume(vol);
//  Serial.print("volume = ");
//  Serial.println(vol);
  
  vibration();
  indicators();
  radio();
}

void radio() {

  // The radio static sample plays all the time:
  if (playSdWav1.isPlaying() == false) {
    Serial.println("Start playing 1");
    playSdWav1.play("static.WAV");
    delay(100); // wait for library to parse WAV info
  }

  tunerVal = analogRead(tunerPin);  // read from the Tuner knob


  /*
   * The code below looks complex, but it really isn't! It splits the reading from
   * the tuner pot by a number of divisions, then for each division a track will be
   * faded in or out (against the static background). I start and stop tracks from
   * the SD Card so there is never more than two playing at a time - I am not sure 
   * how many long tracks can be simultaneously played by the Teensy before it 
   * reaches the limits of its memory.
   */
   
  if(tunerVal < 170) {
    gain1 = 1.0 - ((float)tunerVal / 170.0);
    gain2 = (float)tunerVal / 170.0;
    if (playSdWav3.isPlaying() == true) {
      Serial.println("Stop playing 3");
      playSdWav3.stop();
      delay(100); // wait for library to parse WAV info
    }
    if (playSdWav2.isPlaying() == false) {
      Serial.println("Start playing 2");
      playSdWav2.play("SDTEST1.WAV");
      delay(100); // wait for library to parse WAV info
    }
  }
  else if(tunerVal >= 170 && tunerVal < 340) {
    gain1 = (float)(tunerVal-170) / 170.0;
    gain2 = 1.0 - gain1;
    if (playSdWav3.isPlaying() == true) {
      Serial.println("Stop playing 3");
      playSdWav3.stop();
      delay(100); // wait for library to parse WAV info
    }
    if (playSdWav2.isPlaying() == false) {
      Serial.println("Start playing 2");
      playSdWav2.play("SDTEST1.WAV");
      delay(100); // wait for library to parse WAV info
    }
  }
  else if(tunerVal >= 340 && tunerVal < 510) {
    gain1 = 1.0 - ((float)(tunerVal-340) / 170.0);
    gain3 = (float)(tunerVal-340) / 170.0;
    if (playSdWav2.isPlaying() == true) {
      Serial.println("Stop playing 2");
      playSdWav2.stop();
      delay(100); // wait for library to parse WAV info
    }
    if (playSdWav3.isPlaying() == false) {
      Serial.println("Start playing 3");
      playSdWav3.play("SDTEST2.WAV");
      delay(100); // wait for library to parse WAV info
    }
  }
  else if(tunerVal >= 510 && tunerVal < 680) {
    gain1 = (float)(tunerVal-510) / 170.0;
    gain3 = 1.0 - gain1;
    if (playSdWav4.isPlaying() == true) {
        Serial.println("Stop playing 4");
        playSdWav4.stop();
        delay(100); // wait for library to parse WAV info
    }
    if (playSdWav3.isPlaying() == false) {
      Serial.println("Start playing 3");
      playSdWav3.play("SDTEST2.WAV");
      delay(100); // wait for library to parse WAV info
    }
  }
  else if(tunerVal >= 680 && tunerVal < 850) {
    gain1 = 1.0 - ((float)(tunerVal-680) / 170.0);
    gain4 = (float)(tunerVal-680) / 170.0;
      if (playSdWav3.isPlaying() == true) {
        Serial.println("Stop playing 3");
        playSdWav3.stop();
        delay(100); // wait for library to parse WAV info
    }
    if (playSdWav4.isPlaying() == false) {
      Serial.println("Start playing 4");
      playSdWav4.play("SDTEST3.WAV");
      delay(100); // wait for library to parse WAV info
    }
  }
  else if(tunerVal >= 850 && tunerVal <= 1024) {
    gain1 = ((float)(tunerVal-850) / 174.0);
    gain4 = 1.0 - gain1;
    if (playSdWav3.isPlaying() == true) {
      Serial.println("Stop playing 3");
      playSdWav3.stop();
      delay(100); // wait for library to parse WAV info
    }
    if (playSdWav4.isPlaying() == false) {
      Serial.println("Start playing 4");
      playSdWav4.play("SDTEST3.WAV");
      delay(100); // wait for library to parse WAV info
    }
  }

  // The code below is useful for debugging, but leave it commented out otherwise

//  Serial.print("gain 1= ");
//  Serial.print(gain1);
//  Serial.print(" gain 2= ");
//  Serial.print(gain2);
//  Serial.print(" gain 3= ");
//  Serial.print(gain3);
//  Serial.print(" gain 4= ");
//  Serial.println(gain4);
  
  mixer1.gain(0, gain1);
  mixer1.gain(1, gain2);
  mixer1.gain(2, gain3);
  mixer1.gain(3, gain4);
  mixer2.gain(0, gain1);
  mixer2.gain(1, gain2);
  mixer2.gain(2, gain3);
  mixer2.gain(3, gain4);
}

void vibration() {
    if(tilt != lastTilt) { 
    lastTilt = tilt;
    tiltMS = millis();
    Serial.println("Tilt Detected");
  }
  
  if(timeMS - tiltMS < 10000) vibEnable = true;
  else vibEnable = false;
  
  if(vibEnable) {
    if(vibDir && vibLevel < 255) {
      vibLevel++;
    }
    else if(!vibDir && vibLevel >= 0) {
      vibLevel--;
      if(vibLevel == 0) digitalWrite(vibratePin, LOW);
    }
    if(vibLevel != 0) analogWrite(vibratePin, vibLevel);
    delay(2);
  
    if(vibLevel == 100) vibDir = !vibDir;
    if(vibLevel == 255) vibDir = !vibDir;
  }
  else {
    if(vibLevel != 0) {
      vibLevel--;
      analogWrite(vibratePin, vibLevel);
      delay(5);
    }
    else digitalWrite(vibratePin, LOW);
  }
}

void indicators() {
  if(!indicatorL) {
    if(timeMS - ledLMS > 500) {
      ledLMS = millis();
      ledL = !ledL;
      digitalWrite(ledLPin, ledL);
    }
  }
  else digitalWrite(ledLPin, LOW);

  if(!indicatorR) {
    if(timeMS - ledRMS > 500) {
      ledRMS = millis();
      ledR = !ledR;
      digitalWrite(ledRPin, ledR);
    }
  }
  else digitalWrite(ledRPin, LOW);
}
 
Last edited:
I'm trying the SdCardTest sketch and this is the readout on the Serial Monitor:

SD Card Test
------------
SD card is connected :)
Card type is SDHC
File system space is 31898.86 Mbytes.
SD library is able to access the filesystem

Reading SDTEST1.WAV:
Overall speed = 0.71 Mbyte/sec
Worst block time = 1.41 ms
48.63% of audio frame time

Reading SDTEST1.WAV & SDTEST2.WAV:
Overall speed = 0.43 Mbyte/sec
Worst block time = 3.74 ms
129.08% of audio frame time

Reading SDTEST1.WAV & SDTEST2.WAV staggered:
Overall speed = 0.43 Mbyte/sec
Worst block time = 3.05 ms
105.09% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV:
Overall speed = 0.43 Mbyte/sec
Worst block time = 5.62 ms
193.77% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV staggered:
Overall speed = 0.43 Mbyte/sec
Worst block time = 4.23 ms
145.86% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV:
Overall speed = 0.43 Mbyte/sec
Worst block time = 7.50 ms
258.54% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV staggered:
Overall speed = 0.43 Mbyte/sec
Worst block time = 5.41 ms
186.64% of audio frame time
 
Ok - I just noticed that the print on my SD Ultra is bubbled and chipped, so now I suspect I have a fake micro SD - I can pick the print off with my nail :(
 
I went to a local store and picked up a 16GB SanDisk MicroSD Ultra - pretty sure this one is genuine. I formatted it using Disk Utility - which for some reason has FAT32 greyed out, but allows FAT format (I don't know if this matters) - I then ran SdCardTest again. Just to be clear on formatting - I used Terminal Command Line to format to FAT32, and again repeated the test, the general result seems better right?:

Test 1 (FAT)

SD Card Test
------------
SD card is connected :)
Card type is SDHC
File system space is 15911.79 Mbytes.
SD library is able to access the filesystem

Reading SDTEST1.WAV:
Overall speed = 1.07 Mbyte/sec
Worst block time = 0.77 ms
26.57% of audio frame time

Reading SDTEST1.WAV & SDTEST2.WAV:
Overall speed = 0.80 Mbyte/sec
Worst block time = 2.21 ms
76.28% of audio frame time

Reading SDTEST1.WAV & SDTEST2.WAV staggered:
Overall speed = 0.80 Mbyte/sec
Worst block time = 1.83 ms
63.04% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV:
Overall speed = 0.80 Mbyte/sec
Worst block time = 3.37 ms
116.26% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV staggered:
Overall speed = 0.80 Mbyte/sec
Worst block time = 2.49 ms
85.75% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV:
Overall speed = 0.79 Mbyte/sec
Worst block time = 4.56 ms
157.20% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV staggered:
Overall speed = 0.79 Mbyte/sec
Worst block time = 3.18 ms
109.50% of audio frame time

Test 2 (FAT32)

SD Card Test
------------
SD card is connected :)
Card type is SDHC
File system space is 15915.97 Mbytes.
SD library is able to access the filesystem

Reading SDTEST1.WAV:
Overall speed = 0.97 Mbyte/sec
Worst block time = 0.75 ms
26.02% of audio frame time

Reading SDTEST1.WAV & SDTEST2.WAV:
Overall speed = 0.83 Mbyte/sec
Worst block time = 2.29 ms
79.07% of audio frame time

Reading SDTEST1.WAV & SDTEST2.WAV staggered:
Overall speed = 0.83 Mbyte/sec
Worst block time = 1.92 ms
66.25% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV:
Overall speed = 0.82 Mbyte/sec
Worst block time = 3.52 ms
121.25% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV staggered:
Overall speed = 0.82 Mbyte/sec
Worst block time = 2.65 ms
91.30% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV:
Overall speed = 0.84 Mbyte/sec
Worst block time = 4.55 ms
156.72% of audio frame time

Reading SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV, SDTEST4.WAV staggered:
Overall speed = 0.84 Mbyte/sec
Worst block time = 3.17 ms
109.40% of audio frame time
 
Yep - definitely a fake SD card - everything is working flawlessly now - reset over 10 times and scanned through the tracks adjusting volume etc :) Yay!
 
thank you thread, I was having problems with my audio syncing, it was running about 1 second fast after 2 minutes of play, tried another micro SD and it was 3 seconds fast, knew I was onto something, reformatted SD and reinstalled wav files, works perfect, it was driving me nuts, thanks again!!
 
Back
Top