[英]Java MIDI audio is delayed after laptop comes out of hibernation
我正在開發一種音樂編程語言 ,並使用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
我已經在這一段時間里摸不着頭腦了。 為什么音頻會延遲,我們能做些什么呢?
這看起來像是Sun的Synthesizer實現中的一個錯誤。
我沒有深入研究,但我發現問題顯然是在包含AudioInputStream
Jitter Corrector中。 抖動校正器線程依賴於System.nanoTime()
。 但是,當計算機從待機或休眠模式喚醒時, 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();
}
除了@ apangin的解決方案,我還找到了另外兩個解決方法:
在每次播放之前,關閉並重新打開相同的Synthesizer實例。
每次播放都使用新的Synthesizer實例。
這些都不是理想的,因為打開合成器實例需要幾秒鍾(即使它是以前打開的現有實例),但這些解決方法可能足以滿足某些用例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.