我一直在尝试让Java播放一些简单的wav文件,但是一直没有成功。我尝试了以下代码:
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(soundBytes));
clip.open(inputStream);
clip.start();
这在“clip.open(...)”时失败,并出现异常:
javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
我曾尝试过更复杂的(流媒体版本):
int BUFFER_SIZE = 128000;
AudioInputStream audioStream = null;
AudioFormat audioFormat;
SourceDataLine sourceLine = null;
try {
audioStream = AudioSystem.getAudioInputStream(new ByteArrayInputStream(soundBytes));
} catch (Exception e){
e.printStackTrace();
}
audioFormat = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
try {
sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open(audioFormat);
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
sourceLine.start();
int nBytesRead = 0;
byte[] abData = new byte[BUFFER_SIZE];
while (nBytesRead != -1) {
try {
nBytesRead = audioStream.read(abData, 0, abData.length);
} catch (IOException e) {
e.printStackTrace();
}
if (nBytesRead >= 0) {
@SuppressWarnings("unused")
int nBytesWritten = sourceLine.write(abData, 0, nBytesRead);
}
}
sourceLine.drain();
sourceLine.close();
这也会在执行"sourceLine.open(...)"时失败并抛出异常:
javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian not supported.
我尝试了两个不同的wav文件,包括C:\Windows\Media中的著名的“tada.wav”。
我还使用GoldWave将其中一个文件更改为无符号8位单声道,但这只是将错误消息更改为:
javax.sound.sampled.LineUnavailableException: line with format PCM_UNSIGNED 44100.0 Hz, 8 bit, mono, 1 bytes/frame, not supported.
您认为我可能哪里做错了吗?似乎播放一个简单的波形文件应该很简单,所以我猜我已经走错了路。
提前感谢。
更新
事情变得更加复杂了。如果我们将代码移动到独立的Java程序中,则代码可以正常工作。我们的应用程序中有些东西可能会影响Java播放声音的能力。
这是上述错误的堆栈跟踪:
javax.sound.sampled.LineUnavailableException: line with format PCM_UNSIGNED 44100.0 Hz, 8 bit, mono, 1 bytes/frame, not supported.
at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:492)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:107)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:139)
at com.hcs.orc.detail.SoundAddEdit.playButtonActionPerformed(SoundAddEdit.java:315)
at com.hcs.orc.detail.SoundAddEdit.access$100(SoundAddEdit.java:40)
at com.hcs.orc.detail.SoundAddEdit$2.actionPerformed(SoundAddEdit.java:225)
更新2:
发现更有趣的问题。看起来在加载DLL时存在冲突。我们有自己的DLL来帮助我们完成一些工作(例如查找可靠和可用的MAC地址)。如果在加载我们的DLL之前播放声音(会加载与声音相关的DLL),那么两者都可以正常工作。但是,如果先加载我们的DLL再尝试播放声音,则声音会报告以上错误。
有人了解为什么一个看似无关的DLL会导致另一个DLL后期加载不正确吗?
作为一项非常糟糕和劣质的解决方法,我们可以在启动时播放几分之一秒的静音,然后再查找MAC地址。这样做有很多弊端,包括很多客户根本不使用声音。
更新3:
深入研究我们的库,发现问题是由对RegisterClassEx(...)的调用引起的。我们这样做是为了显示一个嵌入式IE窗口,其中包含我们的HTML帮助文件。