SourceDataLine.drain()在OSX上挂起

时间:2011-10-18 06:33:05

标签: java macos javasound

我的游戏通过常用方法播放声音:

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()代替停止吗?
  • 有关解决方法的任何建议或经验吗?

修改:我发现this错误报告具有类似效果,但页面显示已修复。

1 个答案:

答案 0 :(得分:1)

作为参考,这个使用close()的示例通常在Java 5或6下退出。

在EDT上调用stop()而不是close()会挂起Java 5和6,除非line已在初始线程上正常关闭。这似乎是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