笔记本电脑退出休眠状态后,Java MIDI音频会延迟

Dav*_*ood 12 java audio midi jvm gervill

我正在开发一种音乐编程语言,并使用JVM(通过Clojure)来播放用这种语言编写的乐谱.到目前为止,我们只是使用javax.sound.midi MidiSynthesizer来播放分数.

由于Clojure启动时间较慢,我们希望能够从命令行中获得分数并立即听到,我们选择将分数解释器构建为后台服务器进程,并使用更轻量级的方式与之通信用Java编写的命令行客户端.

所有这一切在大多数情况下都很有效,但是,有一个奇怪的问题,我们看到你在哪里启动服务器,然后关闭你的笔记本电脑*让它休眠,然后再打开它让服务器播放一个得分,音频不会立即发生,但会延迟几秒钟.使用调试日志记录运行服务器,我实际上可以看到MIDI音符开/关事件立即发生(并且正确定时),但音频被延迟.

*这可能是也可能不是特定于平台的.我在运行OS X 10.9.5 Mavericks的2014 Macbook Pro上看到了这个问题.

为了帮助缩小范围,我将这个简单的例子(使用Java,而不是Clojure)放在一起,演示了这个问题:

https://github.com/daveyarwood/java-midi-delayed-audio-example

我已经在这一段时间里摸不着头脑了.为什么音频会延迟,我们能做些什么呢?

apa*_*gin 4

这看起来像是 Sun 的 Synthesizer 实现中的一个错误。

我没有深入调查这一点,但我发现问题显然出在包装AudioInputStream. 抖动校正器线程依赖于System.nanoTime(). 但是,nanoTime当计算机从待机或休眠模式唤醒时,可能会发生跳转。

解决方法是禁用抖动校正器。您可以通过以下方式打开合成器来做到这一点:

    synth = MidiSystem.getSynthesizer();

    if (synth instanceof com.sun.media.sound.SoftSynthesizer) {
        Map<String, Object> params = Collections.singletonMap("jitter correction", false);
        ((com.sun.media.sound.SoftSynthesizer) synth).open(null, params);
    } else {
       synth.open();
    }
Run Code Online (Sandbox Code Playgroud)