読者です 読者をやめる 読者になる 読者になる

S.F. Page

Programming,Music,etc...

MIDIメッセージ

Windows マルチメディア STed2 C++ Audio

昨日もほとんどプログラムを書かずに終わってしまった。 MIDIメッセージをどうC++のクラスで表現するかを考えていて、なかなか答えがでない。 とりあえずはメッセージの種類 = 型と考えて定義はしてみている。

struct ID
{
enum {
ノートオン = 0x90,
ノートオフ = 0x80,
ポリフォニックキープレッシャ = 0xa0,
コントロールチェンジ = 0xb0,
プログラムチェンジ = 0xc0,
チャンネルプレッシャ = 0xd0,
ピッチベンド = 0xe0,
システムエクスクルーシブ = 0xf0,
クォータフレーム = 0xf1,
ソングポジションポインタ = 0xf2,
ソングセレクト = 0xf3,
チューンリクエスト = 0xf6,
エンドオブエクスクルーシブ = 0xf7,
タイミングクロック = 0xf8,
MIDIクロックスタート = 0xfa,
MIDIクロックコンティニュー = 0xfb,
MIDIクロックストップ = 0xfc,
アクティブセンシング = 0xfe,
システムリセット = 0xff
};
};
/** ノート・オン */
struct ノートオン
{
boost::uint8_t ノート;
boost::uint8_t ベロシティ;
static const boost::uint16_t ID = ID::ノートオン;
};
/** ノート・オフ */
struct ノートオフ
{
boost::uint8_t ノート;
boost::uint8_t ベロシティ;
static const boost::uint16_t ID = ID::ノートオフ;
};

IDはMIDIイベント番号のenumである。名前の衝突がないようににenum hackしている。各MIDIメッセージイベントクラス(struct)に静的に持たせてMIDIメッセージ番号と対応させている。

タイムスタンプのみをメンバに持つ基底クラスを継承して、イベントを受信したときに各イベントを型に置き換えてコンテナに保存しようかなと思っている。今悩んでいるのはメソッドをどうしようかなと考えている。クラスにはあまりメソッドを持たせず、フリー関数で対応しようかと考えている。しかしクラスにメソッドを持たせた方が良い条件というのが明確に自分の頭の中にないので悩むのである。

メッセージを受信して、それをメッセージごとに条件分岐してクラスに変換する部分は巨大なswitch文を 書かなくてはならないがここもなんかこうスマートに分かりやすく書けないかな?とか考えている。
こうなんか型をうまくいじくりまわしてコンパイルタイムでかっこ良くコード生成してこうなんかすごい感じでパフォーマンスが良くて短いコードにならないかなと妄想しているが、もちろんC++のエキスパートでないので何も浮かばないのである。

MIDIバイブル〈1〉MIDI1.0規格 基礎編