I have a Sound class that contains a method that, when called, plays a sound using a Clip object (in this case, clip
).
public static void play()
I came across this post via a reference in a similar question.
Yes, the number of Clips playing at once can contribute to the lag, but I don't know how to predict how much of an effect it will be, as this depends on how the JVM interacts with the OS.
You might be able to aid the situation by making the buffer size of the Clip smaller. SourceDataLine and Clip both seem to only allow interactions with incoming requests at buffer boundaries (I'm not sure this is a 100% accurate statement). Specifying the Clip's buffer size is a bit circuitous, as it requires obtaining the data as a PCM array. But if you wish to give it a try, the API is here.
A good way to reduce the number of lines is to use a sound library like TinySound. Many of the programmers at Java-gaming.org have used this library with success.
Another alternative that I'm promoting is AudioCue, a class I recently wrote for concurrent Clip
playback. The license is BCD, source is provided, so feel free to examine, tinker with, and make use of the code. AudioCue
doesn't reduce the number of output lines (yet). But if you are doing the common thing of managing multiple copies of the same cue, it could help in this regard as all concurrent instances are mixed down to a single output. Basic principle: the file is loaded into an array and played back via cursors that iterate over the array and merge their output into a SourceDataLine
. This setup also allows implementation of smooth, real-time volume, panning and pitch fading.
I have had the same kind of problems in the past, and something which worked for me is adding a line listener for whenever a line has finished, and closing it.
The code underneath is a stripped down version of what I use:
music = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(Sound.class.getResource("/sounds" + filename));
music.open(ais);
music.addLineListener(new LineListener(){
public void update(LineEvent e){
if(e.getType() == LineEvent.Type.STOP){
e.getLine().close();
}
}
});
music.start();
When you create the clip, just add in the line listener. When you reset the clip using your play function, it should play properly. I hope this works for you!