笔记本电脑退出 hibernate 后,Java MIDI 音频出现延迟

标签 java audio jvm midi gervill

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

因为 Clojure 的启动时间很慢,而我们希望能够从命令行播放乐谱并立即听到,我们选择将乐谱解释器构建为后台服务器进程,并使用用 Java 编写的更轻量级的命令行客户端。

所有这些在大多数情况下都运行良好,但是,有一个奇怪的问题,我们看到如果您启动服务器,然后关闭笔记本电脑*并让它 hibernate ,然后再次打开它并让服务器播放乐谱,音频不会立即出现,而是会延迟几秒钟。使用调试日志运行服务器,我实际上可以看到 MIDI 音符开/关事件立即发生(并且计时正确),但音频延迟。

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

为了帮助缩小范围,我整理了这个演示问题的简单示例(使用 Java,而不是 Clojure):

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

我已经为这个问题摸不着头脑了一段时间。为什么音频延迟,我们可以做些什么?

最佳答案

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

我没有对此进行深入调查,但我发现问题显然出在包装 AudioInputStream 的 Jitter Corrector 中。抖动校正器线程依赖于 System.nanoTime()。但是,当计算机从待机或 hibernate 模式唤醒时,nanoTime 可能会跳转。

解决方法是禁用抖动校正器。您可以通过以下方式打开 Synthesizer:

    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();
    }

关于笔记本电脑退出 hibernate 后,Java MIDI 音频出现延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38944107/

相关文章:

security - 如何构建一个安全的(受限生态系统)基于插件的架构(在 Kotlin 中)

java - 为什么我的 ORDS servlet 没有执行,即使我已经遵循了现有的指南?

java - 如何手动解密 EncryptedAssertion

java - 获取 java bean 属性名称的列表/数组,按照它们在源文件中出现的顺序排列

java - Java设置麦克风电平

c++ - 在 pcm 上降低音量后出现奇怪的噪音

audio - Julia 中用于音频处理的实时 STFT 和 ISTFT

java - 如何修复 java.lang.UnsupportedClassVersionError : Unsupported major. 次要版本

java - 创建简单类文件时方法签名的常量池索引非法

java - 如何永久增加java堆内存?