EternalWindows
MIDI / メタイベント

メタイベントはMIDIデバイスに送信するためのものではなく、 シーケンサーソフトに対する補足情報です。 つまり、メッセージとしてMIDIデバイスに送信されることはありません。 メタイベントとして格納される情報の種類を理解しておけば、 著作権情報やトラックに設定された名前などを確認することができます。 次に、メタイベントの一覧を示します。

種類 タイプ データ長
シーケンス番号 0x00 2
テキスト 0x01 n
著作権表示 0x02 n
トラック名 0x03 n
楽器名 0x04 n
歌詞 0x05 n
マーカ 0x06 n
キューポイント 0x07 n
プログラム名 0x08 n
デバイス名 0x09 n
チャンネルプリフィックス 0x20 1
ポート 0x21 1
エンドオブトラック 0x2F 0
セットテンポ 0x51 3
SMPTEオフセット 0x54 5
拍子 0x58 4
調号 0x59 2
シーケンサー固有 0x7F n

メタイベントは、タイプの値によって種類が分かれ、 データの長さが異なります。 基本的には、データ長に指定された値だけ読み取ればよいのですが、 0x2Fであるエンドオブトラックについては必ず確認する必要があります。 これは、トラックの終端を示すもので、 これを発見することでトラックから抜けることになります。 また、0x51のセットテンポはデルタタイムを秒単位に変換するために必要になるため、 後で参照することになります。 メタイベントの格納形式は次のようになります。

データ内容 バイト数 データ値
ステータスバイト 1byte 0xFF
タイプ 1byte メタイベントの種類を表す値
データ長 1〜4byte n
データ nbyte ...

メタイベントのデータ長が1〜4byteであることに注意してください。 この要領はデルタタイムと似ていますが、実際その通りです。 つまり、MSBに次に存在バイトもデータ長であるかどうかを示す値が格納されています。 よって、以前に取り上げたReadDeltaという関数でデータ長を取得することができます。 次に、メタイベントを取得するコードを示します。

else if (lpEvent->state == 0xFF) { // メタイベント
	DWORD dw;
	DWORD tmp;
	
	mmioRead(hmmio, (HPSTR)&lpEvent->type, sizeof(BYTE)); // typeの取得

	dw = (DWORD)-1;

	switch (lpEvent->type) {

	case 0x00: dw = 2; break;
	case 0x01:
	case 0x02:
	case 0x03:
	case 0x04:
	case 0x05:
	case 0x06:
	case 0x07:
	case 0x08:
	case 0x09: break;
	case 0x20: dw = 1; break; 
	case 0x21: dw = 1; break; 
	case 0x2F: dw = 0; break; // エンドオブトラック
	case 0x51: dw = 3; break; // セットテンポ
	case 0x54: dw = 5; break;
	case 0x58: dw = 4; break;
	case 0x59: dw = 2; break;
	case 0x7F: break;

	default:
		MessageBox(NULL, TEXT("存在しないメタイベントです。"), NULL, MB_ICONWARNING);
		return FALSE;

	}
	
	tmp = dw;

	if (dw != -1) { // データ長は固定か
		ReadDelta(hmmio, &dw);
		if (dw != tmp) {
			MessageBox(NULL, TEXT("固定長メタイベントのデータ長が不正です。"), NULL, MB_ICONWARNING);
			return FALSE;
		}
	}
	else 
		ReadDelta(hmmio, &dw); // 任意のデータ長を取得

	lpEvent->nData  = dw;
	lpEvent->lpData = (LPBYTE)Alloc(lpEvent->nData);
	mmioRead(hmmio, (HPSTR)lpEvent->lpData, lpEvent->nData); // データの取得
	
	if (lpEvent->type == 0x2F) // トラックの終端
		return TRUE;
}

まず、ステータスバイトがメタイベントを示す0xFFであるかを確認し、 その次にタイプを取得します。 タイプによってデータ長が固定である場合と可変の場合がありますが、 固定である場合はdwにその値を保存します。 そして、ReadDeltaでデータ長を取得し、データ長が固定であった場合は、 取得したデータ長が固定長と一致するかどうかを確認します。 その後、取得したデータ長だけデータを取得し、 タイプがエンドオブトラックである場合は、トラックから抜けることになります。


戻る