我使用以下代码使用java声音API播放声音文件。
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream);
clip.open(inputStream);
clip.start();
对Clip.start()方法的方法调用立即返回,系统在后台线程中播放声音文件。我希望我的方法暂停,直到播放完成。
有没有好办法呢?
编辑:对于对我的最终解决方案感兴趣的每个人,根据Uri的答案,我使用了以下代码:
private final BlockingQueue<URL> queue = new ArrayBlockingQueue<URL>(1);
public void playSoundStream(InputStream stream) {
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream);
clip.open(inputStream);
clip.start();
LineListener listener = new LineListener() {
public void update(LineEvent event) {
if (event.getType() != Type.STOP) {
return;
}
try {
queue.take();
} catch (InterruptedException e) {
//ignore this
}
}
};
clip.addLineListener(listener );
}
答案 0 :(得分:5)
您可以改为使用此代码:
假设你的clip1正在播放,你想要在那之后立即播放clip2,你可以:
clip1.start();
while(clip1.getMicrosecondLength() != clip1.getMicrosecondPosition())
{
}
clip2.loop(some int here);
并且,为了使这项工作不延迟你的主要任务(我说这是因为while循环使得工作等待clip1完成,无论下一步工作是什么......)你可以创建一个新线程你希望它发生的地方,只需将代码放在run()方法中...... 祝你好运!
答案 1 :(得分:4)
声音片段是类型或线条,因此支持线型侦听器。
如果使用addLineListener,则应该在播放开始和停止时获取事件;如果你不在循环中,你应该在剪辑结束时停止。但是,与任何事件一样,在实际播放结束和停止之前可能存在延迟。
使方法等待有点棘手。您可以忙着等待它(不是一个好主意)或使用其他同步机制。我认为有一种模式(不确定)等待一个长期操作来抛出一个完成事件,但这是一个普遍的问题,你可能想要单独发布到SO。
答案 2 :(得分:3)
我更喜欢Java 8中的这种方式:
CountDownLatch syncLatch = new CountDownLatch(1);
try (AudioInputStream stream = AudioSystem.getAudioInputStream(inStream)) {
Clip clip = AudioSystem.getClip();
// Listener which allow method return once sound is completed
clip.addLineListener(e -> {
if (e.getType() == LineEvent.Type.STOP) {
syncLatch.countDown();
}
});
clip.open(stream);
clip.start();
}
syncLatch.await();
答案 3 :(得分:0)
从JDK8开始,Clip
的监听器就是一种错误(即,它可能会发生两次单次重放音频(.start()
)而触发Type.STOP。
因此我会使用类似的东西:
Clip[] myBunchOfClipsToPlaySequentially=new Clip[A_BUNCH];
//
// [load actual clips...]
// [...]
//
for(Clip c: myBunchOfClipsToPlaySequentially)
while(c.getFramePosition()<c.getFrameLength())
Thread.yield(); // Note that if we simply put a NO-OP instead (like a
// semicolon or a {}), we make our CPU
// cry). Thread.yield() allows for almost 0% CPU consumption.
此外,你可以看看JFX8提供的新AudioClip类(有一些漂亮的方法可以摆弄)
答案 4 :(得分:0)
我使用了wait / notify来实现它。仅供参考。
final Clip clip = AudioSystem.getClip(mixerInfo);
clip.addLineListener(new LineListener(){
@Override
public void update(LineEvent e) {
if (e.getType()==LineEvent.Type.STOP){
synchronized(clip){
clip.notifyAll();
}
System.err.println("STOP!");
}
}
});
clip.open(as);
clip.start();
while (true){
synchronized(clip){
clip.wait();
}
if (!clip.isRunning()){
break;
}
}
clip.drain();
clip.stop();
clip.close();
答案 5 :(得分:0)
不确定我是否可以代表其他人发言,这个帖子很旧了。但是我使用剪辑库来播放我的 .wav 文件,然后在声音文件运行的时间内让线程休眠:
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
System.out.println("Clip Started");
Thread.sleep(162000); //Length of time in milliseconds
System.out.println("Clip finished");
对我来说就像一个魅力,我正在监控我的处理器,整个程序最多使用了 4%!