javax.sound.sampled.Clip在Java中一段时间后停止工作

huangapple go评论102阅读模式
英文:

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

Clip.open文档

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.

Clip.open Documentation

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.

huangapple
  • 本文由 发表于 2023年6月19日 03:50:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502297.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定