在Java中播放wav文件出现问题

10
我正在尝试播放一个
PCM_UNSIGNED 11025.0 Hz, 8 bit, mono, 1 bytes/frame

这里(1)这里(2)所描述的那样。

第一种方法可行,但我不想依赖于sun.*。第二种方法只播放了一些前导帧,听起来更像是一个点击声。这不可能是IO问题,因为我是从一个ByteArrayInputStream中播放的。

可能是什么原因导致这种情况发生?

1个回答

32

我不确定为什么你提供的第二种方法要开启另一个线程;我相信音频将会在它自己的线程中播放。问题是你的应用程序在剪辑完成播放之前就结束了吗?

import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.LineEvent.Type;

private static void playClip(File clipFile) throws IOException, 
  UnsupportedAudioFileException, LineUnavailableException, InterruptedException {
  class AudioListener implements LineListener {
    private boolean done = false;
    @Override public synchronized void update(LineEvent event) {
      Type eventType = event.getType();
      if (eventType == Type.STOP || eventType == Type.CLOSE) {
        done = true;
        notifyAll();
      }
    }
    public synchronized void waitUntilDone() throws InterruptedException {
      while (!done) { wait(); }
    }
  }
  AudioListener listener = new AudioListener();
  AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(clipFile);
  try {
    Clip clip = AudioSystem.getClip();
    clip.addLineListener(listener);
    clip.open(audioInputStream);
    try {
      clip.start();
      listener.waitUntilDone();
    } finally {
      clip.close();
    }
  } finally {
    audioInputStream.close();
  }
}

实际上我没有在单独的线程中运行它,只是为了简洁起见链接了它。非常感谢! - yanchenko
@Jataro - 你说得对;我在API中漏掉了那个调用;我会更新代码。 - McDowell
根据http://download.oracle.com/javase/tutorial/sound/playing.html,drain()似乎不适用于Clips。 - lucks
1
@lucks - 谢谢!我已经纠正了代码。从文档中得知:一旦您开始播放声音,如何找到它何时完成?我们在上面看到了一个解决方案——在写入最后一个数据缓冲区后调用drain方法,但这种方法仅适用于SourceDataLine。另一种适用于SourceDataLines和Clips的方法是注册以接收来自线路的通知,每当线路更改其状态时就会生成这些通知,这些通知以LineEvent对象的形式生成,其中有四种类型:OPEN、CLOSE、START和STOP。 - McDowell
看起来你必须在它自己的线程中播放,这个线程直到文件结束才会终止?(即,如果应用程序的主线程退出,程序将退出,不像大多数Java线程化应用程序)。 - rogerdpack
感谢提供示例代码。当我尝试相同的代码时,我没有听到Wav文件的声音,程序只是等待而已。我正在尝试在我的Windows TP上运行该程序。是否需要选择某些设置或播放器?请给予建议。 - Sathish

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接