13

私は音楽プログラミング言語を開発しており、JVM (Clojure 経由) を使用して、この言語で書かれた楽譜を再生しています。これまでのところ、javax.sound.midi MidiSynthesizer を使用してスコアを再生しているだけです。

Clojure の起動時間は遅く、コマンドラインからスコアを再生してすぐに聞きたいので、スコア インタープリターをバックグラウンド サーバー プロセスとして構築し、より軽量なプロセスを使用して通信することを選択しました。 Java で記述されたコマンドライン クライアント。

これらすべてはほとんどの場合うまく機能していますが、サーバーを起動し、ラップトップを閉じて*休止状態にし、再度開いてサーバーで再生すると、奇妙な問題が発生します。スコア、オーディオはすぐには発生しませんが、数秒間遅れます。デバッグ ロギングを使用してサーバーを実行すると、実際に MIDI ノートのオン/オフ イベントがすぐに (そして正確なタイミングで) 発生していることがわかりますが、オーディオは遅れています。

*これは、プラットフォーム固有の場合とそうでない場合があります。OS X 10.9.5 Mavericks を実行している 2014 Macbook Pro でこの問題が発生しています。

絞り込むために、問題を示す簡単な例 (Clojure ではなく Java を使用) をまとめました。

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

私はしばらくの間、これについて頭を悩ませてきました。音声が遅延するのはなぜですか? 何かできることはありますか?

4

2 に答える 2

4

これは、Sun の Synthesizer 実装のバグのようです。

私はこれを深く調査しませんでしたが、明らかに問題はラップする Jitter Corrector にあることがわかりましたAudioInputStream。Jitter Corrector スレッドは に依存していSystem.nanoTime()ます。ただしnanoTime、コンピューターがスタンバイ モードまたは休止状態から復帰したときにジャンプすることがあります。

回避策は、Jitter Corrector を無効にすることです。これを行うには、次の方法でシンセサイザーを開きます。

    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();
    }
于 2016-08-15T02:09:58.720 に答える
0

@apangin の解決策に加えて、他に 2 つの回避策を見つけました。

  • 各再生の前に、同じ Synthesizer インスタンスを閉じてから再度開きます。

  • 再生ごとに新しい Synthesizer インスタンスを使用します。

シンセサイザー インスタンスを開くのに数秒かかるため (以前に開いていた既存のインスタンスであっても)、どちらも理想的ではありませんが、ユース ケースによってはこれらの回避策で十分な場合があります。

于 2017-02-19T17:16:44.120 に答える