Bad news…
This is the class that I use to encapsulate a WAV.
The only propetary function is “Debug(String,int)”, it
simply prints out a string
class Sample{
/* Number of unstopped sounds */
static int numberOfActiveClips=0;
/* Number of clips requested */
static int numberOfRequestedClips=0;
/* Binary data */
byte[] wav;
/* Size of binary data */
int size;
DataLine.Info info;
AudioFormat af;
Vector clipList=new Vector();
/* Constructor */
public Sample(AudioInputStream audioInputStream){
af = audioInputStream.getFormat();
size = (int) (af.getFrameSize() * audioInputStream.getFrameLength());
wav = new byte[size];
info = new DataLine.Info(Clip.class, af, size);
try{
audioInputStream.read(wav, 0, size);
} catch(Exception e){ e.printStackTrace(); }
}
/* Retrivies a Clip from the stored binary data */
public Clip getClip(){
Clip clip,c;
/* Stop and remove finished clips */
Iterator iter=clipList.iterator();
while(iter.hasNext()){
c=(Clip)iter.next();
if(!c.isRunning()){
c.stop();
c.flush();
iter.remove();
numberOfActiveClips--;
}
}
try{
clip = (Clip) AudioSystem.getLine(info);
clip.open(af, wav, 0, size);
} catch(Exception e){ e.printStackTrace(); return null; }
/* Add this clip to the list of unstopped clips */
clipList.add(clip);
numberOfActiveClips++;
numberOfRequestedClips++;
return clip;
}
public static void debug(){
Debug.print("-- Number of active clips: "+numberOfActiveClips,0);
Debug.print("-- Number of requested clips: "+numberOfRequestedClips,0);
}
}
To resolve the problem that clips may live forever, I check
every time a clip is required, what old clips aren’t running
and I stop them.
If I use ONLY one or two Sample, I can request as many
clips as I want and all goes right.
If I use 5/6 Samples after some requests (exactly 64 sample!) Java VM gives me the
following error:
javax.sound.sampled.LineUnavailableException: No Free Voices
at com.sun.media.sound.MixerClip.nSetup(Native Method)
at com.sun.media.sound.MixerClip.getValidVoiceId(MixerClip.java:608)
at com.sun.media.sound.MixerClip.implOpen(MixerClip.java:590)
at com.sun.media.sound.MixerClip.open(MixerClip.java:159)
at fishbros.pyro.Sample.getClip(SoundBank.java:77)
at fishbros.pyro.SoundBank.getSound(SoundBank.java:201)
at fishbros.pyro.SoundBank.playSound(SoundBank.java:249)
at fishbros._teranoid.Ball.controlCollision(Ball.java:421)
at fishbros._teranoid.Ball.live(Ball.java:489)
at fishbros.pyro.EntityRoster.makeEmLive(EntityRoster.java:157)
at fishbros._teranoid.Game.nextFrame(Game.java:290)
at fishbros.pyro.App.run(App.java:299)
at java.lang.Thread.run(Thread.java:536)
It seems like there are no more Line avaible!
What can I do more than simply stop() clips to release lines???
And why if I use only two samples all is OK?
PS: When the GC collectors comes it only slow down
your App for few milleseconds.