使用 java.sound.sampled.Clip 播放声音文件的正确方法是什么
What is the correct way to play a sound file using java.sound.sampled.Clip
我已经阅读了很多关于此主题的 SoF 线程和其他网站,但其中 none 对我有用,所以我再次提问,希望得到量身定制的答案。
我的罐子里有一个 .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);
}
感谢您的尝试。
我昨晚正在尝试这个,似乎对我有用的是:
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() 并且我在停止和从另一个 class 启动音频时遇到问题,但它确实可以播放声音。
需要一个 AudioInputStream
作为打开 Clip
的参数。查看 API,您会看到 AudioSystem.getAudioInputStream(InputStream) or AudioSystem.getAudioInputStream(URL) 中的任一个都可用于获取 AudioInputStream。
Class
有两种服务方式:getResource(String)
或getResourceAsStream(String)
。 getResource 方法将 return 一个 URL
。 getResourceAsStream 方法将 return 一个 InputStream
.
我更喜欢使用 URL 形式,因为它更宽容。使用 AudioSystem.getAudioInputStream(InputStream) 时,如果文件不支持 标记 [=68],则 IOException
将被 returned =] 和 重置 。方法AudioSystem.getAudioInputStream(URL)规避了这个要求。
此外,您应该知道 URL
与 File
不同,可用于识别 jar 中的文件。
你也必须小心设置相对地址。我通常喜欢有一个 /res 文件或 /audio 文件来保存要加载的 .wav。例如,如果 /res 是并行文件夹或“res/myAudio.wav" 如果 /res 是子文件夹,相对于 中使用的 class 的位置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();
}
虽然这个例子应该有效,但它不应该按原样用于生产,原因有二。
Thread.sleep()
命令会暂停主线程,这通常是不需要也不需要的。系统为 Clip
回放创建的线程是 daemon 线程。 守护进程 线程不会阻止程序完成和关闭。在这个简单的 "fire and forget" 示例中,主线程很快完成,因此如果我们不通过休眠间隔来延缓完成,程序将立即关闭。
Clip
的初始加载和 Clip
的播放通常以两种不同的方法完成。 Clip
专为可以方便地保存在内存中的音频而设计,无需重新加载即可重播。如果您使用每个播放命令重新加载 Clip
,您将同时重做不需要的工作并增加延迟,因为剪辑在完全加载之前不会开始播放。如果音频文件不方便保存在内存中(例如,由于持续时间长而导致的大文件),首选方法是使用 SourceDataLine
.
播放它
我已经阅读了很多关于此主题的 SoF 线程和其他网站,但其中 none 对我有用,所以我再次提问,希望得到量身定制的答案。
我的罐子里有一个 .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);
}
感谢您的尝试。
我昨晚正在尝试这个,似乎对我有用的是:
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() 并且我在停止和从另一个 class 启动音频时遇到问题,但它确实可以播放声音。
需要一个 AudioInputStream
作为打开 Clip
的参数。查看 API,您会看到 AudioSystem.getAudioInputStream(InputStream) or AudioSystem.getAudioInputStream(URL) 中的任一个都可用于获取 AudioInputStream。
Class
有两种服务方式:getResource(String)
或getResourceAsStream(String)
。 getResource 方法将 return 一个 URL
。 getResourceAsStream 方法将 return 一个 InputStream
.
我更喜欢使用 URL 形式,因为它更宽容。使用 AudioSystem.getAudioInputStream(InputStream) 时,如果文件不支持 标记 [=68],则 IOException
将被 returned =] 和 重置 。方法AudioSystem.getAudioInputStream(URL)规避了这个要求。
此外,您应该知道 URL
与 File
不同,可用于识别 jar 中的文件。
你也必须小心设置相对地址。我通常喜欢有一个 /res 文件或 /audio 文件来保存要加载的 .wav。例如,如果 /res 是并行文件夹或“res/myAudio.wav" 如果 /res 是子文件夹,相对于 中使用的 class 的位置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();
}
虽然这个例子应该有效,但它不应该按原样用于生产,原因有二。
Thread.sleep()
命令会暂停主线程,这通常是不需要也不需要的。系统为Clip
回放创建的线程是 daemon 线程。 守护进程 线程不会阻止程序完成和关闭。在这个简单的 "fire and forget" 示例中,主线程很快完成,因此如果我们不通过休眠间隔来延缓完成,程序将立即关闭。Clip
的初始加载和Clip
的播放通常以两种不同的方法完成。Clip
专为可以方便地保存在内存中的音频而设计,无需重新加载即可重播。如果您使用每个播放命令重新加载Clip
,您将同时重做不需要的工作并增加延迟,因为剪辑在完全加载之前不会开始播放。如果音频文件不方便保存在内存中(例如,由于持续时间长而导致的大文件),首选方法是使用SourceDataLine
. 播放它