我编写了一个applet,它从服务器传输声音数据并通过客户端的计算机播放。我让客户端掌握扬声器线路,具有以下功能:
private SourceDataLine getSourceDataLine() {
try {
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
for (Mixer.Info mi : AudioSystem.getMixerInfo()) {
SourceDataLine dataline = null;
try {
Mixer mixer = AudioSystem.getMixer(mi);
dataline = (SourceDataLine)mixer.getLine(info);
dataline.open(format);
dataline.start();
return dataline;
}
catch (Exception e) {
e.printstacktrace();
}
if (dataline != null)
try {
dataline.close();
}
catch (Exception e) {
e.printstacktrace();
}
}
}
catch (Exception e) {
e.printstacktrace();
}
return null;
}
打开网页后几乎立即调用此函数,第一次打开页面时效果很好。但是,如果刷新页面,其他所有内容在重新启动时都能正常工作,但会丢失声音。这是因为原始applet在创建新applet时并未完全关闭,因此当新applet尝试获取原始applet时,原始SourceDataLine仍在使用中。它仍然设法找到一个,但它不是真正连接到扬声器的那个。
我想一个解决方案是在尝试获取SourceDataLine之前总是让函数等待一段时间,但这似乎并不特别优雅,我希望程序能够快速获取正确的dataLine尽可能。
那么,有没有人有关于我如何做到这一点的任何提示,或者我几乎被卡住了?
- 编辑 -
我添加了一些堆栈跟踪(根据安德鲁的建议),这是我得到的:
javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian not supported.
at javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian not supported.
at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:494)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:107)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:139)
at view.PlaybackThread.getSourceDataLine(PlaybackThread.java:120)
at view.PlaybackThread.loadSoundData(PlaybackThread.java:99)
at view.PlaybackThread.<init>(PlaybackThread.java:33)
at model.GUIModule.<init>(GUIModule.java:77)
at model.GUIMainApplet.createAndShowGUI(GUIMainApplet.java:24)
at model.GUIMainApplet.access$0(GUIMainApplet.java:22)
at model.GUIMainApplet$1.run(GUIMainApplet.java:17)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:642)
at java.awt.EventQueue.access$000(EventQueue.java:85)
at java.awt.EventQueue$1.run(EventQueue.java:603)
at java.awt.EventQueue$1.run(EventQueue.java:601)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:612)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
我认为那个转储的第6行是我们想要开始寻找的地方。