「SMFの基礎知識」


 ここでは、日常音楽演奏データのやりとりで当たり前のように使われるようになったSMF(スタンダードMIDIファイル)についてお勉強してみようと思います。



1、RPとスタンダードMIDIファイル

 みなさん御存じの通り、MIDIは世界の統一規格で、日本のMIDI規格協議会(JMSC)※1と日本以外の外国を管轄する米国のMMA(MIDI Manufactures Association)によって管理されています。現在のところMIDI規格1.0Ver4.2というのが最新の規格のはずです。MIDI規格の改訂、追加はJMSCとMMAにより随時協議され、規格として承認されたものは承認確認事項C/A(Confirmation Approval)として随時発行されています。
近年様々な形でMIDIが利用されるようになり、新しい応用例をより柔軟に扱えるよう導入されたのがRP(Recommended Practice)です。RPはMIDI規格の一部というわけではなく、JMSCとMMAによって合意されたMIDIの応用例と言えます。
JMSCとMMAはPR文書の管理を行っていますが、実際の運用はRPを採用する各メーカーの責任においてなされます。RPは必ずしもMIDIの応用例の標準を定めるものではなく、採否は各メーカーの判断に任されているというのが現状です。
これからお勉強していくSMFもそのRPの一つなのです。

※1 現在は平成8年に電子楽器メーカーを中心に構成される「音楽電子事業協会」AMEI(Association of Musical Electronics Industry)が設立され、その中のMIDI規格委員会が同事業を運営しています。


2、SMFの誕生

 そもそもSMFは、1988年にDave Oppenheim氏(Opcode System社長)によってMMAに提案されたのが始まりです。当時MMAからJMSCに規格検討の依頼がありましたが、日本では承認されず、MIDI規格としては成立しませんでした。
当時JMSCではMIDIとはMIDI端子をつなぐMIDIケーブル上の通信プロトコルであり、それ意外はMIDI規格の範囲ではないという考えを持っていたためです。
MIDIデータのフォーマット統一は異機種間での相互利用が可能になるだけでなく、データビジネスには大きなメリットが生まれます。主にソフト・メーカー中心で構成されているMMAがJMSCにSMFの規格検討を提案した理由はその点にあります。
個人のユーザーでも簡単に別のシーケンサーにデータを移動出来れば便利であることは言うまでもありません。
しかし、シーケンサーの機能はそのシーケンサーの扱うデータ・フォーマットに多大な影響を受けます。データのフォーマット統一はもしかしたらシーケンサーの機能を制約しかねません。つまりデータのフォーマット統一はシーケンサーにとっては好ましいとは言えないのです。
結果、シーケンサー内部では独自のフォーマットを採用し、SMFのセーブ/ロード時にはコンバーター等で対応するという方式でSMFが一人歩きを始めてしまいました。その後オプコードの「シーケンサー2.5」をスタートに、多くのシーケンサー・ソフトに採用されるようになっていきました。
このようにSMFは広まり、そのことがRPを誕生させたと言っても過言ではありません。その証拠にSMFはRPの一番に登録されています。
以下がJMSCとMMAで合意されたRPです。

RP-001スタンダードMIDIファイル
RP-002MIDIショー・コントロール
RP-003GMシステム・レベル1
RP-009ファイル・ダンプ
RP-012MIDIチューニング
RP-013MIDIマシン・コントロール












3、SMFの主な特徴

●可変長フォーマットである

 SMFは必要に応じてデータ・バイト数やデルタ・タイムのバイト数が増減し、メモリーを効率よく使うことが出来ます。
 コンピュータの世界では下位バイトから読み込むことが多いのですが、SMFでは上位バイトから読み込みます。

●データ構造がシンプル

 基本はMIDIのチャンネル・メッセージから構成されていて、それに時間情報であるデルタタイムが加わったものと考えれば差し支え有りません。ノート・オンとノート・オフは別のイベントとして扱われるので、演奏プログラムの負荷を少なくすることが出来ます。
 またデルタタイムの時間単位には2つのフォーマットが用意されています。通常シーケンサーで使われる相対時間とタイムコードに対応する絶対時間の表記が可能です。

●3つのフォーマットがある

 SMFにはフォーマット0/1/2の3つのフォーマットがあります。通常は複数トラックを持つフォーマット1が便利です。単純な演奏データの受け渡しには1トラック/マルチチャンネルで構成されるフォーマット0が使用されます。たいていのシーケンサー、シーケンサー・ソフトはフォーマットー0/1に対応しています。
フォーマット2については対応している機器、ソフトを私は知りません。フォーマット2は主にドラム・マシンのシーケンサー用のようで、シーケンス・パターンを指定して演奏するためのフォーマットのようです。

●小節の概念がない

 SMFでは小節線にあたるイベントは定義されていません。SMFで小節管理させるためにはイベントで定義されている拍子から小節位置を計算しなければなりません。
 よくソフト上ではちゃんと変拍子で作ったのに、SMFにしたら拍子がぐちゃぐちゃになっちゃったという経験があると思います。これはSMFに小節概念が無いために起こるものです。


4、SMFの目的

 SMFの主な目的は演奏データの互換性を得ることです。これは異なった機種、ソフト間で時間情報を含むMIDIデータを相互に利用出来るようにすることです。
このフォーマットはデータをコンパクトにすることを目標の一つとしていて、ディスク・ベース、ネットワーク・ベースでのやりとりには最適と言えます。しかしシーケンサー・プログラムが素早くアクセスしたり、編集を行うのには不向きという面もあります。ですからSMFはそれを直接演奏したり編集したりするのではなく、あくまでデータの受け渡しに利用されるのが一般的です。


5、SMFのデータ・フォーマット

 前述したようにSMFのフォーマットはMIDIイベント+タイミング情報という極めてシンプルな構造になっています。SMFでは各MIDIイベントごとに時間情報を持っていて、ノート・オン/オフは別扱いです(ちなみにSMFのノート・オン/オフはゲート・タイムで管理するタイプではありません)。更にソング、シーケンス、トラック構造、テンポ、拍子記号等もサポートされています。
 またトラック名やコメント等その他の記述情報はMIDIデータと共にファイルとしてストアすることが出来ます。

5ー1 可変長数値表現

 このお勉強部屋では、ビット0は1バイトの最下位ビットを表し、ビット7が最上位ビットを表すということを前提にお勉強を進めます。
 SMF中の数値は、多くの場合「可変長数値表現」と呼ばれる形式で表現されます。これらの数値は1バイトあたり7ビットで構成され、上位バイトを先頭に表現されます。そしてビット7をフラグ(旗)に見立てて使用し、後続のバイトがある場合には最後のバイトを除いたすべてのバイトのビット7に1がセットされ、最後のバイトのビット7に0がセットされることによって数値の区切りを区別します。(下表参照)

●可変長数値表現の例●

表現する数値可変調表現16進数可変調表現2進数
00H00H0000000B
40H40H1000000B
7FH7FH1111111B
80H ※181H 00H0000001B 0000000B
2000HC0H 00H1000001B 0000000B
3FFFHFFH 7FH1111111B 1111111B
4000H81H 80H 00H0000001B 0000000B 0000000B
100000HC0H 80H 00H1000000B 0000000B 0000000B
1FFFFFHFFH FFH 7FH1111111B 1111111B 1111111B

















※1 ビット7はフラグとして使用されてしまうため、実際の数値表現は0〜6ビットで表現されることになります、従って1バイトで表現出来る上限は1111111H(7FH)となりますので80H以上の数値表現には2バイト以上のデータが必要になります。

 可変長数値表現は数値をメモリーに無駄無く記憶出来、数値の範囲を制限されることもありませんが、読み出し、書き込みの際ビット・シフト等の演算処理が必要になってきます。
 SMFでは一応数値の上限が決められています。その上限は最大4バイトです。4バイト(32ビット)で表現出来る数値は0FFFFFFFHとなります。SMFで扱う数値の内、最も大きな価を取る可能性があるのが時間情報であるデルタタイムですが、仮にテンポ500で1拍の分解能が96の設定の場合(実際にはありえませんが)、4バイトで表現出来る数値の長さは約4日間分に相当します。これはデルタタイムの長さとしては充分と言えると思います。


5ー2 チャンク

 SMFは幾つかのブロックに分かれて構成されています。このブロックをチャンクと呼びます。個々のチャンクにはそのチャンクの機能を示す「タイプ」とチャンク内のデータを示す「データ長」があります。
 SMFは基本的にヘッダー・チャンクとトラック・チャンクの2種類のチャンクで構成されています。ヘッダー・チャンクはSMF全体に関する情報を含み、トラック・チャンクは最大16チャンネル分の時間MIDIデータを含んでいます。マルチ・トラック、ソングの概念等は複数のチャンクを使うことで表現が可能です。
 SMFでは常に1つのヘッダー・チャンクで始まり、1つ以上のトラック・チャンクがそれに続く形で形成されています。
 SMFの構造を以下の図に示します。








































5ー2ー1 ヘッダ・チャンク

 SMFの最初にあるヘッダ・チャンクにはそのファイル中のデータ全体に関しての基本的な情報が記述されています。ヘッダ・チャンクは以下のデータ類が順番に並んで構成されています。

●チャンク・タイプ

 4つのアスキー文字で”MThd”と記述されています。「MT」は半角大文字で、「hd」は半角小文字です。

●データ長

 データ長にはこれに続くデータの長さが32ビット表現で記述されています。これにはチャンク・タイプとデータ長自身の数は含まれません。

●フォーマット

 ファイル全体の構造が記述されています。フォーマットの詳細は後述しますが、SMFには3つのフォーマットが存在します。
フォーマット0:1トラックで構成されています
フォーマット1:複数トラックで構成されています
フォーマット2:パターン・トラックを含んでいます

●トラック数

 後に続くトラック・チャンクの数が記述されています。フォーマット0のファイルでは当然1になっています。

●トラック数

 デルタタイムの意味を定義します。
 前述したように時間単位には2つのフォーマットがあり、1つは記譜上の時間である相対時間、もう一つはタイムコードに対応する絶対時間です。

5ー2ー2 SMFのフォーマット

 前述したようにSMFには3つのフォーマットがありますが、フォーマット2の使用例はほとんど聞いたことがありません。

●フォーマット0

 フォーマット0では、ヘッダ・チャンクとそれに続く1つのトラック・チャンクでSMFが構成されます。これは最も互換性の高いフォーマットと言え、複数トラックを持つプログラムでもこのフォーマットを作成出来ることが推奨されます。

●フォーマット1

 フォーマット1では、ヘッダ・チャンクとそれに続く1つ以上のトラック・チャンクでSMFが構成されます。複数のトラックを同時にサポートするプログラムにはこのフォーマットが適しています。

●フォーマット2

 フォーマット2では、フォーマット1同様にヘッダ・チャンクとそれに続く1つ以上のトラック・チャンクでSMFが構成されます。これは複数の独立したパターンをサポートしていますので、トラックごとに縦割りにして扱うプログラムにはこのフォーマットが適しています。

5ー2ー3 トラック・チャンク

 トラック・チャンクには実際の演奏データそのものが格納されています。個々のトラック・チャンクにはデルタタイム値を持つMIDIイベント、MIDI以外のイベントが連続して格納されています。トラック・チャンクのフォーマットはSMFすべてのフォーマット(0、1、2)で共通です。トラック・チャンクは以下の通りで、構造は単純です。タイミングを司るデルタタイムとイベントで構成され、イベントにはMIDIイベント、sysexイベント、メタ・イベントがあります。

●デルタタイム

 デルタタイムは可変長数値表現で記録され、次に続くイベントまでの時間を表します。デルタタイムは必ず付けられます、例えばトラックの最初のイベントがトラックの開始と同時に始まった場合や、2つのイベントが同時に表れた場合にはゼロのデルタタイムが使われます。
 デルタタイムはヘッダ・チャンクに記述されている1拍の分数で表現されます。

●MIDIイベント

 MIDIイベントは何らかのMIDIチャンネル・メッシージです。MIDIチャンネル・メッセージのステータス・バイトは、先行するイベントが同じステータスのチャンネル・メッセージであれば省略することが出来ます。

●sysexイベント

 sysexイベントはシステム・エクスクルーシブ・メッセージをストアするためのイベントです。

●メタ・イベント

 すべてのメタ・イベントはFFで始まり、1バイトのイベント・タイプ(128未満)と、可変長数値表現でストアされたデータ長、そしてデータそのものから構成されています。もしデータがなければデータ長は0となります。  メタ・イベントの種類を以下の表に示します。個々については後述します。

FF
0002ssssシーケンス番号
01lentextテキスト
02lentext著作権表示
03lentextシーケンス名/トラック名
04lentext楽器名
05lentext歌詞
06lentextマーカー
07lentextキュー・ポイント
2001MIDIチャンネルMIDIチャンネル・プリフィクス
2F00−−−−エンド・オブ・トラック
5103テンポセット・テンポ
5405時/分/秒/フレーム/ffSMPTEオフセット
5804分子/分母/cc/bb拍子
5902sf/mi調
7Flendataシーケンサー固有メタ・イベント
























●シーケンス番号 FF 00 02 ssss

 このイベントはシーケンスの番号を示すイベントです。トラックの最初のゼロではないデルタタイムの前で、更に送信可能なMIDIイベントより前に置いて使用されます。

●テキスト FF 01 len text

 任意の内容のテキストを記述出来ます。トラックの最初にトラック名と共にアレンジのコメント等の情報を入れるために使用することが考えられます。またトラックの途中で歌詞やキュー・ポイントのコメントを入れることが出来ます。
 互換性を得るためにはここで使用される文字はプリント可能なアスキー文字である必要があります。

●著作権表示 FF 02 len text

 プリント可能なアスキー文字による著作権を記述します。

●シーケンス名/トラック名 FF 03 len text

 フォーマット0のトラック内か、フォーマット1のファイルの最初のトラック内ではシーケンスの名前を記述し、それ意外はトラックの名前を記述します。

●楽器名 FF 04 len text

 トラック内で使用される楽器の種類を記述します。

●歌詞 FF 05 len text

 歌の歌詞を記述するためのイベントです。

●マーカー FF 06 len text

 通常フォーマット0のトラックかフォーマット1のファイルの最初のトラックに置かれます。シーケンス内のそのポイントの名前です。

●キュー・ポイント FF 07 len text

 楽譜上のそのポイントでどのようなイベントが発生するかを記述します。

●MIDIチャンネル・プリフィクス FF 20 01 cc

 このイベントに含まれているMIDIチャンネルをシステム・エクスクルーシブとメタ・イベントを含むすべてのイベントに対応させるために使用します。このチャンネルは次の通常のMIDIイベントまたはMIDIチャンネル・プリフィクス・メタ・イベントが来るまで有効となります。

●エンド・オブ・トラック FF 2F 00

 トラックの終わりには必ずこのイベントが置かれます。トラックの正確な終了点を指示し、正確なトラックの長さを規定するのもです。

●セット・テンポ FF 51 03 tttttt

 テンポを設定します。単位はマイクロ秒単位の4分音符の長さで、マイクロ秒単位のMIDIクロック周期の24倍です。時間あたりの拍数ではなく1拍あたりの時間でテンポを表現しています。従ってSMPTEタイムコードやMIDIタイムコードのような絶対時間を基準とした機器との長時間の正確な同期が可能になります。
 この分解能によって得られる精度は1分あたり120拍です。4分の曲を演奏した場合、曲の最後は500マイクロ秒以内におさまります。

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

 トラック・チャンクがスタートすべきSMPTE時間を示します。

●拍子 FF 58 04 nn dd cc bb

 拍子記号は4つの数字で表現されます。nnとddは記譜上の拍子記号の分子と分母を示します。
 ccパラメータはメトロノームの1カウントあたりのMIDIクロック数を表しています。bbパラメータはMIDIの4分音符(24MIDIクロック)中の32分音符の数を表しています。

●調 FF 59 02 sf mi

 調は2つの数値で表されます。sfはシャープまたはフラットの数で、フラットの場合はマイナスの数値を入れます。miはメジャー/マイナーを表します。

sf=−7:フラット7つ
sf=−2:フラット2つ
sf= 0:C調
sf= 2:シャープ2つ
sf= 7:シャープ7つ
mi= 0:長調キー
mi= 1:短調キー

●シーケンサー固有メタ・イベント FF 7F len data

 特定のシーケンサー特有の機能のためにこのイベントを使用することが出来ます。データの最初の1バイトまたは数バイトはメーカーIDとなります。これはエクスクルーシブと同様にこのイベントを使って何かを規定するのはメーカーによって異なります。


今回は少々難解であったかもしれませんがこれでお勉強はおしましです。
SMFに関しては、更に詳細を解説していると小冊子程の量になってしまします。
機会があれば今後徐々にお勉強していくことにしようと思います。