【问题标题】:What is the correct way to play a sound file using java.sound.sampled.Clip使用 java.sound.sampled.Clip 播放声音文件的正确方法是什么
【发布时间】:2020-08-12 08:51:47
【问题描述】:

我已经阅读了很多关于这个主题的 SoF 主题和其他网站,但没有一个适合我,所以我再次询问,希望得到量身定制的答案。

我的 jar 中有一个 .WAV 文件我想播放,但我得到了NullPointerException. 我尝试了很多方法,甚至通过绝对路径在 jar 外播放文件,但我得到了相同的结果。 这是播放声音的函数

public void gimli(){
        try {
            Clip clip;
             AudioInputStream  stream = AudioSystem.getAudioInputStream(this.getClass().getResource(Utils.class.getResourceAsStream("gimlilaught.wav").toString()));
   AudioFormat format = stream.getFormat();
    DataLine.Info info = new DataLine.Info(Clip.class, format);
  clip = (Clip)AudioSystem.getLine(info);
    clip.open(stream);
    clip.start();
}catch(Exception ex){
ex.printStackTrace(System.out);
}

感谢您的尝试。

【问题讨论】:

    标签: java file audio jar nullpointerexception


    【解决方案1】:

    我昨晚尝试了这个,似乎对我有用的是:

    try {
                File filePath = new File(audioLocation);
    
                if (filePath.exists()) {
                    AudioInputStream audioInput = AudioSystem.getAudioInputStream(filePath);
                    Clip clip = AudioSystem.getClip();
                    clip.open(audioInput);
                    FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                    gainControl.setValue(getVolume());
                    clip.loop(Clip.LOOP_CONTINUOUSLY);
                    clip.start();
                } else {
                    System.out.println("Incorrect audio file path!");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    

    虽然我认为我应该在某个地方有 clip.open(),并且我在停止和启动另一个类的音频时遇到了问题,但这确实可以播放声音。

    【讨论】:

    • 感谢您的回复。您的文件路径如何?
    • @BlackDragon 我实际上是从这个系统更改为摆脱 File filePath = new File(audioLocation);完全。我现在使用 URL 作为路径,如果有意义就直接使用它。这样,当您编译为可运行的 Jar 时,音频实际上会播放。我刚刚创建了一个名为 res 的 并将其放入 ("/res/audio.wav")
    • 谢谢,这正是我的音频所在。我试试看。
    【解决方案2】:

    需要AudioInputStream 作为打开Clip 的参数。查看 API,您将看到 AudioSystem.getAudioInputStream(InputStream)AudioSystem.getAudioInputStream(URL) 可用于获取 AudioInputStream

    Class 有两种服务方法:getResource(String)getResourceAsStream(String)getResource 方法将返回一个URLgetResourceAsStream 方法将返回一个InputStream

    我更喜欢使用 URL 形式,因为它更宽容。使用AudioSystem.getAudioInputStream(InputStream)时,如果文件不支持标记重置,将返回IOExceptionAudioSystem.getAudioInputStream(URL) 方法绕过了这个要求。

    另外,您应该知道URLFile 不同,可用于标识 jar 中的文件。

    您还必须小心设置相对地址。我通常喜欢有一个 /res 文件或 /audio 文件来保存要加载的 .wav。例如,如果 /res 是并行文件夹,您可以使用“../res/myAudio.wav”或“res/myAudio.wav” >" 如果 /res 是子文件夹,相对于在 getResource 方法中使用的类的位置。

    这是一个简单的工作示例,其中音频文件位于子文件夹 /res

    private static void loadAndPlayClip() throws UnsupportedAudioFileException, 
            IOException, LineUnavailableException, InterruptedException
    {
        String filename = "a3.wav";
        URL url = BasicClipExample.class.getResource("res/" + filename);
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
        Clip clip = (Clip) AudioSystem.getLine(info);
        clip.open(ais);
    
        clip.start();
        Thread.sleep(7000); // Duration should match length of audio file.
        clip.close();
    }
    

    虽然这个例子应该可以工作,但它不应该在生产中按原样使用,原因有两个。

    1. Thread.sleep() 命令会暂停主线程,这通常既不需要也不需要。系统为Clip 回放创建的线程是daemon 线程。 守护进程 线程不会阻止程序完成和关闭。在这个简单的“即发即弃”示例中,主线程很快就完成了,因此如果我们不通过睡眠间隔来阻止完成,程序将立即关闭。

    2. Clip 的初始加载和Clip 的播放通常以两种不同的方法完成。 Clip 专为可以方便地保存在内存中的音频而设计,无需重新加载即可重播。如果您在每个播放命令中重新加载 Clip,您将重做不需要的工作并增加延迟,因为剪辑在完全加载之前不会开始播放。如果音频文件不方便在内存中保存(例如,由于持续时间长而导致文件较大),首选方法是使用SourceDataLine 播放。

    【讨论】:

    • 代码在我得到 NullPoiterException 之前一直有效,但看起来错误就在我这边。感谢您的回答,我会更深入地研究它。
    • NPE 是哪一行?
    • 好的,我终于知道了java.lang.IllegalArgumentException: No line matching interface Clip supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian is supported. 这到底是什么意思?
    • npe 在这条线上Clip clip = (Clip) AudioSystem.getLine(info); 但我认为现在已经解决了,我有第二件事,no line matching interface Clip supporting...
    • 很好奇。您描述的格式(44100 fps、16 位、立体声、签名 PCM、little-endian)是一种超级通用的标准,通常被描述为“CD 质量”。您的系统不支持这一点毫无意义。如果您运行 AudioSystem.getAudioFileTypes(),您的操作系统是否支持 .WAV?从您显示的代码中,您应该使用默认的混音器。您可能会检查系统上有哪些混音器,以获取线索。本教程有背景,下一个系列展示如何查询。 docs.oracle.com/javase/tutorial/sound/sampled-overview.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多