SourceDataLine.drain()在OSX上挂起
我的游戏通过常用方法播放声音:
sdl.open(); sdl.start(); sdl.write(data, 0, data.length); sdl.drain(); sdl.stop(); sdl.close();
用户可以取消播放(异步):
sdl.stop();
这种取消在Windows下运行良好,但是对于一个运行带有Java 6的OSX 10.5.8的用户,程序会挂起。 Threaddump显示回放线程在drain()中: com.sun.media.sound.MixerSourceLine.nDrain
。 如果用户没有中断声音,它会很好地完成并继续应用程序。
我的问题是:
- 这是OSX Java的错误吗?
- 我应该使用
sdl.close()
而不是停止吗? - 有关变通方法的任何建议或经验吗?
编辑 :我发现此错误报告具有类似的效果,但页面说它已修复。
作为参考,这个使用close()
例子通常在Java 5或6下退出。
除非在初始线程上已经正常关闭了line
,否则在EDT上调用stop()
而不是close()
挂起Java 5和6。 这似乎是drain()
阻塞的预期结果,因为停止的线不能消耗。
import java.awt.EventQueue; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.SourceDataLine; import javax.swing.JOptionPane; /** * @see https://stackoverflow.com/questions/7803310 * @see https://stackoverflow.com/questions/2065693 */ public class Tone { public static void main(String[] args) throws LineUnavailableException { final AudioFormat af = new AudioFormat(Note.SAMPLE_RATE, 8, 1, true, true); final SourceDataLine line = AudioSystem.getSourceDataLine(af); EventQueue.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(null, "Halt"); //line.stop(); // stops and hangs on drain line.close(); } }); line.open(af, Note.SAMPLE_RATE); line.start(); for (Note n : Note.values()) { play(line, n, 500); play(line, Note.REST, 10); } line.drain(); line.close(); } private static void play(SourceDataLine line, Note note, int ms) { ms = Math.min(ms, Note.SECONDS * 1000); int length = Note.SAMPLE_RATE * ms / 1000; int count = line.write(note.data(), 0, length); } }
需要Note
。