Help to figure out why .WAV files aren't playing

Status
Not open for further replies.
Hello! I'm loving the Teensy, I have the 4.1 with an audio shield. I've written a code for a drum machine with 2 piezo pickups (rightPiezo for bass sounds, leftPiezo for snare sounds). Basically I want to hit the piezo pickups and have WAV files play along with some LED lights going off. I am not sure why my code doesn't work (it complies and the lights blink, but no sounds)... if anyone has any insight for me that would be awesome. Thanks in advance!

Here is the code:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

/*This initial setup is important because I have added 2 mixers.
  This means that playSdWav1 and playSdWav2 can be played at the same time*/

AudioPlaySdWav           playSdWav1;
AudioPlaySdWav           playSdWav2;
AudioMixer4              mixer1;
AudioMixer4              mixer2;
AudioOutputI2S           audioOutput;
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(mixer1, 0, audioOutput, 0);
AudioConnection          patchCord6(mixer2, 0, audioOutput, 1);
AudioControlSGTL5000     sgtl5000_1;

#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

// lights
const int yellow = 2;  // led connected to pin 2.
const int white = 3;   // led connected to pin 3.
const int green = 4;   // led connected to pin 4.
const int blue = 5;    // led connected to pin 5.
const int killSwitch = 6;

const int rightPiezo = A0;  // right piezo on analog pin 1
const int leftPiezo = A1;   // left piezo on analog pin 2

int rightsensorReading = 0;
int leftsensorReading = 0;
int ledState = LOW;

const int threshold = 5;  /*do we need this if we're using the Peak capture method? */

bool shouldRunPattern1 = true;
bool shouldRunPattern2 = true;

bool shouldPlaySound1 = false;
bool shouldPlaySound2 = false;

long pattern1Start = 0;
long pattern2Start = 0;

void setup() {
  AudioMemory(20);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);

  AudioNoInterrupts();
 
  pinMode(yellow, OUTPUT);
  pinMode(white, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);

}

void loop() {

  /*if (digitalRead(killSwitch) == LOW) {
      return; } */
  if (shouldPlaySound1) {
    playSdWav1.play("RKIT.WAV");
    shouldPlaySound1 = false;
  }
  if (shouldPlaySound2) {
    playSdWav2.play("LKIT.WAV");
    shouldPlaySound2 = false;
    }
    
  // read sensors and set variables
  rightsensorReading = analogRead(rightPiezo);
  leftsensorReading = analogRead(leftPiezo);

  /* volume control, #s are somewhat subjective,
    will need adjusting once pedal is built*/
  float volume = 0.0;
  if (rightPiezo < 5) {
    volume = 0.0;
  } else if (rightPiezo <= 10) {
    volume = 0.4;
  } else if (rightPiezo <= 22) {
    volume = 0.7;
  } else {
    volume = 1.0;
  }

  if (leftPiezo < 5) {
    volume = 0.0;
  } else if (leftPiezo <= 10) {
    volume = 0.4;
  } else if (leftPiezo <= 22) {
    volume = 0.7;
  } else {
    volume = 1.0;
  }

  // initialize the pattern1
  if (rightsensorReading >= threshold) {
    shouldRunPattern1 = true;
    shouldPlaySound1 = true;
    pattern1Start = millis();
  }
  // initialize the pattern2
  if (leftsensorReading >= threshold) {
    shouldRunPattern2 = true;
    shouldPlaySound2 = true;
    pattern2Start = millis();
  }
  // how long it's been since pattern1 was started
  long pattern1Duration = millis() - pattern1Start;
  // how long it's been since pattern2 was started
  long pattern2Duration = millis() - pattern2Start;
  // change this to change how long the LEDs stay on
  long patternPulseTime = 200;  // .2 seconds
  // run pattern 1
  if (shouldRunPattern1) {
    // green and blue on
    if (pattern1Duration < patternPulseTime) {
      digitalWrite(green, HIGH);
      digitalWrite(blue, HIGH);
    }
    // green and blue off for second half second
    else {
      digitalWrite(green, LOW);
      digitalWrite(blue, LOW);
      shouldRunPattern1 = false;
    }
  }
  // run pattern 2 (same as pattern1 just different leds)
  if (shouldRunPattern2) {
    if (pattern2Duration < patternPulseTime) {
      digitalWrite(yellow, HIGH);
      digitalWrite(white, HIGH);
    } else {
      digitalWrite(yellow, LOW);
      digitalWrite(white, LOW);
      shouldRunPattern2 = false;
    }
  }
}
 
The 3 most common WAV file problems:

1: Unsupported encoding - basically anything other than 16 bit, 44100 Hz.

2: Not 8.3 filenames (not an issue here, and starting with Teensyduino 1.54-beta we use SdFat which supports long filenames)

3: Repeatedly restarting the file, where the first moment is silent or too low to hear. Easy to check this by using the WavFilePlayer example.
 
Hi Paul, thanks for that quick reply!

I have checked the files using the WavFilePlayer example, they do work there and I can hear them fine, and the WAV files are 16 bit. But when I use my code and try to make it play with a Piezo trigger I get nothing.

 
As a very simple first test, try adding a 10 second delay right after you start it playing. Like this:

Code:
  if (shouldPlaySound1) {
    playSdWav1.play("RKIT.WAV");
    delay(10000);
    shouldPlaySound1 = false;
  }
 
Oh, you also need to delete this from setup()

Code:
  AudioNoInterrupts();

Or if you have some reason to turn off audio library updates, you need to turn it back on ASAP to let the audio library run.
 
It does give me this message when the code complies, not sure if that's the issue:

Beata_Teensy: In function 'void loop()':
Beata_Teensy:85: warning: variable 'volume' set but not used
float volume = 0.0;
^
 
Looking at your code again, I'm pretty sure you're hitting problem #3.

But to know for sure, you really need to add some Serial.print() lines and watch with the Arduino serial monitor to see what really happening.

For example, after reading the 2 sensors, print the numbers.

Code:
  rightsensorReading = analogRead(rightPiezo);
  leftsensorReading = analogRead(leftPiezo);
  Serial.print("rightsensorReading = ");
  Serial.print(rightsensorReading);
  Serial.print(", leftsensorReading = ");
  Serial.print(leftsensorReading);
  Serial.println();

My (blind) guess is you're probably reading more than the threshold of 5 on every loop, where this code will then set shouldRunPattern1 to true.

Code:
  // initialize the pattern1
  if (rightsensorReading >= threshold) {
    shouldRunPattern1 = true;
    shouldPlaySound1 = true;
    pattern1Start = millis();
  }

Then on the next run of loop, you'll probably restart playing the WAV file before enough of it has played to be heard.

Code:
  if (shouldPlaySound1) {
    playSdWav1.play("RKIT.WAV");
    shouldPlaySound1 = false;
  }

Again, this is blind gueswork. To be able to actually see what's going on, add something like this:

Code:
  if (shouldPlaySound1) {
    Serial.println("Starting Sound1 Play");
    playSdWav1.play("RKIT.WAV");
    shouldPlaySound1 = false;
  }

Then you can watch in the serial monitor. If it's repeatedly starting the sound over and over, you'll get only the first couple milliseconds of the file played before it starts again. Most WAV files start with a fade in or other soft sound in the first several milliseconds. (and again, that's more guesswork about your situation)

It does give me this message when the code complies, not sure if that's the issue:

Beata_Teensy: In function 'void loop()':
Beata_Teensy:85: warning: variable 'volume' set but not used
float volume = 0.0;

That's probably unrelated. But if you look over your entire program, you have 8 places were your code writes different numbers to that variable. But nowhere is the "volume" variable actually used for anything. If it were warning you about shouldPlaySound1, that would be a different matter. For the volume variable, maybe you intended to add some code later to actually use it? Sometimes mistakes happen where you changed your mind about which variable to use, or used 2 similar names in different places. This sort of compiler warning is trying to let you know that code you went to the trouble to write 8 different cases can't actually do anything because the compiler sees nothing ever uses the result.
 
Wow, you were totally right, I added the Serial.print() lines and it does keep restarting the file. So I just have to figure out how to make it only play when the piezo gets hit? Sorry, I can probably figure it out from here when I have more time to think about it, but I am still a little confused as to why it starts playing even though I haven't hit the Piezo, :confused:

For the volume variable, maybe you intended to add some code later to actually use it? Sometimes mistakes happen where you changed your mind about which variable to use, or used 2 similar names in different places. /QUOTE]

The idea was to measure the peak of the piezo to determine the volume, so if the piezo got hit hard enough it would respond with the drum sound at a certain volume. I saw something like this on a forum here a long time ago and copied it but maybe it's not the best way to go about doing it though.
 
The WAV file probably gets played when the piezo isn't hit because the value read at the A0 and A1 pins is over the threshold value of 5.
I ran this on a T3.6
Code:
void loop(void)
{
  Serial.println(analogRead(A0));
  delay(200);
}
It prints numbers varying from about 450 to 530 when there's no circuit attached to the pin. You may find that even with the piezo attached, it still prints numbers greater than 5.

Pete
 
So I just have to figure out how to make it only play when the piezo gets hit?

Try connecting a resistor from the analog pin to AGND. Starting with 47K. Use higher resistance if you're not getting enough signal for the sensor. Use lower if you get too much noise during times of no activity.

Also in Arduino, click File > Examples > Teensy > USB_MIDI > Piezo_Drum for some ideas about detecting the signal peak.
 
https://forum.pjrc.com/threads/48308-test-code-for-piezo

I found the original forum convo I looked at to figure out the resistor/diode combination I used.

From that link: “I’d like to recommend using 2 resistors (470 and 10K) and 2 signal diodes (1N4148 or 1N914 or similar). The piezo sensor positive should connect to the 470 ohm resistor, and the 2 diodes should connect from the 470 resistor to GND and to 3.3V.”
 
Sorry to bother again with this, I'm new to all the electronics stuff!

This is what I have connected in terms of resistors/diodes (the exact analog pins have changed, but this schematic was just to get the idea):

IMG_3138.jpg

If I change the 10k resistor to 47k, do I have to change the other resistor or diodes?
 
This is what I'm seeing on the serial monitor:

Here's the code:

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

/*This initial setup is important because I have added 2 mixers.
  This means that playSdWav1 and playSdWav2 can be played at the same time*/

AudioPlaySdWav           playSdWav1;
AudioPlaySdWav           playSdWav2;
AudioMixer4              mixer1;
AudioMixer4              mixer2;
AudioOutputI2S           audioOutput;
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(mixer1, 0, audioOutput, 0);
AudioConnection          patchCord6(mixer2, 0, audioOutput, 1);
AudioControlSGTL5000     sgtl5000_1;

#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

// lights
const int yellow = 2;  // led connected to pin 2.
const int white = 3;   // led connected to pin 3.
const int green = 4;   // led connected to pin 4.
const int blue = 5;    // led connected to pin 5.
const int killSwitch = 6;

const int rightPiezo = A10;  // right piezo on analog pin 24(A10)
const int leftPiezo = A11;   // left piezo on analog pin 25(A11)

int rightsensorReading = 0;
int leftsensorReading = 0;
int ledState = LOW;

const int threshold = 30;  /*do we need this if we're using the Peak capture method? */

bool shouldRunPattern1 = true;
bool shouldRunPattern2 = true;

bool shouldPlaySound1 = false;
bool shouldPlaySound2 = false;

long pattern1Start = 0;
long pattern2Start = 0;

void setup() {
  AudioMemory(20);
  sgtl5000_1.enable();
 // sgtl5000_1.volume(0.5);
 
  pinMode(yellow, OUTPUT);
  pinMode(white, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);

}

void loop() {

  /*if (digitalRead(killSwitch) == LOW) {
      return; } */
  if (shouldPlaySound1) {
     Serial.println("Starting Sound1 Play");
    playSdWav1.play("RCAH.WAV");
    delay(2000);
    shouldPlaySound1 = false;
  }
  if (shouldPlaySound2) {
     Serial.println("Starting Sound2 Play");
    playSdWav2.play("LCAH.WAV");
   delay(2000);
    shouldPlaySound2 = false;
    }
    
  // read sensors and set variables
  rightsensorReading = analogRead(rightPiezo);
  leftsensorReading = analogRead(leftPiezo);
  Serial.print("rightsensorReading = ");
  Serial.print(rightsensorReading);
  Serial.print("leftsensorReading = ");
  Serial.print(leftsensorReading);
  Serial.println();

  /* volume control, #s are somewhat subjective,
    will need adjusting once pedal is built*/
  float volume = 0.5;
  if (rightPiezo < 15) {
    volume = 0.0;
  } else if (rightPiezo <= 20) {
    volume = 0.4;
  } else if (rightPiezo <= 25) {
    volume = 0.7;
  } else {
    volume = 1.0;
  }

  if (leftPiezo < 15) {
    volume = 0.0;
  } else if (leftPiezo <= 20) {
    volume = 0.4;
  } else if (leftPiezo <= 25) {
    volume = 0.7;
  } else {
    volume = 1.0;
  }

  // initialize the pattern1
  if (rightsensorReading >= threshold) {
    shouldRunPattern1 = true;
    shouldPlaySound1 = true;
    pattern1Start = millis();
  }
  // initialize the pattern2
  if (leftsensorReading >= threshold) {
    shouldRunPattern2 = true;
    shouldPlaySound2 = true;
    pattern2Start = millis();
  }
  // how long it's been since pattern1 was started
  long pattern1Duration = millis() - pattern1Start;
  // how long it's been since pattern2 was started
  long pattern2Duration = millis() - pattern2Start;
  // change this to change how long the LEDs stay on
  long patternPulseTime = 200;  // .2 seconds
  // run pattern 1
  if (shouldRunPattern1) {
    // green and blue on
    if (pattern1Duration < patternPulseTime) {
      digitalWrite(green, HIGH);
      digitalWrite(blue, HIGH);
    }
    // green and blue off for second half second
    else {
      digitalWrite(green, LOW);
      digitalWrite(blue, LOW);
      shouldRunPattern1 = false;
    }
  }
  // run pattern 2 (same as pattern1 just different leds)
  if (shouldRunPattern2) {
    if (pattern2Duration < patternPulseTime) {
      digitalWrite(yellow, HIGH);
      digitalWrite(white, HIGH);
    } else {
      digitalWrite(yellow, LOW);
      digitalWrite(white, LOW);
      shouldRunPattern2 = false;
    }
  }
}

Thanks for the link Rolfdegen, greetings from Boston! I already saw that one though, I had it linked above. Was there something specific on there you saw that I am missing?
 
Status
Not open for further replies.
Back
Top