我使用以下代码使用java声音API播放声音文件.
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(stream);
clip.open(inputStream);
clip.start();
Run Code Online (Sandbox Code Playgroud)
调用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 );
}
Run Code Online (Sandbox Code Playgroud)
在 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();
Run Code Online (Sandbox Code Playgroud)
小智 6
你可以把这个代码改为:
假设你的clip1正在播放,你想要在那之后播放一个clip2,你可以:
clip1.start();
while(clip1.getMicrosecondLength() != clip1.getMicrosecondPosition())
{
}
clip2.loop(some int here);
Run Code Online (Sandbox Code Playgroud)
并且,为了使这项工作不延迟你的主要任务(我说这是因为while循环使得工作等待clip1完成,无论接下来的工作是什么......)你可以在你的位置创建一个新线程希望它发生,只需将代码放在run()方法中......好运!
声音剪辑是一种类型或 Line,因此支持 Line 侦听器。
如果您使用addLineListener,您应该在播放开始和停止时获取事件;如果您没有处于循环状态,则应该在剪辑结束时停止。但是,与任何事件一样,在实际播放结束和停止之前可能会有延迟。
让方法等待稍微棘手一些。您可以忙等待(这不是一个好主意)或使用其他同步机制。我认为有一种模式(不确定)用于等待长时间操作以引发完成事件,但这是您可能需要单独发布到 SO 的一般问题。