英文:
javax.sound.sampled.Clip in Java stops working after a while
问题
我一直在一个项目中使用Java Clip,但是我遇到了一个奇怪的错误。有问题的代码部分如下,它应该从名为"path"的文件中播放声音:
public static void playSound(String path)
{
logger.info("Playing " + path);
Clip clip = null;
try {
clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new BufferedInputStream(path)));
clip.start();
} catch (LineUnavailableException e) {
System.err.println("error while playing " + path);
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
它应该播放一堆文件,但显然发生了奇怪的事情。正如您在这里看到的,它成功播放了一些声音(我也能听到它们),但突然之间,当播放一个文件时,我收到了一个LineUnavailableException异常(在不同的运行中,引发错误的文件也会更改),而我已经播放过了:
我当然已经谷歌了这个错误,并发现像这样的错误可能是由于播放Clip不支持的声音文件类型引起的(这也是错误告诉我的)。然而,在这种情况下,当它尝试播放已经播放过的声音时,剪辑会失败(因此我知道它的类型受支持)。这可能是因为我播放了太多声音(其中一些持续时间只有0.5秒),在太短的时间间隔内(每秒两个声音)?可能的原因是什么?
如果有帮助的话,我在Linux(Ubuntu)工作站上使用OpenJDK 20运行我的应用程序。
提前感谢您的帮助!
顺便说一句,我还尝试过缓存我播放的文件(以避免打开太多文件),仅加载它们一次,并使用ByteArrayInputStream提供clip.open(),但没有太大的成功。
英文:
I've been using Java Clip for a project, but I've stumbled into a strange error. The incriminated piece of code is this, which should just play a sound reading it from the file named path
public static void playSound(String path)
{
logger.info("Playing " + path);
Clip clip = null;
try {
clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new BufferedInputStream(path)));
clip.start();
} catch (LineUnavailableException e) {
System.err.println("error while playing " + path);
e.printStackTrace();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
It should play a bunch of files, but clearly something weird happens. As you can see here, it plays successfully some sounds (I can also here them), but, all in a sudden, I get a LineUnavailableException while playing a file (in different runs, the file causing the error changes too), that I've already played:
21:35:42.478 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/01 Title Screen.wav
21:35:44.289 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/02 Stage Start.wav
21:35:47.114 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/03 Main BGM.wav
21:35:47.555 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:47.921 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:48.138 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX bomb in place.wav
21:35:48.297 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:48.663 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:49.026 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:49.392 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:50.126 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/explosion.wav
21:35:50.448 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX bomb in place.wav
21:35:50.510 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:50.876 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:51.242 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:51.609 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:52.429 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/explosion.wav
21:35:53.095 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:53.494 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:53.860 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:54.226 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:54.559 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/03 Main BGM.wav
21:35:54.592 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:54.959 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:55.326 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:55.693 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:56.059 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:56.228 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX bomb in place.wav
21:35:56.426 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:56.792 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:57.159 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:57.675 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:58.125 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:58.225 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/explosion.wav
21:35:58.492 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:58.858 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:59.226 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:59.594 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:35:59.960 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX bomb in place.wav
21:35:59.965 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:00.332 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:00.699 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:01.065 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:01.442 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:01.809 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:01.960 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/explosion.wav
21:36:02.009 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/03 Main BGM.wav
21:36:02.176 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:02.543 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:02.910 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:03.275 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:03.643 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:04.009 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:04.087 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX bomb in place.wav
21:36:04.376 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:04.776 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:05.142 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:06.009 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:06.075 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/explosion.wav
21:36:06.375 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:06.742 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
21:36:07.131 [JavaFX Application Thread] INFO app.jbomberman.audio.AudioPlayer - Playing sounds/Bomberman SFX horizontal.wav
error while playing sounds/Bomberman SFX horizontal.wav
javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
at java.desktop/com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:484)
at java.desktop/com.sun.media.sound.DirectAudioDevice$DirectClip.implOpen(DirectAudioDevice.java:1241)
at java.desktop/com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:115)
at java.desktop/com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1038)
at java.desktop/com.sun.media.sound.DirectAudioDevice$DirectClip.open(DirectAudioDevice.java:1134)
at app.jbomberman@1.0-SNAPSHOT/app.jbomberman.audio.AudioPlayer.playSound(AudioPlayer.java:95)
... the stack trace ...
at java.base/java.lang.Thread.run(Thread.java:833)
I've of course googled the error, and found out that errors like this can be caused by playing a sound file whose type is not supported by Clip (that's also what the error is telling me). However, in this case, clip fails when it's trying to play a sound that has already been played (so I know its type is supported). Might this be due to the fact that I'm playing too many sounds (some of which last only 0.5s) in too short time intervals (two sounds per seconds)? What could be the cause?
I'm running my app with OpenJDK 20 on a linux (Ubuntu) Workstation, if that might help.
Thanks in advance for your help!
BTW I've tried also to cache the files that I play (to avoid opening too many files), loading them only once, and providing clip.open() with a ByteArrayInputStream, without much success.
答案1
得分: 1
clip.open
方法接受一个AudioInputStream
参数,然而在您的playSound
方法中,您提供了一个BufferedInputStream
,请改为使用AudioSystem.getAudioInputStream
方法(该方法可以接受文件、InputStream、URL等其他有用的类型),替代您的BufferedInputStream
。
AudioSystem.getAudioInputStream文档
以下是一些可工作代码的示例:
public static void playSound(String path) {
logger.info("Playing " + path);
try {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File(path)));
clip.start();
} catch(LineUnavailableException | UnsupportedAudioFileException | IOException e) {
System.err.println("error while playing " + path);
e.printStackTrace();
}
}
另外,我知道您考虑使用ByteArrayInputStream
来缓存文件,但这仍然引入了每次播放声音时创建新的Clip
的开销。相反,我建议为每个声音初始化一个Clip
对象,并将其传递到playSound
方法中,然后您可以调用clip.setFramePosition(0)
和clip.start()
来重置并再次播放声音。
英文:
The clip.open
method takes in an argument of AudioInputStream
, however in your playSound
method you supply it a BufferedInputStream
, instead use the AudioSystem.getAudioInputStream
method (which can take in File, InputStream, URL, and other useful types), in place of your BufferedInputStream
.
AudioSystem.getAudioInputStream Documentation
Here's an example of some working code:
public static void playSound(String path) {
logger.info("Playing " + path);
try {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File(path)));
clip.start();
} catch(LineUnavailableException | UnsupportedAudioFileException | IOException e) {
System.err.println("error while playing " + path);
e.printStackTrace();
}
}
Also, I know you considered caching the files by using a ByteArrayInputStream
, however that still introduces the overhead of creating a new Clip
each time you play the sound. Instead I'd recommend initializing a Clip
object for every sound you have and passing that into the playSound
method, you can then call clip.setFramePosition(0)
and clip.start()
to reset and play the sound again.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论