Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: Playing audio files randomly from a button

  1. #1
    Junior Member
    Join Date
    Feb 2016
    Posts
    9

    Playing audio files randomly from a button

    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 ?
    
      }
    
    }

  2. #2
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    1,925
    you should use playSdWav1.play(myFile.c_str());

    and if you want a random number from 1 to 10 use randNumber = random(1,11);

  3. #3
    Junior Member
    Join Date
    Feb 2016
    Posts
    9
    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...

  4. #4
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    1,925
    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

  5. #5
    Junior Member
    Join Date
    Feb 2016
    Posts
    9
    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 ?
    
      }
     }
    }

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,928
    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());
      }
    }

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,928
    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;

  8. #8
    Junior Member
    Join Date
    Feb 2016
    Posts
    9
    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 by nakatano; 01-14-2018 at 04:32 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •