るいもの戯れ言

rust-jackのサンプルを見ると、


        put_p.write(&RawMidi {
                time: 0,
                bytes: &[0b10010000 /* Note On, channel 1 */,
                         0b01000000 /* Key number */, 0b01111111 /* Velocity */],
            })
            .unwrap();
        put_p.write(&RawMidi {
                time: ps.n_frames() / 2,
                bytes: &[0b10000000 /* Note Off, channel 1 */,
                         0b01000000 /* Key number */, 0b01111111 /* Velocity */],
            })
            .unwrap();

RawMidiの第一パラメータに時間情報が指定されているので、ここを色々変更して試してみた。すると、どうも大きな値を指定するとプログラムが異常終了する。


thread '' panicked at 'called `Result::unwrap()` on an `Err` value: UnknownError', ../src/libcore/result.rs:799
stack backtrace:
Jack: JackClient::ClientNotify ref = 4 name = rust_jack_show_midi notify = 3
Jack: JackClient::kXRunCallback
   1:     0x556f8a7d8a0f - std::sys::backtrace::tracing::imp::write::h6f1d53a70916b90d
   2:     0x556f8a7db50d - std::panicking::default_hook::{{closure}}::h137e876f7d3b5850
   3:     0x556f8a7daa1a - std::panicking::default_hook::h0ac3811ec7cee78c
   4:     0x556f8a7dafb8 - std::panicking::rust_panic_with_hook::hc303199e04562edf
   5:     0x556f8a7dae52 - std::panicking::begin_panic::h6ed03353807cf54d
   6:     0x556f8a7dad90 - std::panicking::begin_panic_fmt::hc321cece241bb2f5
   7:     0x556f8a7dad11 - rust_begin_unwind
   8:     0x556f8a80ffef - core::panicking::panic_fmt::h27224b181f9f037f
   9:     0x556f8a7cadf2 - core::result::unwrap_failed::hf4a2bbe780b35bc4
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libcore/macros.rs:29
  10:     0x556f8a7c8ad0 - >::unwrap::h089470f17859500e
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libcore/result.rs:737
  11:     0x556f8a7ce894 - sample::main::{{closure}}::hf2f3cb9afdb66a80
                        at /home/shanai/rust/midi-sample/src/main.rs:34
  12:     0x556f8a7cd12f - ::process::h4cdfe5f6478477da
                        at /home/shanai/.cargo/registry/src/github.com-1ecc6299db9ec823/jack-0.2.2/src/callbacks.rs:181
  13:     0x556f8a7ccef2 - jack::callbacks::process::h6e653a5eccae8773
                        at /home/shanai/.cargo/registry/src/github.com-1ecc6299db9ec823/jack-0.2.2/src/callbacks.rs:215
  14:     0x7f379543fc1d - 
  15:     0x7f379543f057 - 
  16:     0x7f379545767f - 
  17:     0x7f37950136b9 - start_thread
  18:     0x7f3794b3382c - clone
  19:                0x0 - 
fatal runtime error: failed to initiate panic, error 5

二分法で限界を探してみると、1023までなら大丈夫で、1024以上だとエラーになる。Jackのサイトにプログラミング・モデル的な解説が無いので理解に時間がかかったが、どうやらこういうことらしい。

この設定で指定したフレーム/ピリオドに指定した値が限界らしい。rust-jackではコールバックを登録するが、このコールバックは、ここで指定したフレーム/ピリオドで指定された間隔で呼ばれ、コールバック内では1フレーム内の動作のみを指定可能なようだ。なので、時間指定にはこのフレーム/ピリオドの値未満しか指定できない。で、この値の単位なのだが、1/サンプルレート 秒になる。つまり、この例であれば1/44100秒。なので、1フレームは1024/44100秒になる。分解能は1/44100秒なので、仮にテンポ=600(1分で四分音符600回演奏、つまり1秒に四分音符10回演奏)を上限とすると、四分音符の分解能は4410となる。MIDIシーケンサとしては十分な値だろう。

最後にピリオド/バッファーだが、ここで指定した個数のフレーム用バッファーが用意されるようだ。ここの値が大きければ事前にデータを準備しておけるので、コールバックでの処理が少々遅延したとしても途切れずに再生できるが、先にデータを用意しておかないといけないので、レイテンシーが増大する。この画面の右下にあるレイテンシーがそれを表しているようだ(1024 * 3 * 1/44100 = 0.0696598639)。