Playing audio files randomly from a button

Status
Not open for further replies.

nakatano

Member
Hi all,

For an installation, I want to build a simple system where an audio file is randomly choosed on the SD card after a button (and later, a sensor) is pressed.
I have 10 files on the SD card named SDTEST1.WAV, SDTEST2.WAV, SDTEST3.WAV etc.
The button is connected to Digital In #16 on my Teensy3.2 (+ audio shield).
The idea is to concatenate the file name from a string and start the play function automatically.
When the audio file finishes to play, to system stops, waiting for the button to be pressed again.
After many, many tests, I can't find a correct way to concatenate the file name (in the attached code, the issue appears line 85).
I tried a lot of other solutions but none of them is working so, I think I need your help !

Thanks
Nicolas.


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

const int buttonPin = 16;
long randNumber;
int buttonState = 0;


AudioPlaySdWav           playSdWav1;
AudioOutputI2S           i2s1;
AudioConnection          patchCord1(playSdWav1, 0, i2s1, 0);
AudioConnection          patchCord2(playSdWav1, 1, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;


void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  Serial.begin(9600);
  AudioMemory(8);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  SPI.setMOSI(7);
  SPI.setSCK(14);
  if (!(SD.begin(10))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  delay(1000);
}

void playFile(const char *filename)
{
  Serial.print("Playing file: ");
  Serial.println(filename);

  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playSdWav1.play(filename);

  // A brief delay for the library read WAV info
  delay(5);

  // Simply wait for the file to finish playing.
  while (playSdWav1.isPlaying()) {
    // uncomment these lines if you audio shield
    // has the optional volume pot soldered
    //float vol = analogRead(15);
    //vol = vol / 1024;
    // sgtl5000_1.volume(vol);
  }
}

void loop() {

  // cf : https://www.arduino.cc/en/Tutorial/Debounce

  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed. If it is not, the buttonState is LOW:
  if (buttonState == LOW) {
   (playSdWav1.isPlaying() == true); // inverser true et false ?
   Serial.println("Stop playing");
   delay(10); // wait for library to parse WAV info
   // do nothing while playing...
 }

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  else (buttonState == HIGH); {
    // defini le nom aleatoire du fichier Audio
    randNumber = (random(4) + 4); // genere les valeurs 15 et 16 uniquement
    String(myString1) = "SDTEST"; // avec ou sans parentheses autour de myString1 ?
    String(myString2) = ".WAV  "; // idem myString2 ?
    String(myFile) = (myString1 + randNumber + myString2);
    (playSdWav1.isPlaying() == false);
    Serial.println("Start playing");
    playSdWav1.play(String(myFile)); // le pb est bien ici. pourquoi le programme ne reconnait-il
    // pas le nom du fichier ?
    delay(10); // wait for library to parse WAV info
    Serial.println(myFile); // comment stopper la fonction
    // le temps de lire le fichier audio ?

  }

}
 
you should use playSdWav1.play(myFile.c_str());

and if you want a random number from 1 to 10 use randNumber = random(1,11);
 
Hi Manitou, thanks for your help,

So, I modified the code. It compiles and loads but it runs continuously without playing the audio files.
When the button id depressed, the monitor shows SDTEST2.WAV Stop playing Start playing SDTEST4.WAV Stop playing Start playing SDTEST8.WAV Stop playing Start playing, etc
When it's pressed, SDTEST1.WAV Start playing SDTEST8.WAV Start playing SDTEST7.WAV Start playing SDTEST5.WAV Start playing SDTEST8.WAV Start playing, etc

Did I make a mistake in the functions order (the void playFile(const char *filename), line 37) ?
I tried to reverse the "true" and "false" statements (lines 68 and 81), unsuccessfully...
 
for starters, add playSdWav1.play("SDTEST1.WAV"); to the end of your setup(), so you can confirm play/audio works. And normally pinMode for a button is INPUT_PULLUP, so button pin is in known state (unless you have an external pullup or pulldown resistor on the button pin). you need to consider the problem of "button bounce" and probably use

https://www.pjrc.com/teensy/td_libs_Bounce.html
 
As you noticed, I'm not a great programmer !
:)

So, I implemented the debounce function which seems to work properly, now (I forgot it since I usually do this part directly in Pure Data or Max using the [change] objects but this time, the Teensy has to work as a "standalone").

When the button is pressed, the monitor goes :
Start playing
SDTEST9.WAV

When it's depressed :
Stop playing

Unfortunately, no sound file is playing yet, even though I keep the button pressed or depressed.
Any idea ?
(note that the sound files works great with other codes like the WavFilePlayer example).

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

long randNumber;
int buttonState = 0;
const int buttonPin = 16;
Bounce pushbutton = Bounce(buttonPin, 10);  // 10 ms debounce


AudioPlaySdWav           playSdWav1;
AudioOutputI2S           i2s1;
AudioConnection          patchCord1(playSdWav1, 0, i2s1, 0);
AudioConnection          patchCord2(playSdWav1, 1, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;


void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
  AudioMemory(8);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  SPI.setMOSI(7);
  SPI.setSCK(14);
  if (!(SD.begin(10))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}

byte previousState = HIGH;         // what state was the button last time

void playFile(const char *filename)
{
  Serial.print("Playing file: ");
  Serial.println(filename);

  // Start playing the file.  This sketch continues to
  // run while the file plays.
  playSdWav1.play(filename);

  // A brief delay for the library read WAV info
  delay(5);

  // Simply wait for the file to finish playing.
  while (playSdWav1.isPlaying()) {
    // uncomment these lines if you audio shield
    // has the optional volume pot soldered
    //float vol = analogRead(15);
    //vol = vol / 1024;
    // sgtl5000_1.volume(vol);
  }
}

void loop() {

  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed. If it is not, the buttonState is LOW:
 if (pushbutton.update()) {
   if (pushbutton.fallingEdge()) {
   (playSdWav1.isPlaying() == false); // inverser true et false ?
   Serial.println("Stop playing");
   delay(10); // wait for library to parse WAV info
   // do nothing while playing...
 }

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  else {
   // if (count != countPrinted) {
    unsigned long nowMillis = millis();
    // defini le nom aleatoire du fichier Audio
    randNumber = random(1,11); // genere les valeurs 1 a 10
    String(myString1) = "SDTEST"; // avec ou sans parentheses autour de myString1 ?
    String(myString2) = ".WAV  "; // idem myString2 ?
    String(myFile) = (myString1 + randNumber + myString2);
    (playSdWav1.isPlaying() == true);
    Serial.println("Start playing");
    playSdWav1.play(myFile.c_str());
    delay(10); // wait for library to parse WAV info
    Serial.println(myFile); // comment stopper la fonction
    // le temps de lire le fichier audio ?

  }
 }
}
 
Try this.

Code:
#include <Audio.h>
#include <SD.h>
#include <Bounce.h>

long randNumber;
const int buttonPin = 16;
Bounce pushbutton = Bounce(buttonPin, 20);

AudioPlaySdWav           playSdWav1;
AudioOutputI2S           i2s1;
AudioConnection          patchCord1(playSdWav1, 0, i2s1, 0);
AudioConnection          patchCord2(playSdWav1, 1, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;


void setup() {
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT_PULLUP);
  Serial.begin(9600);
  AudioMemory(8);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  SPI.setMOSI(7);
  SPI.setSCK(14);
  if (!(SD.begin(10))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  while (!Serial && millis() < 2500) ; // wait 2.5 sec for Arduino Serial Monitor
  Serial.println("begin random player");
}


void loop() {
  pushbutton.update();
  if (pushbutton.fallingEdge()) {
    randNumber = random(1, 5);
    String myString1  = "SDTEST";
    String myString2  = ".WAV";
    String myFile = myString1 + randNumber + myString2;
    Serial.println(myFile);
    playSdWav1.play(myFile.c_str());
  }
}
 
Or to avoid playing the same song twice in a row, you could generate the random number like this:

Code:
    long newRandNumber;
    do {
      newRandNumber = random(1, 5);
    } while (newRandNumber == randNumber);
    randNumber = newRandNumber;
 
Hi Paul,

It works as in a dream !
I now have to analyse and try to understand my mistakes !
A huge thanks,

Nicolas.
(I'll post some pictures of the installation which will work with reel to reel tape recorders, vintage Tascam M30 mixing console and analog FX pedals, alla Alvin Lucier's I'm sitting in a room, for the exhibition's premiere in March !)
 
Last edited:
Status
Not open for further replies.
Back
Top