更新日:
確認環境: macOS 27.0(測定)、macOS 15 の構成ファイル

MIDI 2.0 の機器を一台もつないでいない Mac で、IAC ドライバのバスだけが MIDI 2.0 でした。

つまり、IAC でつないだアプリ間の MIDI は、MIDI 2.0 の機器がなくても、すでに MIDI 2.0 を通っています。IAC のバスは MIDI 2.0 のプロトコルを報告していて、アプリが MIDI 1.0 で IAC に送ると、Core MIDI が受け手に合わせて変換します。MIDI 2.0 で受け取るアプリには MIDI 2.0 のメッセージ(16 ビットのベロシティなど)が、MIDI 1.0 で受け取るアプリには MIDI 1.0 のメッセージが届きます。

気づいたきっかけ

MIDIFabric で、MIDI 1.0 と MIDI 2.0 の変換をどこで行うかを決めるために、Mac のポートのプロトコルを調べていました。macOS 27.0 で Core MIDI のプロトコルのプロパティを読むと、USB、DIN、ネットワークの機器はどれも 1(MIDI 1.0)だったのに、IAC のバスだけは送信側も受信側も 2(MIDI 2.0)でした。

macOS 27 で変わったわけではありません。2025 年 7 月(macOS 15 のころ)に保存された MIDI の構成ファイルにも、IAC ドライバの protocol = 2 がすでに書かれていました。少なくともそのころから MIDI 2.0 だったことになります。いつからなのかは、調査していません。

私たちが確認した範囲の Apple の文書(Core MIDI のヘッダーと API ドキュメント、Audio MIDI 設定のユーザーガイド)には、IAC が MIDI 2.0 だとは書かれていませんでした。ただ、JUCE のフォーラムでも、JUCE の開発者が実際の挙動から同じことを指摘しています。

変換そのものについては、Apple のドキュメントに、Core MIDI が MIDI 2 の仕様を採用し、受け手が指定するプロトコルへ透過的に変換すると書かれています。個々のメッセージをどう変換するかまでは書かれていないので、実際に送って確かめました。

MIDI 1.0 から MIDI 2.0 へ

MIDI 1.0 で IAC のバスに送り、MIDI 2.0 で受け取りました。

MIDI 1.0 で送ったものMIDI 2.0 で届いたもの
Note On C4、ベロシティ 64Note On C4、16 ビットのベロシティ 0x8000(中央の値)
CC 74 = 32CC 74 = 0x40000000(32 ビットの値)
バンクセレクト 1 / 2 + プログラム 5バンクを含んだ 1 つのプログラムチェンジ

値は、最小・中央・最大が変わらないように広げられています。MIDI 2.0 の仕様にある方法どおりです。

MIDI 2.0 から MIDI 1.0 へ

逆に、MIDI 2.0 のメッセージを MIDI 1.0 の受け手へ送りました。

MIDI 2.0 で送ったものMIDI 1.0 で届いたもの
Note On、ベロシティ 0x8000Note On、ベロシティ 64
Note On、ベロシティ 0x0100(ごく弱い)Note On、ベロシティ 1(0 にはならない)
Note On、ベロシティ 0x0000Note On、ベロシティ 1(Note Off にはならない)
NRPN 1:2値を含む 4 つの CC(99、98、6、38)
RPN 0:0 = 23 つの CC。下位の値が 0 なので CC 38 が省かれたらしい(未確認)
バンク付きのプログラムチェンジCC 0、CC 32、プログラムチェンジ
ノートごとのピッチベンド、相対値のコントローラー、ノートの属性届かない(MIDI 1.0 に対応するものがない)

途中で変わる細部

ほとんどは仕様どおりでしたが、いくつか引っかかる所がありました。

  • 同じメッセージでも、送り方で届き方が変わる。 アプリが MIDI 1.0 のメッセージを「MIDI 2.0」と宣言して送ると、Core MIDI は変換しません。MIDI 2.0 の受け手には、MIDI 1.0 のメッセージがそのまま届きます。「MIDI 1.0」と宣言して送れば変換されます。
  • NRPN が途中の値で届く。 MIDI 1.0 から MIDI 2.0 への変換で、Core MIDI は NRPN の値を 2 回出しました。1 回目は CC 6 が届いた時点で、値の上位だけ。2 回目は CC 38 が届いた時点で、完全な値です。1 回目に反応する受け手は、一瞬だけおかしな値を受け取ります。詳しくは「NRPN が最初に違う値で届くのはなぜ?」に書きました。
  • RPN では、CC 101 が先にそのまま届く。 変換された RPN の前に、元の CC 101 がそのまま通ってきました。
  • IAC の MIDI 1.0 の受け手に、同じメッセージが重ねて届く。 IAC を通した NRPN が、MIDI 1.0 の受け手には CC 99、98、6、6、38 として届き、RPN では CC 101 が 2 回届きました。IAC が内部で MIDI 2.0 に変換し、また戻しているからだと考えています。最終的な値は正しいものの、MIDI ラーンやログには余分なメッセージが見えます。

使う側への影響

  • IAC でアプリ間の MIDI をつないでいるなら、MIDI 1.0 の機器しか持っていなくても、もう MIDI 2.0 の経路を使っています。
  • MIDI 2.0 で受け取れるアプリ(Logic Pro 10.7.7 以降、Cubase / Nuendo 13 以降など)は、IAC から高い解像度の値を受け取れます。
  • IAC を通した NRPN で、MIDI ラーンが CC を二重に拾ったり、おかしな値を拾ったりするなら、上の変換を疑ってみてください。

まだ確かめていないこと

  • MIDI 2.0 モードの DAW が、ほかのアプリが「MIDI 2.0」と宣言して IAC に送った MIDI 1.0 のメッセージを受け付けるか。
  • 2 つのアプリが同じ受け手に同時に送ったとき、Core MIDI が展開した一連のメッセージ(RPN、NRPN、バンクとプログラム)の間に、別のメッセージが割り込むか。
  • RPN の下位の値が 0 のとき、CC 38 が必ず省かれるか。
  • macOS 15 より前、それに Windows や Android での挙動。

何か分かったら、このページを更新します。

MIDIFabric について

MIDIFabricは、IAC のバスも含めて、どのポートが MIDI 2.0 かを表示し、モニタで MIDI 2.0 のメッセージを名前で解読します。上に書いた変換は、macOS が行っています。

← 開発ノートの一覧