We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSound,  Music Libraries › Minim - changing file based on variable
Page Index Toggle Pages: 1
Minim - changing file based on variable (Read 2939 times)
Minim - changing file based on variable
Apr 30th, 2010, 10:58pm
 
Hi,

I'm trying to get my code to play a different file based on the outcome of a calculation which sets a variable.

The numbers generated are between 0.0 and 19.0 and should combine with ".wav" to create a filename (the correct files are sitting the folder).

If I remove the minim functions (calling 'song' etc) the animation runs fine (obviously it doesn't play the sound file). But when I try to add the sound in, the animation stops after one sound has played.

I tried using a bunch of 'song' values (song1, song2, etc) and declaring them in setup(), then calling them with if and else if, but this didn't seem to work

Any ideas?
Thanks,
Andrew

Code:
import ddf.minim.*;

int x1=0; int y1; int rw=10; int rh;
int i=10;
float xMouse;
int low1=50; int up1=100; //colours 1
int low2=130; int up2=200; //colours 2
int low3=100; int up3=204; //colours 3
float time; float run=75; float runInt;
int counter=0;
float tone;
Minim minim;
AudioPlayer song;


void setup()
{
 size(500,500);
 background(255);
 noStroke();
 smooth();
}

void draw()
{
 time=round(random(0,500)/10)*10;
 if ((run-10)<=millis())
 {
   if((run+10)>=millis())
   {
     linesRegenerate();
     runInt=(mouseX/4)+20;
     run=run+runInt;
   }
 }
}

void linesRegenerate()
{
 for (float xpos=time-i; xpos<time; xpos=xpos+10)
 {
   y1=mouseY;
   rh=2*(250-y1);
   fill(255);
   rect(xpos,0,rw,500);
   float col1=random(low1,up1);
   float col2=random(low2,up2);
   float col3=random(low3,up3);
   fill(col1,col2,col3);
   tone=round(((col1+col2+col3)/9.6)-29);
   rect(xpos,y1,rw,rh);
   minim = new Minim(this);
   println(tone+".wav");
   song = minim.loadFile(tone+".wav");
   song.loop(0);
 }
}

void stop()
{
 song.close();  
 minim.stop();
 super.stop();
}
Re: Minim - changing file based on variable
Reply #1 - May 1st, 2010, 7:06am
 
minim = new Minim(this);
   println(tone+".wav");
   song = minim.loadFile(tone+".wav");

should NOT be in your main loop. it's trying to load the entire song from disc every frame, 60 times a second. move it to setup.
Re: Minim - changing file based on variable
Reply #2 - May 1st, 2010, 11:27pm
 
Presumably that means I’ll have to define each sound track individually (there are 20, about two seconds each), so I’ll have song1, song2, song3, etc.
I’ve tried that on the code below, but it still doesn’t seem to work. If you comment out the lines

song0 = minim.loadFile("0.0.wav");

and

song0.loop(0);

the animation runs, if you leave them in, it seems to stop before the animation is run.

Any ideas?
Cheers koogy.

Code:
import ddf.minim.*;

int x1=0; int y1; int rw=10; int rh;
int i=10;
float xMouse;
int low1=50; int up1=100; //colours 1
int low2=130; int up2=200; //colours 2
int low3=100; int up3=204; //colours 3
float time; float run=75; float runInt;
int counter=0;
float tone;
Minim minim;
AudioPlayer song0;

void setup()
{
 size(500,500);
 background(255);
 noStroke();
 smooth();
 minim = new Minim(this);
 song0 = minim.loadFile("0.0.wav");
}

void draw()
{
 time=round(random(0,500)/10)*10;
 if ((run-10)<=millis())
 {
   if((run+10)>=millis())
   {
     linesRegenerate();
     runInt=(mouseX/4)+20;
     run=run+runInt;
   }
 }
}

void linesRegenerate()
{
 for (float xpos=time-i; xpos<time; xpos=xpos+10)
 {
   y1=mouseY;
   rh=2*(250-y1);
   fill(255);
   rect(xpos,0,rw,500);
   float col1=random(low1,up1);
   float col2=random(low2,up2);
   float col3=random(low3,up3);
   fill(col1,col2,col3);
   tone=round(((col1+col2+col3)/9.6)-29);
   rect(xpos,y1,rw,rh);
   println(tone+".wav");
   song0.loop(0);
 }
}

void stop()
{
 song0.close();
 minim.stop();
 super.stop();
}
Re: Minim - changing file based on variable
Reply #3 - May 2nd, 2010, 4:20am
 
this

 if ((run-10)<=millis())
 {
   if((run+10)>=millis())
   {

looks very narrow in terms of acceptable values.

if you write it
 if ((run-10) <= millis() && (run+10) >= millis())
(which is equivalent) and put a debug printf as an else block you'll notice that the condition always fails (at least it does here, loading a 2 second wav in setup() means that millis() is 382 before it ever gets to the draw() so it's never true...)
Re: Minim - changing file based on variable
Reply #4 - May 2nd, 2010, 2:29pm
 
Thanks koogy, that's got it a bit further.

I now get the sounds playing for the first few seconds but then they stop.

I took your advice and added in the println code to debug, and I also have another line which prints the name of the file which should be called.

In the print area, when the program first runs, every line printed is the file name (i.e. 1.0.wav, 3.0.wav,etc, which is correct), after a while I get the 'error' line I made popping in every 5 lines or so. This then increases until there are more error lines than filename lines.

Quote:
10.0.wav
time false
time false
9.0.wav
time false
time false
time false
12.0.wav
time false
time false
time false
5.0.wav
time false
time false
time false
12.0.wav
time false
time false
time false
3.0.wav


Hope that makes sense, do you have any ideas?
Thanks,
Andrew.

The code below has the references to files commented out so you shouldn't get errors

Code:
import ddf.minim.*;

int x1=0; int y1; int rw=10; int rh;
int i=10;
float xMouse;
int low1=50; int up1=100; //colours 1
int low2=130; int up2=200; //colours 2
int low3=100; int up3=204; //colours 3
float time; float run=75; float runInt;
int counter=0;
float tone;
Minim minim;
AudioPlayer snd0; AudioPlayer snd1;
AudioPlayer snd2; AudioPlayer snd3;
AudioPlayer snd4; AudioPlayer snd5;
AudioPlayer snd6; AudioPlayer snd7;
AudioPlayer snd8; AudioPlayer snd9;
AudioPlayer snd10; AudioPlayer snd11;
AudioPlayer snd12; AudioPlayer snd13;
AudioPlayer snd14; AudioPlayer snd15;
AudioPlayer snd16; AudioPlayer snd17;
AudioPlayer snd18; AudioPlayer snd19;

void setup()
{
 size(500,500);
 background(255);
 noStroke();
 smooth();
 minim = new Minim(this);
 //snd0 = minim.loadFile("0.0.wav"); snd1 = minim.loadFile("1.0.wav");
 //snd2 = minim.loadFile("2.0.wav"); snd3 = minim.loadFile("3.0.wav");
 //snd4 = minim.loadFile("4.0.wav"); snd5 = minim.loadFile("5.0.wav");
 //snd6 = minim.loadFile("6.0.wav"); snd7 = minim.loadFile("7.0.wav");
 //snd8 = minim.loadFile("8.0.wav"); snd9 = minim.loadFile("9.0.wav");
 //snd10 = minim.loadFile("10.0.wav"); snd11 = minim.loadFile("11.0.wav");
 //snd12 = minim.loadFile("12.0.wav"); snd13 = minim.loadFile("13.0.wav");
 //snd14 = minim.loadFile("14.0.wav"); snd15 = minim.loadFile("15.0.wav");
 //snd16 = minim.loadFile("16.0.wav"); snd17 = minim.loadFile("17.0.wav");
 //snd18 = minim.loadFile("18.0.wav"); snd19 = minim.loadFile("19.0.wav");
}

void draw()
{
 time=round(random(0,500)/10)*10;
 if ((run-150) <= millis() && (run+150) >= millis())
 {
   linesRegenerate();
   runInt=(mouseX/4)+20;
   run=run+runInt;
 }
 else {println("time false");}
}

void linesRegenerate()
{
 for (float xpos=time-i; xpos<time; xpos=xpos+10)
 {
   y1=mouseY;
   rh=2*(250-y1);
   fill(255);
   rect(xpos,0,rw,500);
   float col1=random(low1,up1);
   float col2=random(low2,up2);
   float col3=random(low3,up3);
   fill(col1,col2,col3);
   tone=round(((col1+col2+col3)/9.6)-29);
   rect(xpos,y1,rw,rh);
   println(tone+".wav");
   //if (tone==0.0) {snd0.play();}
   //else if (tone==1.0) {snd1.play();} else if (tone==2.0) {snd2.play();}
   //else if (tone==3.0) {snd3.play();} else if (tone==4.0) {snd4.play();}
   //else if (tone==5.0) {snd5.play();} else if (tone==6.0) {snd6.play();}
   //else if (tone==7.0) {snd7.play();} else if (tone==8.0) {snd8.play();}
   //else if (tone==9.0) {snd9.play();} else if (tone==10.0) {snd10.play();}
   //else if (tone==11.0) {snd11.play();} else if (tone==12.0) {snd12.play();}
   //else if (tone==13.0) {snd13.play();} else if (tone==14.0) {snd14.play();}
   //else if (tone==15.0) {snd15.play();} else if (tone==16.0) {snd16.play();}
   //else if (tone==17.0) {snd17.play();} else if (tone==18.0) {snd18.play();}
   //else {snd19.play();}
 }
}

void stop()
{
 snd0.close(); snd1.close(); snd3.close();
 snd4.close(); snd5.close(); snd6.close();
 snd7.close(); snd8.close(); snd9.close();
 snd10.close(); snd11.close(); snd12.close();
 snd13.close(); snd14.close(); snd15.close();
 snd16.close(); snd17.close(); snd18.close();
 snd19.close();
 minim.stop();
 super.stop();
}
Re: Minim - changing file based on variable
Reply #5 - May 2nd, 2010, 3:06pm
 
arrays - http://processing.org/reference/Array.html

public static final int NUM_WAVS = 20;
AudioPlayer[] snd = new AudioPlayer[NUM_WAVS];

...

for (int i - 0 ; i < NUM_WAVS ; i++) {
 snd[i] = minim.loadFile(i + ".0.wav");
}

...
//if (tone==0.0) {snd0.play();}
//...
//else {snd19.play();}
// can replace that whole block with:
snd[(int)tone].play;
// might be better if tone is an int but check the values for rounding errors
// and float tone; is funnier if you know your kraftwerk...

generally if you're typing the same code again and again with only tiny things different on each line it's a sign that you are doing it wrong.

none of this fixes your problem, just makes the code tidier / readable. i have no real idea what you're trying to do, which makes it hard to fix...
Re: Minim - changing file based on variable
Reply #6 - May 2nd, 2010, 3:27pm
 
(slight bug in the above - you'll need to constrain tone from 0 to 19 before using it as an index into your array)

"In the print area, when the program first runs, every line printed is the file name (i.e. 1.0.wav, 3.0.wav,etc, which is correct), after a while I get the 'error' line I made popping in every 5 lines or so. This then increases until there are more error lines than filename lines."

a quick play seems to suggest that mouseX determines time between notes and thus the number of misses you see. i get no misses when mouse is hard left, 5 or 6 when mouse is hard right. but it never stops.

which makes me think it's a sound problem. am wondering whether you need to rewind before playing or set the AudioPlayer to loop. are the samples just finishing?

http://code.compartmental.net/minim/javadoc/ddf/minim/AudioPlayer.html
Re: Minim - changing file based on variable
Reply #7 - May 2nd, 2010, 4:05pm
 
I had a look at arrays but I couldn't get my head around them, the code you provided helps though, thanks.

I do get a little bit of play out of it though. Although it seems to be fairly random, the position of the mouse pointer doesn't seem to affect things.

I get
ArrayIndexOutOfBounds Exception: 20 (or Exception: 21) or
NullPointerException after the code runs for a bit.

Is this trying to call a number outside the array limits? If so how do I stop it, or prevent it from stopping the code running?

I'll try and explain the idea a bit better. I had to build on a previous project (which was the lines) and add interactivity and sound.

I want the colour of the lines to correspond to the tone of sound which is played. Movement of the mouse in the x direction speeds or slows the line generation, and in the y direction will control the volume.

The colour generated is random (with some level of control so that they remain cohesive). The numbers from the colour are calculated to give a number between 0 and 19 which should correspond to the sound file played.

Thanks for your help koogy, really appreciate it.

Code:
import ddf.minim.*;

int x1=0; int y1; int rw=10; int rh;
float xMouse;
int d=10;
int low1=50; int up1=100; //colours 1
int low2=130; int up2=200; //colours 2
int low3=100; int up3=204; //colours 3
float time; float run=75; float runInt;
int counter=0;
float tone;
Minim minim;
public static final int NUM_WAVS = 20;
AudioPlayer[] snd = new AudioPlayer[NUM_WAVS];

void setup()
{
 size(500,500);
 background(255);
 noStroke();
 smooth();
 minim = new Minim(this);
 for (int i = 0 ; i < NUM_WAVS ; i++) {
   snd[i] = minim.loadFile(i + ".0.wav");
 }
}

void draw()
{
 time=round(random(0,500)/10)*10;
 if ((run-100) <= millis() && (run+100) >= millis())
 {
   linesRegenerate();
   runInt=(mouseX/4)+20;
   run=run+runInt;
 }
 else {println("time false");}
}

void linesRegenerate()
{
 for (float xpos=time-d; xpos<time; xpos=xpos+10)
 {
   y1=mouseY;
   rh=2*(250-y1);
   fill(255);
   rect(xpos,0,rw,500);
   float col1=random(low1,up1);
   float col2=random(low2,up2);
   float col3=random(low3,up3);
   fill(col1,col2,col3);
   tone=round(((col1+col2+col3)/9.6)-29);
   constrain(tone, 0, 19);
   rect(xpos,y1,rw,rh);
   println(tone+".wav");
   snd[(int)tone].loop(0);
 }
}

void stop()
{
 minim.stop();
 super.stop();
}
Re: Minim - changing file based on variable
Reply #8 - May 2nd, 2010, 6:12pm
 
Never mind, I got it working.
There was a problem with my calculation that changed the sum of the colour components into a number between 0 and 19, which had numbers coming through as high as 23.

Thanks for all your help koogy
Re: Minim - changing file based on variable
Reply #9 - May 3rd, 2010, 3:17am
 
ha, that's exactly what i meant when i wrote

"(slight bug in the above - you'll need to constrain tone from 0 to 19 before using it as an index into your array)"

where you were testing for each value individually you had an else case that caught everything over 19 and played 19.0.wav. and i just figured that the values were always going to be 0-19. but when i ran it i was getting 20s and 21s.

constrain() is a method btw - http://processing.org/reference/constrain_.html
Page Index Toggle Pages: 1