見出し画像

Event PacketsさえわかればUSB-MIDIを攻略できるはず

以前、USB Hostを使ったライトを作ったとき、USB-MIDIを使ったが、駆け足すぎたので、今回、改めて、USB-MIDIのデータフォーマットの理解を深める

https://www.usb.org/MIDI を検索すると、1.0と2.0の資料がみつかる

  • Ver. 1.0と2.0があるが、直近で必要そうなのは、USB MIDI1.0だと思われるので、Universal Serial Bus Device Class Definition for MIDI Devices 1.0 Nov 1, 1999の4章のイベントパケットだけを今回は読む

  • 本当は通して読んだ方がよいのだろうが、データフォーマットがわかれば、とりあえずやりたいことはできそうと推測して

  • 困ったときに、資料を読み直すという戦略でいく

資料

USB-MIDI Ver.1.0の資料

  • 今回、読んだ資料は以下

https://www.usb.org/sites/default/files/midi10.pdf

USB-MIDI Ver.2.0の資料

https://www.usb.org/sites/default/files/USB MIDI v2_0.pdf

その他

https://midi.org/ にもMIDI関連の資料がありそうだが、メンバーにならないと見れないようだ

資料の意訳

「4 USB-MIDI Event Packets」をかなり意訳する(直訳は、自動翻訳に任せた、直訳が好きな方は本記事は向いていない)

イベントパケットの構成

https://www.usb.org/sites/default/files/midi10.pdf


MIDI data is transferred over USB using 32-bit USB-MIDI Event Packets. These packets provide an efficient method to transfer multiple MIDI streams with fixed length messages.

https://www.usb.org/sites/default/files/midi10.pdf
  • MIDIデータは、32ビット(4バイト)固定長で送信される



The 32-bit USB-MIDI Event Packet allows multiple "virtual MIDI cables" routed over the same USB endpoint. This approach minimizes the number of required endpoints.

https://www.usb.org/sites/default/files/midi10.pdf
  • 同じUSBのエンドポイントで複数の仮想MIDIケーブルを扱える仕様がある



It also makes parsing MIDI events easier by packetizing the separate bytes of a MIDI event into one parsed USB-MIDI event.

https://www.usb.org/sites/default/files/midi10.pdf
  • パケット化することで、MIDIイベントのパースを楽にしている(本意を把握できていないが、1つのUSB-MIDIイベントを1つのパケットにして、パースを楽にしている、と理解した)



The first byte in each 32-bit USB-MIDI Event Packet is a Packet Header contains a Cable Number (4 bits) followed by a Code Index Number (4 bits).

https://www.usb.org/sites/default/files/midi10.pdf

4バイトのうち、最初の1バイト目は、ケーブル番号(仮想MIDIのケーブル番号)とコードインデックス番号(メッセージのカテゴリのID、ノートオン、ノートオフなどを分別、と理解すればよいだろう)が含まれる



The remaining three bytes contain the actual MIDI event. Most typical parsed MIDI events are two or three bytes in length. Unused bytes must be padded with zeros (in the case of a one- or two-byte MIDI event) to preserve the 32-bit fixed length of the USB-MIDI Event Packet. They are reserved for future use. Figure 8 illustrates the layout of the packet.

https://www.usb.org/sites/default/files/midi10.pdf
  • 残りの3バイト、実際のMIDIイベントの内容

  • 1バイトと2バイトのデータのMIDIイベントの使わないバイトはゼロで埋める

    • (多くは、2バイト、もしくは3バイトのパケット)

  • SysExはどうなるの?と疑問に思うが、後を読むとわかる



The Cable Number (CN) is a value ranging from 0x0 to 0xF indicating the number assignment of the Embedded MIDI Jack associated with the endpoint that is transferring the data. The Code Index Number (CIN) indicates the classification of the bytes in the MIDI_x fields. The following table summarizes these classifications.

https://www.usb.org/sites/default/files/midi10.pdf
  • ケーブル番号(CN)は、0~15まで。

  • コード番号(CIN)は、クラス(カテゴリ)を表す

    • CINのカテゴリの分別は次に示す

  • 「CN」と「CIN」と似てるので混同しないように注意

    • ケーブル1本想定の場合、CNは無視してもよいはず

    • CINの0~Fのみを意識すればよさそう

CINの値

https://www.usb.org/sites/default/files/midi10.pdf
https://www.usb.org/sites/default/files/midi10.pdf


個人的に重要なCIN

  • 0x2: MTC(MIDIのタイムコード)

  • 0x4: SysEx starts or continues(システムエクスクルーシブメッセージの開始と途中)

  • 0x5: SysEx ends with following single byte.(システムエクスクルーシブメッセージの終了)

  • 0x6: SysEx ends with following two bytes(システムエクスクルーシブメッセージの終了)

  • 0x7: SysEx ends with following three bytes.(システムエクスクルーシブメッセージの終了)

  • 0x8: Note-off(ノートオフ)

  • 0x9: Note-on(ノートオン)

  • 0xB: Control Change(コントロールチェンジ)

  • 0xC: Program Change(プログラムチェンジ)

  • 0xE: PitchBend Change(ピッチベンドチェンジ)

SysExについて補足

  • SysExは、継続するか、終了するかでCINが変わる(パースがかなり楽!)

  • 次のパケットに続く場合は4で、このパケットで終わる場合は、5,6,7のうちのどれか(残りのバイト数によって異なる)

実際のパケットイベントの例

ノートオン

  • USB-MIDI Packet

19 9n kk vv
  • MIDIの場合

9n kk vv
  • ケーブル番号:1

  • CIN:9(ノートオンというクラス)

  • 9がノートオン(MIDIメッセージとしてのノートオンを示す)

  • nがチャンネル番号

  • kkがキー(音の高さ)

  • vvがベロシティ(音の大きさ)

システムエクスクルーシブの実際のデータの例

  • ケーブルはp(pは無視してよい)

SysExを4バイト送る場合

  • 1番目でp4で開始して3バイト送る

  • 2番目でp5で終了して1バイト送って、2バイトをゼロ埋めする

「F0 00 01 F7」は「p4 F0 00 01」「p5 F7 00 00」の2つのパケットになる

SysExを5バイト送る場合

  • 1番目でp4で開始して3バイト送る

  • 2番目でp5で終了して2バイト送って、1バイトをゼロ埋めする

「F0 00 01 02 F7」は「p4 F0 00 01」「p5 F7 00 00」の2つのパケットになる

SysExを6バイト送る場合

  • 1番目でp4で開始して3バイト送る

  • 2番目でp5で終了して3バイト送る

「F0 00 01 02 03 F7 」は「p4 F0 00 01」「p7 02 03 F7」の2つのパケットになる

SysExを2バイト送る

「F0 F7」は 「p6 F0 F7 00」の1つのパケットになる

SysExを3バイト送る

「F0 mm F7」は「p7 F0 mm F7」の1つのパケットになる

その他の例

https://www.usb.org/sites/default/files/midi10.pdf

感想

  • 4バイト固定長なのは、パースが楽だ

  • 最初のバイトのCINだけみて、不要なパケットは簡単に除外できそうだ

  • MIDIのラーニングステータスは、パース泣かせな仕様と感じる

    • もちろん遅い転送速度を補うために、データ数を減らすという工夫だと思うのだが

    • ラーニングステータスという特別な仕様の存在を知ると、他にも特別な仕様があるかもしれない、と考えてしまう

    • つまり、すべての仕様を把握しないと安心できない感がある

  • 4バイト固定で、先頭のバイトを見れば、データの全容が把握できるという仕様は、非常にありがたい

  • とはいえ、USB-MIDI Ver.2では、4バイト固定ではないようだ

  • 大きなデータを送信するときは、非効率感が否めないかもしれない


この記事が気に入ったらサポートをしてみませんか?