Java的Clip类中的Drain方法

mat*_*ieu 5 java

我正在创建一个短片然后播放它,调用该start()方法.然后我调用该drain()方法来阻止执行,直到剪辑回放完成.但是,当运行多次下面的代码时,有时它会工作,有时它不会,并且声音在结束前随机停止.

Mixer mixer = AudioSystem.getMixer(null);
AudioFormat format = new AudioFormat(44100, 8, 1, true, false);
DataLine.Info info = new DataLine.Info(Clip.class, format);
try {
    // Create a sound of 1 second
    Clip clip = (Clip)mixer.getLine(info);
    byte[] b = new byte[44100];
    for(int i=0; i<b.length; i++)
        b[i] = (byte) (50*Math.sin(i/10.0));

    clip.open(format, b, 0, b.length);
    clip.setFramePosition(0);
    clip.start();
    clip.drain();
} catch(LineUnavailableException lue) { lue.printStackTrace(); }
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:这是一个错误吗?还是我误解了这个drain()方法?

Dan*_*ári 0

看来clip.start()有时会在Start事件发生之前立即返回,这是由于错误(?)造成的,在这种情况下,drain没有效果。通过解决方法,我们可以使用 Listener 来捕获 START 事件:

解决办法:

Mixer mixer = AudioSystem.getMixer(null);
AudioFormat format = new AudioFormat(44100, 8, 1, true, false);
DataLine.Info info = new DataLine.Info(Clip.class, format);
try {
    // Create a sound of 1 second
    Clip clip = (Clip)mixer.getLine(info);

    //Workaround part 1
    clip.addLineListener(new LineListener() {
        @Override
        public void update(LineEvent event) {
            if (event.getType() == Type.START)
                synchronized (clip) {
                    clip.notify();
                }
        }
    });

    byte[] b = new byte[44100];
    for(int i=0; i<b.length; i++)
        b[i] = (byte) (50*Math.sin(i/10.0));

    clip.open(format, b, 0, b.length);
    clip.setFramePosition(0);

    //Workaround part 2
    synchronized (clip) {
        clip.start();
        clip.wait();
        System.out.println("Started");
    }
    clip.drain();
    System.out.println("Drained");
} catch(LineUnavailableException | InterruptedException lue) { lue.printStackTrace(); }
Run Code Online (Sandbox Code Playgroud)