Minim: Play a random song out of an array

Hey!
I’m trying to make a sketch that plays a random sound out of a pre-loaded AudioPlayer array in certain for loop conditions.
My problem is that for some reason ALL 3 items in the array play at once when I use – (int) random(3) –

Any suggestions?
Code is as follows:

import ddf.minim.*;
import ddf.minim.effects.*;

float start, runtime;
PImage earth, angry, happy, neutral;
PShape globe;
Minim minim;
AudioPlayer[] playlistGood;
AudioPlayer[] playlistBad;

void setup(){
  size(1200,800, P3D);
  background(32);
  start = millis();

   minim = new Minim(this);
 playlistGood = new AudioPlayer[3];
 playlistGood[0] = minim.loadFile("bestfriends2.mp3");
 playlistGood[1] = minim.loadFile("changeworld.mp3");
 playlistGood[2] = minim.loadFile("bus.mp3");
 
 playlistBad = new AudioPlayer[3];
 playlistBad[0] = minim.loadFile("acting2.mp3");
 playlistBad[1] = minim.loadFile("composting.mp3");
 playlistBad[2] = minim.loadFile("grandchildren.mp3");
 
 
 angry = loadImage("angry.JPG");
 happy = loadImage("happy.JPG");
 neutral = loadImage("neutral.JPG");
   
}

void draw(){
  background(32);
  //smooth();
  lights();
  runtime = millis() - start;
  
 

//sound/visual changes depending on time and position of person
if (mouseX > 1100) {
  earth = angry;
  playlistGood[0].rewind();
  playlistGood[1].rewind();
  playlistGood[2].rewind();
   playlistBad[(int) random(3)].play();

} else if ((mouseX < 1100) && (runtime > 5000)){
  earth = happy;
  playlistBad[0].rewind();
  playlistBad[1].rewind();
  playlistBad[2].rewind();
    playlistGood[(int)random(3)].play();
  
} else {
  println("walking");
  earth = neutral;
}

//reset timer after 15 seconds of inaction
if (runtime >= 20000){
  start = millis();
}
  println("runtime:" + runtime);

  //DRAW GLOBE
  translate(width/2, height/2);
  rotateX(0.2);
  //follow mouse movements
  rotateY(mouseX * 0.002);
  globe = createShape(SPHERE, 300);
  globe.setTexture(earth);
  globe.setStroke(false);
  shape(globe);
  
}

i cut your main program flow out and put in prints:

float start, runtime;
void setup() {
  size(1200,100, P3D);
  start = millis();
}
 int loop = 0;
 
void draw() {
  loop++;
  runtime = millis() - start;
  if (mouseX > 1100) {
    println(loop+" > 1100 "+(int)random(3));
  } else if ((mouseX < 1100) && (runtime > 5000)) {
    println(loop+" < 1100 &&  runtime > 5000 "+(int)random(3));
  } else {
    println(loop+" walking");
  }
  if (runtime >= 20000) {
    start = millis();
    println(loop+" runtime >= 20000");
  }
}


now you see what you are doing to the computers audio player!

Yeesh… What a train wreck! Yes I see now what it’s doing. Actually that’s what I thought it was going to do even when it was just playing one song - it just didn’t show it I guess!

How do I get around this?
Does it need to pick the songs outside of the for loop… even outside of draw? I’m not sure how I would go about doing this. They still need to play from the start when activated by the - for - conditions.

-a- learn to make a good ?toggle? button ( mousePressed ) logic
-b- at setup start all song with .loop and .pause
and the toggle logic for one song would be

  if ( groove.isPlaying() )     groove.pause();
  else                          groove.loop();

while still need to pause all others.

I’m sorry, I don’t understand this at all…

So all songs need to be in setup as

if ( song1.isPlaying() )     song1.pause();
  else                          song1.loop();

if ( song2.isPlaying() )     song2.pause();
  else                          song2.loop();

?
I know (some) mousePressed logic but I don’t know how to apply that to mouseOver (or in this case torsoX coordinates)

Would you then still use .play in the if loops?

no, that would be the logic to toggle one song, like from toggle button press

for more songs
-a- need to use the array with that logic AND
-b- take care of all other songs .pause besides the one you started with .loop

no, if you have a logic to start stop like in mousePressed keyPressed
a .play in draw would overwrite that?
and it would not say .play, it would say
.play.play.play.play.play.play.play.play.play.play.play.play.play.play.play.play
that you should have understood from my above version of your code.

i expected you show us some button code:

a rectangle with mouse over logic, boolean status memory and indication fill green or blue for run stop
and a mousePressed() handling that button logic

Colour me confused…

try this code

// https://discourse.processing.org/t/minim-play-a-random-song-out-of-an-array/14683

import ddf.minim.*;
import ddf.minim.effects.*;

Minim minim;
AudioPlayer[] playlistGood;

void setup() {
  size(800, 800, P3D);
  minim = new Minim(this);
  playlistGood = new AudioPlayer[2];
  playlistGood[0] = minim.loadFile("groove0.mp3");
  playlistGood[1] = minim.loadFile("groove1.mp3");

  for ( int i = 0; i < playlistGood.length; i++ ) {
    playlistGood[i].loop();
    playlistGood[i].pause();
  }
}

// button config
int b1x=700, b1y=100, b1w=80, b1h=30;
boolean set1 = false;
int b2x=700, b2y=200, b2w=80, b2h=30;
boolean set2 = false;
// mouse over rect function
boolean over(int x, int y, int w, int h) {
  if (  
    ( mouseX > x ) && ( mouseX < ( x + w ) ) && 
    ( mouseY > y ) && ( mouseY < ( y + h ) ) 
    )  return true;
  return false;
}

void draw_button() {
  strokeWeight(3);
  // button 1
  if ( over(b1x, b1y, b1w, b1h) ) stroke(200, 0, 200);     // border color
  else                            stroke(0, 200, 200);
  if ( set1 )   fill(0, 200, 0);                           // status fill color
  else          fill(0, 0, 200);
  rect(b1x, b1y, b1w, b1h);
  // button 2
  if ( over(b2x, b2y, b2w, b2h) ) stroke(200, 0, 200);     // border color
  else                            stroke(0, 200, 200);
  if ( set2 )   fill(0, 200, 0);                           // status fill color
  else          fill(0, 0, 200);
  rect(b2x, b2y, b2w, b2h);
}

void draw() {
  background(200, 200, 0);
  draw_button();
}

void mousePressed() {
  if ( over(b1x, b1y, b1w, b1h) ) {                          // button 1
    set1 = ! set1;
    if ( set1 ) {
      set2 = false;                                          // make option group logic unset others
      play_only_one(0);
    } else {
      pause_only_one(0);
    }
  }
  if ( over(b2x, b2y, b2w, b2h) ) {                          // button 2
    set2 = ! set2;
    if ( set2 ) {
      set1 = false;                                          // make option group logic unset others
      play_only_one(1);
    } else {
      pause_only_one(1);
    }
  }
}

void play_only_one(int j ) {
  for ( int i = 0; i < playlistGood.length; i++ ) {
    if ( ! playlistGood[i].isPlaying() && ( i == j ) ) {
      playlistGood[i].loop();  // if not play, start this one
      println("start "+j);
    } else playlistGood[i].pause();                                               // stop the rest
  }
}

void pause_only_one(int j ) {
  if ( playlistGood[j].isPlaying() ) {
    playlistGood[j].pause();
    println("stop "+j);
  }
}


i did NOT use class …
and only the song array ( like you have )
so the buttons are very manual…
but as a first step easy to understand, esp note the OVER function

it is not a random song play, it is a idea for one button for one song structure…
so for your idea need to change.
i wanted to show better buttons and the play one song logic.