2020年9月6日日曜日

C#で、もう1回、MIDI その4

 今回はMIDIファイルで遊ぶため、そのフォーマットをまとめておきます。

 MIDIファイルのフォーマットの詳細は、WikipediaさんとかGoogle先生とかに聞けばわかります。それでも分からないところは、実際のMIDIファイルをダンプして調べてみませう。


------------------------------

 MIDIファイルの構造 (SMF, Standard Midi File)

<HeaderChunk> + <TrackChunk> + <TrackChunk> ...


MIDIファイルには複数のフォーマットがある (SMF0, SMF1, SMF2)

SMF0 : TrackChunkは1つ

SMF1 : TrackChunkは複数

SMF2 : 使われていないらしいので省略


SMF1では、1つのTrackには1つのChannel (1つの楽器) が対応

SMF1では、最初のTrackにはテンポなどの情報だけ入れる(コンダクタトラック)


--------------------------------------------------

<HeaderChunk>

ChunkID            4bytes, "MThd"

ChunkSize          4bytes, Big Endian, 6

FormatType         2bytes, Big Endian, 0 or 1

NumberOfTracks     2bytes, Big Endian, SMF0なら1

TimeDivision       2bytes, Big Endian


--------------------------------------------------

TimeDivisionについて

(1) bit15が0の場合(0*** **** **** ****)

4分音符の分割数 (48, 96, 960, etc)

4分音符の実際の時間は、MidiEventのMetaEventで設定可能 (デフォルトは0.5sec)

(2) bit15が1の場合(1aaa aaaa bbbb bbbb)

1aaa aaaaが1秒間のフレーム数 (-24, -25, -29, -30)

bbbb bbbbが1フレームの分解能 (4, 8, 10, 80, 100, etc)


(1)を使うことが多い

なお、MIDIでは最小時間単位をtickという


--------------------------------------------------

<TrackChunk>

ChunkID            4bytes, "MTrk"

ChunkSize          4bytes, Big Endian

Data               MidiEventの配列


MidiEventには、ChannelEvent , SystemEvent, MetaEventの3種類ある(最初の1byteで区別する)


--------------------------------------------------

variable length (可変長)について

最上位bitが1なら、次の1byteもデータと見なす

(1xxx xxxx 1yyy yyyy 0zzz zzzz) は (xxx xxxx yyy yyyy zzz zzzz)を意味する

最大4bytes (データは最大で28bits)


--------------------------------------------------

<ChannelEvent>

DeltaTime      variable length, Big Endian, 直前のMidiEventからの時間 (tick単位)

EventType      1byte, 0x80-0xEF

Param1         1byte

Param2         1byte, EventTypeによっては存在しない


0x 8n kk vv    3bytes, Note Off

0x 9n kk vv    3bytes, Note On

0x An kk vv    3bytes, Note Aftertouch

0x Bn cc dd    3bytes, Controller

0x Cn pp       2bytes, Program Change

0x Dn vv       2bytes, Channel Aftertouch

0x En ll mm    3bytes, Pitch Bend


n      4bits, 0-15,  Channel Number

kk     1byte, 0-127, Note Number

vv     1byte, 0-127, Velocity

cc     1byte, 0-127, Controller Type

dd     1byte, 0-127, Controller Value

pp     1byte, 0-127, Program Number

ll     1byte, 0-127, Pitch Value

mm     1byte, 0-127, Pitch Value


ChannelEventでは、同じChannelEventが連続するときは、2回目以降が省略可能 (Running Status)

1つのChannelには1つの楽器を対応させる (n=9はパーカッションに固定されている)

ControllerについてはWikipedia etcを参照

Program NumberについてはWikipedia etcを参照

llとmmは2つで1つのパラメータ(0-16383、8192のときはPitchの変更なし)

ll=0xxxxxxx, mm=0yyyyyyyは、yyyyyyyxxxxxxxを意味する(Little Endian)


--------------------------------------------------

<SystemEvent>

DeltaTime      variable length, Big Endian, 直前のMidiEventからの時間 (tick単位)

EventType      1byte, 0xF0 or 0xF7

DataLength     variable length, Dataのサイズ(byte単位)

Data


Dataが長い場合は、複数のSystem Eventにすることもある(送信エラーも起こりうる)

Dataの最初なら、System EventはF0で始める

分割されたDataの途中なら、System EventはF7で始める(variable lengthは分割されたDataのサイズ)

Dataの最後にはF7を付ける (variable lengthにはF7の1byteも含める)


--------------------------------------------------

<Meta Event>

DeltaTime      variable length, Big Endian, 直前のMidiEventからの時間 (tick単位)

EventType      1byte, 0xFF

MetaEventType  1byte, 種類はたくさんある

DataLength     variable length, Dataのサイズ(byte単位)

Data


0x FF 00    シーケンス番号  (Dataは2bytes)

0x FF 01    テキスト

0x FF 02    著作権

0x FF 03    シーケンス名

0x FF 04    楽器名

0x FF 05    歌詞

0x FF 06    マーカー

0x FF 07    キューポイント

0x FF 20    MIDIチャンネルプリフィックス    (Dataは1byte)

0x FF 21    ポート指定  (Dataは1byte。非標準。)

0x FF 2F    トラック終端    (必須。Dataは0byte)

0x FF 51    テンポ      (Dataは3bytes)  4分音符の秒数(usec単位) デフォルトは500000usec

0x FF 54    オフセット  (Dataは3bytes)  hr mn se fr ff  0-23, 0-59, 0-59, 0-30, 0-99の値をとるらしい

0x FF 58    拍子        (Dataは4bytes)  4/4拍子とか

0x FF 59    調号        (Dataは2bytes)  シャープ、フラット、長調、短調

0x FF 7F    シーケンサー特定メタイベント


--------------------------------------------------

参考URL

http://ja.wikipedia.org/wiki/General_MIDI

http://www.midi.org/techspecs/midimessages.php


0 件のコメント:

コメントを投稿