MIDI 2.0 で受け取るように作った MIDIFabric の入力ポートで、NRPN の値が 2 回届き、1 回目だけ値が違っていました。
Core MIDI が、NRPN の値がそろう前に MIDI 2.0 へ変換していました。ここで送った MIDI 1.0 の NRPN は、パラメータを選ぶ CC 99・98 と、値の上位・下位を送る CC 6・38 の 4 メッセージです。
MIDI 2.0 で受信すると、CC 6 の時点で上位だけの値が届き、CC 38 の到着後に完全な値が届きます。MIDI 1.0 のまま受信する場合、この二段階の変換は起きません。
気づいたきっかけ
以前の版の MIDIFabric は、Core MIDI の入力ポートを MIDI 2.0 のプロトコルで作っていたことがあります。そのとき、MIDI 1.0 の NRPN が、値の下位がそろう前に一度届くことが分かり、入力ポートを MIDI 1.0 のプロトコルで作るようにしました。
その後、IAC ドライバのバスが MIDI 2.0 だと分かったので(「Mac の IAC ドライバは MIDI 2.0?」)、同じことを IAC で確かめ直しました。
観察したこと
MIDI 1.0 の NRPN を IAC のバスへ送り、MIDI 2.0 で受け取るアプリで受けました。パラメータは 1:2、値は 0x1234 です。
| 送った MIDI 1.0 | 届いた MIDI 2.0 |
|---|---|
| CC 99 = 1、CC 98 = 2 | まだ何も届かない |
| CC 6 = 0x24(上位) | Assignable Controller 1:2、値 0x48000000(上位だけの値) |
| CC 38 = 0x34(下位) | もう一度 Assignable Controller 1:2、値 0x48D00000(完全な値) |
1 回目と 2 回目で値が異なるため、単純な重複として取り除くことはできません。
以前の版の MIDIFabric で見たのと同じ挙動です。IAC だけの問題ではなく、Core MIDI がアプリのために MIDI 1.0 を MIDI 2.0 へ変換する場所で起きると考えています。
RPN と MIDI 1.0 での受信結果
- RPN では CC 101 が先に届く。 MIDI 1.0 の RPN(CC 101、100、6)は、元の CC 101 がそのまま届き、その後に変換された RPN のメッセージが届きました。
- IAC の MIDI 1.0 の受け手には、重複が届くことがある。 IAC は内部で MIDI 2.0 に変換して戻すため、IAC から MIDI 1.0 で受け取るアプリには、NRPN が CC 99、98、6、6、38 として、RPN は CC 101 が 2 回届きました。「Mac の IAC ドライバは MIDI 2.0?」も参照してください。
影響
- アプリのつまみなどが、一瞬違う値に飛んでから落ち着きます。
- 記録したオートメーションに、不完全な値の点が余分に入ります。
- MIDI ラーンやログが、不完全な値を拾ったり、1 回の変更を 2 つのメッセージとして記録したりします。
- ピッチやフィルターのカットオフのようにすぐ反応するパラメータでは、跳ねが音に出ることがあります。
最終値は正しいため、表示だけでは気づきにくい挙動です。NRPN を細かく連続して変える場合は、途中の値にも注意が必要です。
避け方
利用者の場合:
- アプリで MIDI の受け取り方を選べるなら、MIDI 1.0 で受け取れば起きません。
- 同じ Mac のアプリ間では、IAC ドライバ自体が MIDI 2.0 です。ほかがすべて MIDI 1.0 でも、IAC から MIDI 2.0 で受け取るアプリには起きます。
アプリを作る人の場合:
- 入力ポートを MIDI 1.0 のプロトコルで作り、CC 99、98、6、38 から NRPN を自分で組み立てます。値は CC 38 が届くまで(または短い時間切れまで)待ってから使います。
- MIDI 2.0 で受け取る必要がある場合は、同じパラメータの Assignable Controller がすぐに続いたら 1 回の変更として扱うか、下位が届くまで値を確定しないようにします。
- MIDI 2.0 の受け手へ送る場合は、MIDI 1.0 の NRPN ではなく、MIDI 2.0 のコントローラーのメッセージを直接送ります。
MIDIFabric について
MIDIFabricは、MIDI 1.0 の機器を MIDI 1.0 のプロトコルで受け取り、CC 99、98、6、38 を自分で 1 つの NRPN にまとめます。モニタには最終的な値で 1 回の変更として表示し、開けば元の 4 つのメッセージを確かめられます。