Minim: Sound won't stop (beacause of if statement?)

edited July 2014 in Library Questions

I trigger a sound when a switch is flipped on an Arduino.

Unfortunatly the sound keeps looping and feeding back, presumably because the condition says to keep doing it until the switch is changed.

How do I get the sound to just play once each time the switch changes?

Here is my code:

import ddf.minim.*;

Minim minim;
AudioPlayer song;

import processing.serial.*;

Serial myPort;  // Create object from Serial class
int val;      // Data received from the serial port

void setup() 
{
  size(200, 200);
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
  String portName = Serial.list()[1];
  myPort = new Serial(this, portName, 9600);

  minim = new Minim(this);  
}

void draw()
{
  if ( myPort.available() > 0) {  // If data is available,
    val = myPort.read();         // read it and store it in val
  }
  background(255);             // Set background to white
  if (val == 0) {              // If the serial value is 0,
    fill(0);                   // set fill to black
    text("button is '0'",10,30);

    // this loads first noise from the data folder
    song = minim.loadFile("btn06.mp3");
    song.play();
  } 
  if (val == 1) {                       // If the serial value is not 0,
    fill(204);                 // set fill to light gray
    text("button is '1'",10,30);

    // this loads second noise from the data folder
    song = minim.loadFile("btn08.mp3");
    song.play();
  }
  rect(50, 50, 100, 100);
}

Answers

  • Answer ✓

    Beware, once val has a value of 0 or 1, as long as it has this value, you attempt to load a MP3 file on each call of draw(), ie. some 60 times per second.

    You should have two song variables, load them in setup() instead, and play them when the state change, not on a value of state. So, perhaps keep the previous value of val, and compare the new value with the old one: only when they are different, trigger the sound. Don't forget to assign the new value to the old one just after.

  • edited July 2014

    That makes sense, thanks!. I've tried to do something similar but can't seem to figure out a conditional statement that runs IF the variable changes from one string to another (switchOnePosition goes from "state 0" to "state 1" for example).

    The code below shows what I currently have:

    import ddf.minim.*;
    
    Minim minim;
    AudioPlayer song;
    
    
    
    import processing.serial.*;
    
    Serial myPort;  // Create object from Serial class
    int val;      // Data received from the serial port
    
    String switchOnePosition = "statex";
    
    void setup() 
    {
      size(200, 200);
      // I know that the first port in the serial list on my mac
      // is always my  FTDI adaptor, so I open Serial.list()[0].
      // On Windows machines, this generally opens COM1.
      // Open whatever port is the one you're using.
      String portName = Serial.list()[1];
      myPort = new Serial(this, portName, 9600);
    
      minim = new Minim(this);
    
    }
    
    void draw()
    {
      if ( myPort.available() > 0) {  // If data is available,
        val = myPort.read();         // read it and store it in val
      }
      background(255);             // Set background to white
      if (val == 0) {              // If the serial value is 0,
        fill(0);                   // set fill to black
    
        switchOnePosition = "state 0";
    
        text("button is "+switchOnePosition,10,30);
      } 
      if (val == 1) {                       // If the serial value is not 0,
        fill(204);                 // set fill to light gray
    
        switchOnePosition = "state 1";
    
        text("button is "+switchOnePosition,10,30);
      }
      rect(50, 50, 100, 100);
    
    
      //Play Sounds
    
      if (switchOnePosition == "state 1"){
         // this loads second noise from the data folder
        song = minim.loadFile("btn08.mp3");
        song.play(); 
      }
    
       if (switchOnePosition == "state 0"){
         // this loads second noise from the data folder
        song = minim.loadFile("btn06.mp3");
        song.play(); 
      }
    
    }
    
  • Fixed it, I needed three states for the switch variable (off, playsnd and waiting), this combined with IFF AND statements that combine the switch value and the variable state result in the sound being played only once.

    Incase any other beginners are puzzled by the same, here's the code I used:

    import ddf.minim.*;
    
    Minim minim;
    AudioPlayer song;
    
    import processing.serial.*;
    
    Serial myPort;  // Create object from Serial class
    int val;      // Data received from the serial port
    
    //VARIABLES FOR THE SWITCH
    String switchOnePosition = "state X";
    String switchOneUp = "off";  // will change between "off", "playsnd" or "waiting"
    String switchOneDown = "off";  // will change between "off", "playsnd" or "waiting"
    
    void setup()
    {
      size(200, 200);
      // Open Com6 (port 1)
      String portName = Serial.list()[1];
      myPort = new Serial(this, portName, 9600);
    
      minim = new Minim(this);
    }
    
    void draw()
    {
      if ( myPort.available() > 0) {  // If data is available,
        val = myPort.read();         // read it and store it in val
      }
      background(255);             // Set background to white
    
      //FIRST SWITCH STATE
      if ((val == 0) && (switchOneUp == "off")) {              // If the serial value is 0,
        fill(0);                   // set fill to black
    
        switchOnePosition = "state 0";
        switchOneUp = "playsnd";
    
        text("button is "+switchOnePosition,10,30);
      }
    
      //SECOND SWITCH STATE
      if ((val == 1) && (switchOneDown == "off")) {                       // If the serial value is not 0,
        fill(204);                 // set fill to light gray
    
        switchOnePosition = "state 1";
        switchOneDown = "playsnd";
    
        text("button is "+switchOnePosition,10,30);
      }
    
      //DRAW RECTANGLE (that changes on different switch states)
      rect(50, 50, 100, 100);
    
      //PLAY SOUNDS
      if (switchOneUp == "playsnd"){
        // this loads first noise from the data folder
        song = minim.loadFile("btn01.mp3");
        song.play();
        switchOneUp = "waiting";
        switchOneDown = "off";
      }
    
       if (switchOneDown == "playsnd"){
        // this loads second noise from the data folder
        song = minim.loadFile("btn04.mp3");
        song.play();
        switchOneUp = "off";
        switchOneDown = "waiting";
      }
    
    }
    
  • edited July 2014

    Data type String isn't appropriate for "state" variables! Especially when using operator == to check them out!
    Instead, use int constants to represent those states.
    And since switchOnePosition only got 2 states, boolean is pretty enough! :D

    http://processing.org/reference/boolean.html

    static final int OFF = -1, PLAY_SND = 0, WAITING = 1;
    int switchOneUp = OFF, switchOneDown = OFF;
    
    boolean switchOnePosition;
    
  • What I had in mind (untested):

    import ddf.minim.*;
    
    Minim minim;
    AudioPlayer song1, song2;
    
    import processing.serial.*;
    
    Serial myPort;  // Create object from Serial class
    int val, int prevVal;      // Data received from the serial port
    
    void setup()
    {
      size(200, 200);
      String portName = Serial.list()[1];
      myPort = new Serial(this, portName, 9600);
    
      minim = new Minim(this); 
      song1 = minim.loadFile("btn06.mp3");
      song2 = minim.loadFile("btn08.mp3");
    }
    
    void draw()
    {
      if ( myPort.available() > 0) {  // If data is available,
        val = myPort.read();         // read it and store it in val
      }
      background(255);             // Set background to white
      if (val != prevVal && val == 0) { If the serial value goes to 0,
        fill(0);                   // set fill to black
        text("button is '0'",10,30);
    
        song1.play();
        prevVal = val;
      }
      if (val != prevVal && val == 1) { If the serial value goes to 0,
        fill(204);                 // set fill to light gray
        text("button is '1'",10,30);
    
        song2.play();
        prevVal = val;
      }
      rect(50, 50, 100, 100);
    }
    
Sign In or Register to comment.