今回はC#を使ってMIDIのプログラミングをしてみようと思います。
プログラミングをするには、当然、予備知識が必要です。たいていはGoogle先生とかWikipedia先生に訊けば分かります。
とりあえず、手始めにMIDIファイルの構造を以下にまとめてみます。
次回以降が実際のソースコードです。まぁ、百聞は一見に如かずで、ソースコードを見た方が分かりやすいかもしれません。
参考URL
MIDI
SMF
C#
Windows API
==================================================
MIDIファイルの構造 (SMF, Standard Midi File)
<HeaderChunk> + <TrackChunk> + <TrackChunk> ...
MIDIファイルには複数のフォーマットがある (SMF0, SMF1, SMF2)
SMF0 : TrackChunkは1つ
SMF1 : TrackChunkは複数 (1つのTrackには1つのChannelが対応, 最初のTrackにはテンポなどの情報だけ入れる(コンダクタトラック))
SMF2 : 使われていないらしいので省略
==================================================
<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(可変長)について
最上位bitが1なら、次の1byteもデータと見なす
(1xxx xxxx 1yyy yyyy 0zzz zzzz) は (xxx xxxx yyy yyyy zzz zzzz)を意味する
最大4bytes (データは最大で28bits)
==================================================
<ChannelEvent>
DeltaTime variable, 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はパーカッションに固定されている) (SMF1なら1つのTrackが1つのChannel、1つの楽器に対応する)
ControllerについてはWikipedia etcを参照
Program NumberについてはWikipedia etcを参照
llとmmは2つで1つのパラメータ(0-16383、8192のときはPitchの変更なし)
ll=0xxxxxxx, mm=0yyyyyyyは、yyyyyyyxxxxxxxを意味する(Little Endian)
Dataが長い場合は、複数のSystem Eventにすることもある(送信エラーも起こりうる)
Dataの最初なら、System EventはF0で始める
分割されたDataの途中なら、System EventはF7で始める(variableは分割されたDataのサイズ)
Dataの最後にはF7を付ける (variableにはF7の1byteも含める)
==================================================
DeltaTime variable, 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はパーカッションに固定されている) (SMF1なら1つのTrackが1つのChannel、1つの楽器に対応する)
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, Big Endian, 直前のMidiEventからの時間 (tick単位)
EventType 1byte, 0xF0 or 0xF7
DataLength variable, Dataのサイズ(byte単位)
Data
Dataが長い場合は、複数のSystem Eventにすることもある(送信エラーも起こりうる)
Dataの最初なら、System EventはF0で始める
分割されたDataの途中なら、System EventはF7で始める(variableは分割されたDataのサイズ)
Dataの最後にはF7を付ける (variableにはF7の1byteも含める)
<Meta Event>
DeltaTime variable, Big Endian, 直前のMidiEventからの時間 (tick単位)
EventType 1byte, 0xFF
MetaEventType 1byte, 種類はたくさんある
DataLength variable, 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
==================================================