使用Stackoverflow的javasound标签示例播放音频

在今天早些时候阅读javasound标签时,我试图实现我们可以在那里看到的简单代码(进行一些小修改,例如使用File而不是URL ):

 File file = new File(System.getProperty("user.dir") + "/sound.wav"); Clip clip = AudioSystem.getClip(); AudioInputStream ais = AudioSystem.getAudioInputStream(file); clip.open(ais); // exception 

但是我得到了一个java.lang.IllegalArgumentException: Invalid format当我尝试打开我们在那里看到的AudioInputStreamjava.lang.IllegalArgumentException: Invalid format

但是,当我尝试使用以下来自互联网的代码时

 File file = new File(System.getProperty("user.dir") + "/sound.wav"); AudioInputStream ais = AudioSystem.getAudioInputStream(file); AudioFormat format = ais.getFormat(); DataLine.Info info = new DataLine.Info(Clip.class, format); Clip clip = (Clip)AudioSystem.getLine(info); clip.open(ais); clip.start(); 

确实有效: sound.wav正确播放 – 然而,我觉得这对于一些应该像我们的第一个例子一样简单的东西是笨重的,在javasound标签本身给出。

通过从clip中读取文档 ,我确认当[...] the stream's audio format is not fully specified or invalid时抛出IllegalArgumentException 。 但是,它似乎确实是一种有效的格式。

我们的第一个例子在这里出了什么问题? AudioSystem.getAudioInputStream()确实接受File作为参数,并且,从第二个示例可见,它看起来确实具有有效的音频文件数据,因为它可以工作。 我错过了一些明显的东西吗 而且,如果是这样,不应该在javasound标签上指出?

经过一些研究,我发现它可能与系统属性有关。 在这些属性中,您可以指定getLine()方法的默认值(getLine(),getClip(),getSourceDataLine()和getTargetDataLine())。 如果您调用其中一种方法,Java会执行以下操作( AudioSystem说明 ):

系统属性javax.sound.sampled.Clip设置为

javax.sound.sampled.Clip = great.Mixer#great.clip.Clap

Mixer类称为great.Mixer ,Clip称为great.clip.Clap

当您请求Clip时,Java会检查以下内容:

  • 如果找到混音器great.Mixer并包含Clip great.clip.Clap ,则返回此Clip
  • 如果找到混音器great.Mixer ,但不包含剪辑great.clip.Clap ,则返回混音器中指定的第一个剪辑
  • 如果混音器great.Mixer不包含任何剪辑或找不到它, 在任何混音器中返回great.clip.Clap的第一个实例
  • 如果没有Mixer包含great.clip.Clap ,则返回找到的第一个Mixer的第一个Clip
  • 如果在任何混音器中未指定Clip,则抛出IllegalArgumentException

这意味着如果您收到IllegalArgumentException,则不会在任何调音台中安装剪辑。

 DataLine.Info info = new DataLine.Info(Clip.class, format); 

你正在定义一个新的Clip。 这意味着您对getLine()方法的下一次调用将返回此对象,而不是给您一个错误。