Sound Library bugs? (lagging, noise/choppy)

Hi,
I am new to the Sound Library, and I’m experiencing an issue - while playing an mp3 repeatedly, the audio becomes increasingly choppy / play noise(?) as time passes.
I would really really appreciate it if you can help me out. How I do to get rid of it?

I screen-recorded what happens:

From about 0:24 sec ~ in the video, you can see what I’m talking about.

The sound files are played/triggered at an interval decided by the input gained by an accelerometer sensor (from Arduino). The greater the input from the sensor, at faster interval the sound plays. Just after I run the code, the sound plays fine. However, after a while it starts to have this choppy sound and it just increases to the point the audio files are inaudible. It feels like it’s lagging too.

It seems like the shorter the interval - the more rapid the sound is played, (seen 0:19 ~ in the video) the noise / choppy-ness increases faster. So I tried to keep the interval longer. However, it still starts to have this choppy sound after a while, even it succeeds in playing without the noise for a longer period compared to when the triggering intervals are shorter.
It would be great if I can get rid of this bug.

It feels almost like some error/cache is accumulating, thus making it lag & choppy? My guess is, there must be some sort of a method to “flush” out this “cache”…?

Thanks in advance,
and here is my code:

// This example code is in the public domain.

  import processing.serial.*;     // import the Processing serial library
  import processing.sound.*;

  Serial myPort;                  // The serial port
  SoundFile[] file;
int trigger; 
int numsounds = 5;  // Define the number of samples
float inByteX;
float inByteY;
float inByteZ;
// Define a variable to store the randomly generated background color in
int backgroundColor[] = {255, 255, 255};


float x;
float y;
float z;
float tempo;

  void setup() {
    size(640, 480);
    background(0);
    
        // Create a Sound renderer and an array of empty soundfiles
  file = new SoundFile[numsounds];

  // Load 5 soundfiles from a folder in a for loop. By naming
  // the files 1.aif, 2.aif, 3.aif, ..., n.aif it is easy to iterate
  // through the folder and load all files in one line of code.
  for (int i = 0; i < numsounds; i++) {
    file[i] = new SoundFile(this, (i+1) + ".aif");
  }


    // List all the available serial ports
    // if using Processing 2.1 or later, use Serial.printArray()
    //println(Serial.list());

    // I know that the first port in the serial list on my Mac is always my
    // Arduino board, so I open Serial.list()[0].
    // Change the 0 to the appropriate number of the serial port that your
    // microcontroller is attached to.
    myPort = new Serial(this, Serial.list()[3], 9600);

    // read bytes into a buffer until you get a linefeed (ASCII 10):
    myPort.bufferUntil('\n');
    
    trigger = millis();


  }
  
float[] octave = {0.25, 0.5, 1.0, 2.0, 4.0};

  void draw() {

    
     if (millis() > trigger) {
        float rate = octave[int(random(0, octave.length))];  //octave length = 5

        file[int (random(0,4))].play(rate, 1.0);   //Play sounds at random rate from the octaves array
        for (int i = 0; i < 3; i++) {  //Change background colour when sound plays
            backgroundColor[i] = int(random(255));
        }     
        background(backgroundColor[0], backgroundColor[1], backgroundColor[2]);
    
    //How do I make it choose the maximum number and use that as tempo?
    //maximum(inByteX, inByteY, inByteZ){
     //  tempo = maximum
    //}
    
      
        float maximumTempo = max(inByteX, inByteY, inByteZ); 
        maximumTempo = constrain(maximumTempo, 0, 100);
        tempo = map(maximumTempo, 0, 100, 300, 0);
 
        // Create a new triggertime in the future, with a random offset between 200 and 1000 milliseconds
        //if (x > 4){
        //      trigger = millis() + int(tempo);
        //} else {
        //  trigger = millis() + 2000;  //If accelerometer signal is under 4, play at 2000 interval
        //}
        
        //if ((x < 4) && (y < 4) && (z < 4)){
        if (maximumTempo < 4){
          tempo = 2000;  //If accelerometer signal is under 4, play at 2000 ms interval
        };
        trigger = millis() + int(tempo);
    }
  } //End of draw

  // serialEvent method is run automatically by the Processing applet whenever
  // the buffer reaches the  byte value set in the bufferUntil()
  // method in the setup():

  void serialEvent(Serial myPort) {
    // read the serial buffer:
    String myString = myPort.readStringUntil('\n');
    // if you got any bytes other than the linefeed:
    myString = trim(myString);

    // split the string at the commas and convert the sections into integers:
    int sensors[] = int(split(myString, ','));

    // print out the values you got:
    for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
      print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");
    }
    println();  //add a linefeed after all the sensor values are printed
    
    //println("X: "+x+"\t"+"Tempo: "+ tempo);
      
    if (sensors.length > 1) {
      inByteX = map(sensors[0], 0, 1023, 0, 100);
      inByteY = map(sensors[1], 0, 1023, 0, 100);
      inByteZ = map(sensors[2], 0, 1023, 0, 100);
    }
  
    // send a byte to ask for more data:
    myPort.write("A");
  }
4 Likes

Hello. I have a similar problem.

Did you find a solution?

Replying to this only because I had the same problem!

I believe the issue is that the Processing sound library cannot handle many sounds being played in a short interval of time. I’m not sure if there’s a way to get around this unfortunately

My solution to anyone reading this in the future is to find a way to efficiently implement as few sounds as possible :rofl:

Same problem detected. Sadly no solution - I have switched to Beads audio library where I use SamplePlayer class and it works great. Reported issue to github: Stutter and lag when playing multiple samples repeatedly · Issue #74 · processing/processing-sound · GitHub and created sample code to test it without Serial:

import processing.sound.*;

int timer;
SoundFile[] file = new SoundFile[5];

void setup() {
  size(640, 480);
  background(0);
  for (int i=0; i<file.length; i++) {
    file[i] = new SoundFile(this, "http://soundbible.com/grab.php?id=1705&type=wav" );
  }
  timer = millis();

  frameRate(30);
}


int numplays = 0;

void draw() {
  //around 800-1100 plays it will start to stutter
  if (numplays<1000) {
    if (millis() > timer + 20 ) {
      int i = (int)random(0, file.length);
      file[i].play();
      numplays++;
      println(numplays);
      timer = millis();
    }
  }
}