【问题标题】:Audio file plays in Eclipse IDE; but NOT as JAR file音频文件在 Eclipse IDE 中播放;但不是作为 JAR 文件
【发布时间】:2015-07-05 08:43:28
【问题描述】:

我使用的音频文件在这里:http://www.orangefreesounds.com/loud-alarm-clock-sound/

这是我在 Eclipse IDE 中的文件结构:

当我在 IDE 中运行音频文件时,它播放得非常好,但当我将它导出为 JAR 文件时就不行了。我已经检查并发现音频文件在 JAR 文件中。

我正在使用终端命令java -jar Sandbox.jar & 来运行JAR 文件。该程序似乎能够找到该文件(因为它没有抛出 IOException),但似乎无法执行播放。

为什么会出现这个问题,我该如何解决?

奇怪的更新

好的,实际上,JAR 文件在 Windows 8.1 上的 cmdPowerShell 中运行时能够播放音频文件,但由于某种原因不能在 Ubuntu 14.04 的终端中播放。一直以来,我一直在尝试在 Ubuntu 14.04 中运行 JAR 文件。

奇怪的更新 #2

我已确认 JAR 文件仅适用于 Windows 8.1 系统的问题。这个问题中的两个代码 sn-ps 都不起作用,而 MadProgrammer 的两个解决方案都有效。

最小、完整和可验证的示例(不适用于 Windows 或 Ubuntu)

import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.*;

public class Sandbox
{

    public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
    {
        URL url = Sandbox.class.getResource("/sound-effects/alarmSoundClip.wav");
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        AudioFormat af = ais.getFormat();
        DataLine.Info info = new DataLine.Info(Clip.class, af);

        Clip clip = (Clip) AudioSystem.getLine(info);
        clip.open(ais);
        clip.start();
    }

}

尝试的解决方案 #1(不适用于 Windows 或 Ubuntu)

一个尝试的解决方案(如 Andrew Thompson 所建议的)是写 this.getClass().getResource( ... ) 而不是 Sandbox.class.getResource( ... ):

import java.io.IOException;
import java.net.URL;

import javax.sound.sampled.*;

public class Sandbox
{

    public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException
    {
        new Sandbox();
    }

    public Sandbox() throws UnsupportedAudioFileException, IOException, LineUnavailableException
    {
        URL url = this.getClass().getResource("/sound-effects/alarmSoundClip.wav");
        AudioInputStream ais = AudioSystem.getAudioInputStream(url);
        AudioFormat af = ais.getFormat();
        DataLine.Info info = new DataLine.Info(Clip.class, af);

        Clip clip = (Clip) AudioSystem.getLine(info);
        clip.open(ais);
        clip.start();
    }
}

【问题讨论】:

  • 使用某种 zip 程序并解压 jar 并确保“音效”确实存在于您期望的 jar 文件中
  • 音效文件在JAR文件里面; /sound-effects/alarmSoundClip.wav.
  • URL url = Sandbox.class.getResource("/sound-effects/alarmSoundClip.wav"); 可能得到了错误的类加载器。重新排列代码,使其可以表示为URL url = this.getCass().getResource("/sound-effects/alarmSoundClip.wav");。一种方法是将语句移动到 Sandbox 构造函数中。
  • @AndrewThompson 作为 JAR 运行时它仍然不起作用。我将编辑我的答案以包含您的解决方案。
  • clip.start 之后添加clip.drain()clip.start 不是阻塞方法,所以它会启动另一个线程,这可能会允许 JVM 在存在 main 方法后立即终止

标签: java eclipse swing audio embedded-resource


【解决方案1】:

clip.start() 之后添加clip.drain() 对我来说似乎没问题(IDE 和命令行,无论有无&

import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Sandbox {

    public static void main(String[] args)  {
        try {
            URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
            AudioInputStream ais = AudioSystem.getAudioInputStream(url);
            AudioFormat af = ais.getFormat();
            DataLine.Info info = new DataLine.Info(Clip.class, af);

            Clip clip = (Clip) AudioSystem.getLine(info);
            clip.open(ais);
            clip.start();
            System.out.println("Drain...");
            clip.drain();
            System.out.println("...Drained");
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException exp) {
            exp.printStackTrace();
        }
    }

}

话虽如此,过去我发现drain 有点不可靠,尤其是在播放多个声音的情况下,我倾向于使用LineListener

例如...

import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

public class Sandbox {

    protected static final Object LOCK = new Object();

    public static void main(String[] args) {
        try {
            URL url = Sandbox.class.getResource("/sound-effects/Loud-alarm-clock-sound.wav");
            AudioInputStream ais = AudioSystem.getAudioInputStream(url);
            AudioFormat af = ais.getFormat();
            DataLine.Info info = new DataLine.Info(Clip.class, af);

            Clip clip = (Clip) AudioSystem.getLine(info);
            clip.open(ais);

            clip.addLineListener(new LineListener() {
                @Override
                public void update(LineEvent event) {
                    System.out.println(event.getType());
                    if (event.getType() == LineEvent.Type.STOP) {
                        synchronized (LOCK) {
                            LOCK.notify();
                        }
                    }
                }
            });
            clip.start();

            synchronized (LOCK) {
                LOCK.wait();
            }
        } catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException exp) {
            exp.printStackTrace();
        }
    }

}

【讨论】:

  • @JohnH 使用LineListener 代替(尽管也许你可以在Clip#start 之前调用Clip#flush 来测试Clip#drain
  • 真的吗?看起来不错
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
  • 2015-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多