MIDI資料館‎ > ‎

SMF (Standard MIDI Files) の構造

更新履歴

目次


SMFとは

MIDIを使った演奏情報を一定の形式(フォーマット)のファイルにまとめたものを (ここでは)「MIDIデータファイル」と呼んでいるが、 そのMIDIデータファイルの、世界でもっとも一般的な形式がSMF(Standard MIDI Format)である。 ファイルの拡張子は ~.MID であることが多いが、 ~.SMF であることもある。

SMFは基本的に 「この時間(タイミング)に、この音を強さ**でオンにする」 といったレベルの情報の集まりでしかなく、 「ここを2回繰り返す」とかいった「ちょっと高級な情報」は扱えない。 よって、SMFは曲データを作成しているときの保存フォーマットとして用いられることは少なく、 専ら曲データ完成後の配布用フォーマットとして用いられている。 実際、一般的なシーケンサソフトでは、 独自フォーマットとSMFのどちらでもデータを保存することができ、 前者は通常のデータ保存に、後者は(シーケンサソフト外にデータを渡す)エクスポート的な機能として用いているはず。

以下の表記について、その他

  • 数値は、10進か16進かは特に区別せずルーズに記述している :-)。 ただし、 16進には prefixとして "0x"をつけていることがある。 (例: 0xFFなど。C言語での表記と同じ)
  • SMFにおいては、数値データはほぼすべてbig endianの即値で表される。 例えば 0x12345678 という4バイトの数値は、 0x12 0x34 0x56 0x78という順で格納される。
    (唯一の例外はMIDIイベントの0xEnで、 これだけはlittle endianで格納される)
  • 基本的に「(プログラム側で)理解できないコードは、無視する」 ことができるようなデータ構造になっているため、 SMF関連のプログラムを作成する際には、そのように設計すべき。 そうしておけば、将来SMFに拡張があった場合でも、 そのプログラムを使って問題が生じるようなことにはならない。

SMFのおおざっぱな構造

ものすごく大雑把に書くと、以下のものを順番に単純に結合(concatenate)したもの、 ということになる。

  • ヘッダ
  • トラックデータその1 (Conductor Track (和訳するなら指揮トラックってところ??)と呼ばれることもある。 フォーマット0の場合、 トラックデータその2以降は存在しない)
  • トラックデータその2
  • トラックデータその3
  • ・・・以後、トラックの数だけ、トラックデータが続く

以下サンプル。テンポ120で、四分音符でドレ、全音符でミを鳴らすSMF。 ヘッダとトラックデータその1(Conductor Track)、トラックデータその2を色分けしている。

000000 4D 54 68 64 00 00 00 06 00 01 00 02 00 30 4D 54  / MThd.........0MT
000010 72 6B 00 00 00 0B 00 FF 51 03 07 A1 20 00 FF 2F  / rk......Q....../
000020 00 4D 54 72 6B 00 00 00 18 00 90 3C 7F 30 3C 00  / .MTrk.....・0<..
000030 00 3E 7F 30 3E 00 00 40 7F 81 49 40 00 00 FF 2F  / .>.0>..@..0@.../
000040 00                                               / .

また、フォーマット1の場合、「トラックデータその1」 (Conductor Track)には演奏以外のデータ (テンポ等の各種メタイベントSysExイベント) を格納し、実際の演奏データは「トラックその2」以降に格納するのが一般的。

以下、ヘッダ以下の具体的なデータ構造を記す。


ヘッダについて

説明 "MThd" 実データの大きさ (現状、必ず6) フォーマット(0000/0001/0002) トラック数 (2byte数値) 時間単位 (デルタタイムの意味の指定)
データ例 4D 54 68 64 00 00 00 06 00 00 00 02 00 30

ヘッダにおける、実データの大きさについて

ヘッダに含まれる実データの大きさを4byteのbig endianで格納する。 ヘッダでの実データの大きさは、 フォーマットに2byte、トラック数に2byte、時間単位で2byteなので、合計6byte。 結局、ここには (現状では) 常に 00 00 00 06 が格納されることになる。

フォーマットについて

現在、0, 1, 2の3種類が定義されている。それぞれフォーマット0, フォーマット1, フォーマット2と呼ばれる。

  • フォーマット0
    1本のトラックに全チャンネルの情報を押し込める形式。 トラックが1つしかないため、対応プレーヤの制作が容易。 またプレーヤ・シーケンサ間の互換性も保ち易くなるため、 市販のSMFデータは大抵がこの形式。
  • フォーマット1
    同期演奏される複数のトラックで構成される。 大抵はシーケンサのいちトラックに対して SMFデータのいちトラックが対応するようになる。 つまり、一般的に「トラック」 と呼ばれるものが順番にバイナリ化されて concatenate (結合) されたフォーマットと考えればよい。 そのため、 トラック構成を保存しつつSMF化したい場合はこの形式が用いられる。 通常はこのフォーマット1を用いればよいと思う。
  • フォーマット2
    複数トラックで構成される。パターン情報を保存し、 パターンを切り替えつつ演奏させるなんて場合に用いる。 フォーマット1がトラックを垂直に並べ、 それぞれを同期させて演奏させるフォーマットであるとするなら、 フォーマット2はパターン情報を水平に並べ、 順番に演奏させるようなものといえるだろう。
    ただし筆者はフォーマット2に対応したシーケンサソフトを知らない。 通常フォーマット0か1だけを扱っていても特に問題となることはない (・・・と、思う)。

時間単位について (デルタタイムの意味の指定)

  • 正数である場合 (MSB(第15bit目)が0の場合; こちらが一般的)
    デルタタイムを、小節・拍等を基準として表現する。 この場合、このフィールドには4分音符あたりの分解能が入る。 例えば、全音符の分解能が1920だったなら、 ここに入るデータは 1920÷4 = 480 = 0x01E0 となる。
  • 負数である場合 (MSB(第15bit目)が1の場合)
    デルタタイムを、実時間のタイムコードで表現する。
    (以下は Standard MIDI Files 0.06 March 1, 1988 の翻訳より抜粋)

    上位バイトは -24, -25, -29, -30 の4つのうちひとつとなる。 (これは SMPTEや MIDIタイムコードの4種類の秒当りのフレーム数に対応している) 2番目のバイト(正数)はフレーム当りの分解能である。 通常の値は 4 (MIDIタイムコードの分解能), 8, 10, 80(ビット分解能), 100 であろう。 このシステムはタイムコードベースのトラックにはぴったりだが、 さらに、25 frames/sec で分解能を 40 units / frame にすることによって、 ミリセコンド・ベースのトラックにも有効である)


トラックデータについて

データ例 4D 54 72 6B ** ** ** ** ** ** ~
説明 "MTrk" 実データのデータ長 実データが続く

実データ (本当はMTrkイベントと呼ぶ) においては、以下のデータの組み合わせがトラック末尾まで続く。

以下、それぞれの構成要素について記す。

デルタタイムとは

次に続くイベントまでの時間を表す時間情報のこと。 ヘッダーブロックで時間単位の項目を正数で指定した場合 (=デルタタイムを小節・拍等を基準として表現する場合)、 デルタタイムは(直前のイベントから)次に続くイベントまでの時間差を表す。 例えば全音符の分解能が480だった場合、デルタタイム120というのは 「四分音符分の時間(の後)」を意味する。同様に、 もしトラックの最初のイベントがトラックの先頭に発生する際のデルタタイムや、 2つのイベントが同時に発生するような場合(の2つ目のイベント)につくデルタタイムは、 0となる。

上記の実データの説明でも分かるように、 前のイベントと次のイベントの時間間隔を定義するために、 デルタタイムは常に必要である。

ちなみにヘッダーブロックで規定するように、 デルタタイムは拍子(に基づく時間情報)を意味するだけではなく、 SMPTEタイムと共にトラックをレコーディングする場合の"秒"の分数 (分解能) を意味することもあるが、後者の表現を用いることは稀であり、 無視して良いと思う。 (映画なんかでSEを挟む場合、こちらの表現を用いることがある、らしい)

可変長形式について

デルタタイムは、以下のような可変長形式で表される。

  • 1byte(8bit)の内、数値に7bit、 次のバイトもデータバイトが続くかどうかのフラグに1bit用いる。 フラグにはMSB(第7bit)を用いる。
  • 最大4バイト。つまり、実際に表現できる数値の最大値は228-1。 これだけあれば、通常の音楽に用いる時間表現には十分。 (デルタタイム 0FFFFFFF というのは、1拍当りの分解能 1/96 でかつ 500 BPM という速いテンポでも4日間という長さ)
  • 以下具体例。左が数値(16進)で、右が可変長形式での表現(16進)。
    00000000 → 00
    00000040 → 40
    0000007F → 7F
    00000080 → 81 00
    00002000 → C0 00
    00003FFF → FF 7F
    00004000 → 81 80 00
    00100000 → C0 80 00
    001FFFFF → FF FF 7F
    00200000 → 81 80 80 00
    08000000 → C0 80 80 00
    0FFFFFFF → FF FF FF 7F

MIDIイベントとは

いわゆる演奏データのこと。 MIDIのチャンネルメッセージそのままと考えて差し支えない。
以下、具体例。

  • 8n kk vv (3byte) または 9n kk 00
    ノートオフ。チャンネル番号nで鳴っているノート番号kkの音を消音する。
  • 9n kk vv (3byte; vvは0以外)
    ノートオン。チャンネルnでノート番号kkの音をベロシティvvで発音する。 vvが0の場合は、ノートオフと同じ意味となる。
  • An kk vv (3byte)
    ポリフォニックキープレッシャー。 チャンネルnで発音中のノート番号kkの音に対し、ベロシティvvの プレッシャー情報を与える。 (キーボードで、今押さえている鍵盤を、 新たにベロシティvvで押さえ直す)
  • Bn cc vv (3byte) (特定条件下で、4byteになる時があるので注意。詳細後述)
    コントロールチェンジ。 チャンネルnで、コントローラナンバーccに、値vvを送る。
  • Cn pp (2byte)
    プログラムチェンジ。 チャンネルnで、プログラム(音色)をppに変更する。
  • Dn vv (2byte)
    チャンネルプレッシャー。 チャンネルnに対し、プレッシャー情報vvを送信する。 (ポリフォニックキープレッシャーの、チャンネル内全音版)
  • En mm ll (3byte)
    ピッチベンド。チャンネルnに対し、ピッチベンド値llmmを送信する。このイベントのデータに限り、さりげなくlittle endianなので注意。
    ピッチベンド値llmmは、他のMIDイベントの2byte目以降と同様に、
    • llとmmはどちらも7bitの値を採る
    • 正数のみ記載可能である
    ため、例えばピッチベンドが-8192,0,8191に対応する値llmmはそれぞれ 0x0000, 0x4000, 0x7F7F となる。(ピッチベンド値に 8192のゲタを履かせた形になる)

これらチャンネルメッセージは、 厳密にはチャンネルモードメッセージとチャンネルボイスメッセージに分かれる。

  • チャンネルモードメッセージ
    コントロールチェンジ120~127を使用するメッセージ(0xBn 0x78 ~ 0x7F) のことで、要は音源制御系のメッセージである。 (All Sounds Off とか、Reset All Controllers など)
  • チャンネルボイスメッセージ
    上記以外のチャンネルメッセージのことで、要は発音系のメッセージである。

チャンネルモードメッセージの中で、 「MIDIモードをモード4にする」操作を行うときにのみ、 コントロールチェンジ(0xBn)の構成バイトが4byteになるので注意。 それ以外のコントロールチェンジはすべて3byte構成になる。

例: MIDIモードをモード4(OMNI OFF / MONO)にする
B1 7C 00	(MIDIチャンネル2を、まずOMNI OFFにする)
B1 7E 00 04	(MONO; 4byte目に使用するチャンネル数(ここでは4つ)を記載する)

例: MIDIモードをモード2(OMNI ON / MONO)にする
B1 7D 00	(MIDIチャンネル2を、まずOMNI ONにする)
B1 7E 00	(そして、MONO ONにする)

ランニングステータスについて

前のMIDIチャンネルメッセージのステータスバイトと同じステータスバイトが連続する場合、 2回目以降のステータスバイトを省略することができる。 これをランニングステータス(ルール)と呼ぶ。 ステータスバイトとは、 MIDIのチャンネルメッセージで書いたところの、 0x8nとか0x9nとか0xAnとか。
例えば、以下の実データ例において、 太字で表した部分はランニングステータスルールにより省略可能である。
(なお一番左のデータはデルタタイムである。念のため)

00 90 3C 7F : ノート番号3C(ド)をベロシティ7Fで発音
60 90 3C 00 : ノート番号3C(ド)を消音
00 90 3E 7F : ノート番号3E(レ)をベロシティ7Fで発音
60 90 3E 00 : ノート番号3E(レ)を消音
00 90 3C 7F : ノート番号3C(ド)をベロシティ7Fで発音
00 90 40 7F : ノート番号40(ミ)をベロシティ7Fで発音
00 90 43 7F : ノート番号43(ソ)をベロシティ7Fで発音
60 90 3C 00 : ノート番号3C(ド)を消音
00 90 40 00 : ノート番号40(ミ)を消音
00 90 43 00 : ノート番号43(ソ)を消音
00 C0 00 : 音色をピアノに変更

ランニングステータスが適用されているかどうかは、 ステータスバイトに相当する部分のMSB(第7bit)で判定できる。 (0なら適用、1なら未適用)

ノートオフを表現する場合、8nと9nによる2つの表現方法があるが、 当然9nを用いた方がランニングステータスを適用しやすくなる、 すなわち、SMFのデータを小さくすることができる。
一方で、ランニングステータスを用いると、 曲の途中から再生するようときに、省略されたステータスをプレーヤが復元できない、 といったこともあり得るので、SMFデータ作成者は、 ランニングステータスを用いない方法でもデータを作成できるようにしておくべき。 またこの場合、先ほどとは逆にノートオフには8nを用いた方が、 ノートオフの意味合いをより明示できるだろう。

SysExイベントとは

主にMIDIシステムエクスクルーシブメッセージを指定するのに用いられる。 SysExイベントには、F0で始まるものとF7で始まるものの2種類がある。

w x y z
F0なSysEx F0
データ長 (= y + zの長さ)
転送データ (= w + y + z) F7
F7なSysEx F7
データ長 (= yの長さ)
転送データ(= y)

  • F0で始まる場合、
    • 送信されるデータにはF0が含まれる (つまり、w, y, z が送信される)
    • データ長にはF0の分を含めない (つまり、y + z 分の長さが収まる)
    • データの最後は必ずF7で終了する
    • 一般的には、エクスクルーシブメッセージを転送するのに用いる
    • 例: F0 05 aa bb cc dd F7 (これで、F0 aa bb cc dd F7 が転送される)
  • F7で始まる場合、
    • 送信されるデータにはF7が含まれない (y のみ送信される)
    • データ長にはF7の分を含めない (y の長さが収まる)
    • 一般的には、任意のデータを転送するのに用いる
    • 例: F7 04 aa bb cc dd (これで、aa bb cc dd が転送される)

いずれの場合も、データ長は可変長形式で格納される。 (従って、SysExイベントにはランニングステータスは適用できない。 データ長のMSB(第7bit)が可変長形式適用で1になっていると、 ランニングステータスとの区別が付かない)

F7で始まるSysExイベントは、リアルタイムバイトやソングポインター、 MIDIタイムコード、システムリセットなど、 通常の方法では送れないデータを直接送るための裏技として用いられるが、 シーケンサを変えた場合にこのデータがどう処理されるかは分からない等互換性維持の面で問題があるため、 通常はF0で始まるエクスクルーシブメッセージ送信のみを用いるのが無難である。
(実際、余程のことがない限りF0のみを使用していても問題とはならないはず)

メタイベントとは

メタイベントは、シーケンサやSMFに便利な、演奏データに含まれない情報 (テンポ、曲タイトル等)を納めるのに用いるイベント。 基本的に、ステータスバイトFFで始まり、 次にイベントタイプを表すバイトが続き、 さらに可変長形式で格納されたデータ長が続き、 最後にデータ自体が続く (SysExイベントのF7の場合と似ている)。

もしデータがなければデータ長は0となる。 SysExイベントと同様に、 ランニングステータスの適用はできない。

すべてのプログラムがすべてのメタイベントをサポートしなければならないということではない。

現在定義されているメタイベントは、具体的には以下のものがある。

ステータス
バイト
メタイベント
種類
データ長
(可変長形式)
データ 意味 備考
FF 00 02 ssss シーケンス番号
FF 01 len text テキスト
FF 02 len text 著作権表示
FF 03 len text シーケンス名(曲タイトル)・トラック名
FF 04 len text 楽器名
FF 05 len text 歌詞
FF 06 len text マーカー
FF 07 len text キューポイント
FF 08 len text プログラム名 (音色名) RP-019
FF 09 len text デバイス名 (音源名) RP-019
FF 20 01 cc MIDIチャンネルプリフィックス v1.0
FF 21 01 pp ポート指定 SMF非標準
FF 2F 00 --- トラック終端
FF 51 03 tttttt テンポ設定
FF 54 05 hr mn se fr ff SMPTEオフセット
FF 58 04 nn dd cc bb 拍子の設定
FF 59 02 sf mi 調の設定
FF 7F len data シーケンサ特定メタイベント

  • FF 00 02 ssss : シーケンス番号

    フォーマット2で、パターンを識別するために用いる。 通常フォーマット0,1では用いない。

  • FF 01 len text : テキスト

    任意の長さ・内容のテキストを記述することができる。 ただし、 著作権表示シーケンス名/トラック名楽器名歌詞マーカーキューポイントプログラム名デバイス名 といった用途には、 専用のメタイベントタイプ(0x02~0x09)が別途用意されているのでそちらを用いるべき。
    (余談: メタイベントタイプの 0x01~0x0Fは、 この手のテキストイベントのために予約されている)

    例えば、トラックのいちばん初めに、意図する音源名やオーケストレイション、 その他ユーザがそこに置きたいと思う情報を書いておくと良い。

    なお互換性のことを考えると、このイベント中のテキストは、 印刷可能なASCII文字を使用することが推奨されている。 (まあイマドキそんなことを気にする必要もないとは思いますが・・ 以下、 いちいち書きませんがテキスト関連のメタイベントすべてに同じことが当てはまります)

  • FF 02 len text : 著作権表示

    曲に関する著作権表示を記述する。 この表示には (C)の文字、 著作物発行年と、著作権所有者名とが含まれなければならない。

    このイベントは第1トラック (Conductor Track)の最初のイベントとして、 デルタタイム0で置かれなければならない。 また、ひとつのMIDIファイルに幾つかの楽曲がある時には、 すべての著作権表示をこのイベントに置いて、 かつそれがファイルの先頭に来るようにしなければならない。

  • FF 03 len text : シーケンス名(曲タイトル)・トラック名

    以下の場合には、シーケンス名(つまり、曲のタイトル)となる。

    その他の場合には、トラック名となる。
  • FF 04 len text : 楽器名

    そのトラックで用いられる楽器の種類を記述する。

  • FF 05 len text : 歌詞

    歌詞。
    一般的には、(歌詞の)各音節が別々の歌詞イベントとして記述され、 そのイベントが始まるタイミングでシーケンサ等が歌詞を表示することになる。

  • FF 06 len text : マーカー

    リハーサル記号やセクション名のような、 シーケンスのその時点の名称を記述する。 ("Introduction" とか "A", "B" など)

    このメタイベントを使用する場合、置き場所としては 通常フォーマット0のトラック、 もしくはフォーマット1のファイルの第1トラック (Conductor Track)となる。

    (余談: 日本ファルコム社のYs2 EternalのMIDI曲では、 このメタイベントを 無限ループ用のマーカーとして用いているようです)

  • FF 07 len text : キューポイント

    曲データ中、このメタイベントの挿入されている位置で、 その曲以外の進行を記述するのに用いる。 (曲中の進行の記述には、マーカーを用いる)

    例えば「車が走り出す」「画面がフェードアウトする」など。

  • FF 08 len text : プログラム名 (音色名)

    直後に続く「プログラムチェンジ」と 「バンクチェンジ」で表している音色名を記載する。 (非GM音源だと結構使いでがあるでしょ?)

    このメタイベントはトラック中のどこにおいても構わないが、 プログラムチェンジやバンクセレクトと共に用いるべきである。

  • FF 09 len text : デバイス名 (音源名)

    このメタイベントがあるトラックが、 どのデバイスに配置されるのかということをテキストで表すものだが、 大抵は音源の名前を入れることになるだろう。
    (区別できれば結局どんなテキストでも構わないわけですが)

    このメタイベントは、1トラックにつき1回だけ、 最初に音源にデータが送られる前に記述されるべき。
    (データが送られた後で音源が決まるんじゃ、意味ないですしね)

    ちなみにこのメタイベントは、 あくまで16ch以上のデータを想定して考案されたものなので、 「音源名」に拘らず「ポート番号」や、 もっと極端な話「FM」「WAVE」とか、そういったのもアリ。

  • FF 20 01 cc : MIDIチャンネルプリフィックス

    MIDIイベント以外 (つまりSysExイベントメタイベント)のイベントに対して、 MIDIチャンネルを指定する際に用いる。

    例えば、 エクスクルーシブメッセージをMIDIチャンネルに対応させたり、 楽器名をMIDIチャンネルに対応させたり、 フォーマット0を使用時にMIDIチャンネルとトラック名を対応させたりする場合に用いる。

    なおこのイベントによる設定は、再度このイベントが現れるか、 任意のMIDIイベントが現れるまで有効。

  • FF 21 01 pp : 出力ポート指定 (現在のSMFでは未定義)

    このメタイベントは現在のSMF Version 1.0では定義されていないが、 32ch対応のMIDI音源の台頭に伴い、 いわゆるデファクトスタンダードとして普及しているようだ。

    利用法として、現状以下の3パターンが確認されているが、 どのパターンで作成されているかはデータだけでは識別不能。

    1. pp=0~3が、それぞれポート1~4に対応している場合
    2. pp=0がミュート、1~4がそれぞれポート1~4に対応している場合
    3. pp=0がポート1、pp=1がポート2、pp=2がポート1&2両方、 pp=3がミュート

    日本国内(のフリーソフトの類)では基本的に 1. のパターンを想定しておけば問題ないと思われる。

    このイベントの効力は次に同イベントが出現するまで続く。 当然ながら初期状態(無指定時)ではポート1が選択されている。

    (余談: SMF ver1.0 specに完全に沿った形で32chなデータを表現する (つまり、このメタイベントを用いない)場合、以下の方法が考えられる。

    1. フォーマット2を使う
    2. 出力ポート毎に、個別のSMF(ファイル)を出力する
    3. テキストイベント等 メタイベント FF 09 (デバイス名) で、トラック毎に 出力ポート 出力デバイス名 を明記しておく
    ただし、1.~3.はいずれも演奏には当然「対応プレーヤ」が必要となる・・・
  • FF 2F 00 : トラック終端

    そのトラックの終端を表す。
    これがあることによって トラックの正しい終結点が明確になり、 トラックが正確な長さを持つようになる。 このイベントは仕様上省略不可となっているので注意。

    (余談: 逆に、メタイベントに関しては、 このメタイベントと次に出てくるテンポのメタイベントさえ実装すれば、 極端な話それ以外(のメタイベント)は実装上無視しても、 演奏自体は正しいものとなる)

    (蛇足: FF 2* 系は、基本的に「トラック全体に関わる設定項目」 を想定しているように思われます)

  • FF 51 03 tttttt : テンポ設定 (単位は μsec / MIDI 四分音符)

    このイベントでテンポ変更を指示する。
    tttttt (3byte) には、四分音符の長さをマイクロ秒 (μsec) で表したものを格納する。

    例えば、BPM=120 (1分あたり四分音符が120個)の場合、 四分音符の長さは 60 x 106 / 120 = 500,000 (μsec)。 これを16進にすると0x07A120。従って、メタイベントは
    FF 51 03 07 A1 20
    となる。

    (余談: 割算した結果が割り切れない場合、大抵のプレーヤは 「有効桁数以下切り捨て」として扱っている → データ作成時も切り捨てていることを想定している、 ようです。 個人的には有効桁数以下0捨1入した方がより正確なテンポ値に近づくと考えますが、 自身のMMLコンパイラでそのように実装した結果プレーヤでの表示が1ずれたりしちゃって、 「何でテンポ値がずれるの?」 というFAQに追われる羽目となってしまいました(^^;)

  • FF 54 05 hr mn se fr ff : SMPTE オフセット

    トラックデータの先頭にこのメタイベントをおくことで、 トラックデータの演奏開始時刻を指定することができる。 時間は、MIDIタイムコードと全く同様に、 SMPTEフォーマットでエンコードされなければならない。

  • FF 58 04 nn dd cc bb : 拍子記号

    拍子記号は、4つの数字で表現される。 nnとddは、そのまま拍子記号の分子と分母を表す。 ただし分母は2のマイナス乗で表現する。 つまり2=4分音符、3=8分音符、4=16分音符・・・となる。

    ccは、メトロノーム1拍あたりのMIDIクロック数を表している。 24MIDIクロックで4分音符を表す(後述)ため、 例えば4分音符ごとにメトロノームを鳴らす場合、 cc=0x18 (=24)となる。

    bbは、MIDI4分音符(24MIDIクロック)の中に入る32分音符の数を表す。 大抵bb=8となる。

    例:
    4/4拍子だと、FF 58 04 04 02 18 08
    3/4拍子だと、FF 58 04 03 02 18 08
    6/8拍子だと、FF 58 04 06 03 18 08
    いずれも、cc=0x18(=24)、bb=8の場合。 (余程のことがない限り変更する必要はないと思いますが)

  • FF 59 02 sf mi : 調号

    調号を指定する。

    sfには、♯や♭の数が入る。正数なら♯の数、負数なら♭の数を表す。 ハ長調(つまり♯も♭もない)の場合は0。 (このあたりの詳細は、楽典などで確認のこと。)

    miは長調か短調かを表すフラグで、0なら長調、1なら短調。

  • FF 7F len data : シーケンサー特定メタイベント

    特定のシーケンサーのための特別な要求のためこのイベントタイプを用いる。 データバイトの最初の1バイトはメーカーIDである。 その後、独自フォーマットによるデータが続く。 このようなものであるため、 SMFデータの互換性を考えるならこの機能を使うことはないだろう。


SMFの実際

テンポ120で、四分音符でドレ、全音符でミを鳴らすSMF。
ランニングステータスが多用されていることに注意。 また、ランニングステータスの効果を高めるために、 ノートオフとして 9n kk 00 (ベロシティゼロでノートオン) を使用している。
000000 4D 54 68 64 00 00 00 06 00 01 00 02 00 30 4D 54  / MThd.........0MT
000010 72 6B 00 00 00 0B 00 FF 51 03 07 A1 20 00 FF 2F  / rk......Q....../
000020 00 4D 54 72 6B 00 00 00 18 00 90 3C 7F 30 3C 00  / .MTrk.....・0<..
000030 00 3E 7F 30 3E 00 00 40 7F 81 49 40 00 00 FF 2F  / .>.0>..@..0@.../
000040 00                                               / .
ヘッダ
4D 54 68 64				"MThd"
00 00 00 06				ブロック長(6)
00 01					フォーマット(1)
00 02					トラック数(2)
00 30					四分音符の分解能(0x30=48)

トラック1のデータ (Conductor Track)
4D 54 72 6B				"MTrk"
00 00 00 0B				ブロック長(0x0B=11)
00 FF 51 03 07 A1 20			テンポ(120)
00 FF 2F 00				トラックエンド

トラック2のデータ (演奏トラックその1)
4D 54 72 6B				"MTrk"
00 00 00 18				ブロック長(0x18=24)
00    90 3C 7F				ベロシティ127でノート3Cをノートオン
30       3C 00				48tick後、ノート3Cをノートオフ
00       3E 7F				直後に、ベロシティ127でノート3Eをノートオン
30       3E 00				48tick後、ノート3Eをノートオフ
00       40 7F				直後に、ベロシティ127でノート40をノートオン
81 40    40 00				192tick後、ノート40をノートオフ
00    FF 2F 00				トラックエンド

筆者がたどったはまり道

  • ランニングステータスは、 MIDIイベントのみに有効
     つまり、SysExイベント(F0, F7)や、 メタイベント(FF) では使えない。
  • SysExイベント(F0, F7)のデータ長は、 可変長形式で格納する
     ただ、大抵この手のデータは127バイト以下なので、 ただの1バイトデータだと思いこんでいても何とかなってしまうことが多いが。
  • 曲中の テンポ情報(FF 51 03)は、 Conductor Track(最初のMTrk)にすべてまとめる
     これをやっておかないと一部シーケンサ (MacのPerformer; バージョンは分からず)なんかで誤動作することがあるらしい。 以下は Standard MIDI Files 0.06 March 1, 1988 の翻訳より抜粋。

    フォーマット0 のファイルでは、テンポはトラック中に分散し、 テンポ・マップ・リーダーは間のイベントを無視しなければならない。 フォーマット1 のファイルでは、テンポ・マップは最初のトラックになければならない (0.04から追加)。


参考文献


E-mail:

Comments