I have always run multiple sounds like this. I don't spawn a new thread as I guess javaSound already runs clips in an another threads. Main "game loop" may continue doing its own stuff. App may register listeners for callbacks or use getters to see what clips are doing.
Sometimes if we are to make multimedia or game application its easier to just use getters. Running gameloop 30-60fps gives enough granularity for most cases and we have a total control of what happens and when. This little testapp playbacks two wav files, first is run once, second is started after 3sec, second loops.
// java -cp ./classes SoundTest1 clip1=sound1.wav clip2=sound2.wav
import java.util.*;
import java.io.*;
import java.net.URL;
import javax.sound.sampled.*;
public class SoundTest1 {
public Clip play(String filename, boolean autostart, float gain) throws Exception {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File(filename));
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.setFramePosition(0);
// values have min/max values, for now don't check for outOfBounds values
FloatControl gainControl = (FloatControl)clip.getControl(FloatControl.Type.MASTER_GAIN);
gainControl.setValue(gain);
if(autostart) clip.start();
return clip;
}
public static void main(String[] args) throws Exception {
Map<String,String> params = parseParams(args);
SoundTest1 test1 = new SoundTest1();
Clip clip1 = test1.play(params.get("clip1"), true, -5.0f);
Clip clip2 = test1.play(params.get("clip2"), false, 5.0f);
final long duration=Long.MAX_VALUE;
final int interval=500;
float clip2IncGain=0.4f;
for(long ts=0; ts<duration; ts+=interval) {
System.out.println(String.format("clip1=%d/%d(%.2f), clip2=%d/%d(%.2f)"
,clip1.getFramePosition(), clip1.getFrameLength()
,((FloatControl)clip1.getControl(FloatControl.Type.MASTER_GAIN)).getValue()
,clip2.getFramePosition(), clip2.getFrameLength()
,((FloatControl)clip2.getControl(FloatControl.Type.MASTER_GAIN)).getValue()
));
if (ts>6000 && !clip2.isRunning()) {
clip2.setFramePosition(0);
clip2.start();
}
if (!clip1.isRunning()) {
clip1.close();
}
if(ts % 2000 == 0) {
// values have min/max values, for now don't check for outOfBounds values
FloatControl gainControl = (FloatControl)clip2.getControl(FloatControl.Type.MASTER_GAIN);
float oldVal=gainControl.getValue();
clip2IncGain = oldVal>=5.5 ? clip2IncGain*-1
: oldVal<=-5.5 ? clip2IncGain*-1
: clip2IncGain;
gainControl.setValue(oldVal+clip2IncGain);
}
Thread.sleep(interval);
}
}
private static Map<String,String> parseParams(String[] args) {
Map<String,String> params = new HashMap<String,String>();
for(String arg : args) {
int delim = arg.indexOf('=');
if (delim<0) params.put("", arg.trim());
else if (delim==0) params.put("", arg.substring(1).trim());
else params.put(arg.substring(0, delim).trim(), arg.substring(delim+1).trim() );
}
return params;
}
}
See JavaSound documentation for more information.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…