トップページ


MIDIメッセージをホストアプリケーションから受け取る関数

MIDIメッセージをホストアプリケーションから受け取るにはprocessEvents()関数を利用する。

processEvents()関数
VstInt32  processEvents (VstEvents* events)

戻り値と引数については以下のとおりである。
戻り値(型) 説明
VstInt32 戻り値についてはホストアプリケーションで無視される。
ただし、念のため1を返すようにするとよい。

引数 説明
VstEvents* events イベントを保持しているVstEvents型変数(後述)へのポインタ

processEvents()関数はMIDIメッセージだけを受け取る関数ではなく、VSTに関するホストアプリケーションからのイベントをすべて受け取る関数となっている。
ただし、実装されているメッセージは現在(2010年11月)のところMIDIに関する以下の2つだけである。

  • MIDIメッセージ
  • MIDI System Exclusiveメッセージ

processEvents()関数との関係

ホストアプリケーションはprocessReplacing()関数を呼び出す前に必ず1度だけprocessEvents()関数呼び出し、イベントをVSTに通知する。
また、processEvents()関数で渡されるイベントは直後に呼び出すprocessReplacing()関数に関連するイベントのみとなっている。

ホストアプリケーション側の処理のイメージとしては以下のような感じである。
【ホストアプリケーションの動作】
①processEvents()関数呼び出し
     ↓
②processReplacing()関数呼び出し
     ↓
③いろいろ処理
     ↓
④processEvents()関数呼び出し
     ↓
⑤processReplacing()関数呼び出し
     ↓
⑥いろいろ処理
     ↓
⑦processEvents()関数呼び出し
     ↓
⑧processReplacing()関数呼び出し
     ↓
     :
     :
ホストアプリケーションは①でprocessEvents()関数を呼び出した際に、②processReplacing()関数に関連するイベントのみをVSTに渡す。
(ホストアプリケーションは②に無関係のイベント(⑤や⑧に関連するイベント)については渡してはいけない。)

サンプルコード


processEvents()関数でMIDIメッセージを保存するサンプルコードは以下のとおり。
  1. VstInt32 MyMidiSampleVST::processEvents (VstEvents* events)
  2. {
  3. // MIDIのリストを初期化します。
  4. midimsgnum = 0;
  5. memset(midimsgbuf, 0, sizeof(MidiMessage) * MIDIMSG_MAXNUM);
  6.  
  7. // VSTイベントの回数だけループをまわす。
  8. int loops = (events->numEvents);
  9. for (int i = 0;i < loops; i++)
  10. {
  11. // 与えられたイベントがMIDIならばmidimsgbufにストックする
  12. if ((events->events[i])->type == kVstMidiType)
  13. {
  14. VstMidiEvent *midievent = (VstMidiEvent*)(events->events[i]);
  15.  
  16. midimsgbuf[midimsgnum].deltaFrames = midievent->deltaFrames;
  17. midimsgbuf[midimsgnum].message = midievent->midiData[0] & 0xF0; // MIDIメッセージ
  18. midimsgbuf[midimsgnum].channel = midievent->midiData[0] & 0x0F; // MIDIチャンネル
  19. midimsgbuf[midimsgnum].data1 = midievent->midiData[1]; // MIDIデータ1
  20. midimsgbuf[midimsgnum].data2 = midievent->midiData[2]; // MIDIデータ2
  21. midimsgnum++;
  22.  
  23. // MIDIメッセージのバッファがいっぱいの場合はループを打ち切る。
  24. if (i >= MIDIMSG_MAXNUM)
  25. {
  26. break;
  27. }
  28. }
  29. }
  30.  
  31. // 1を返しておく
  32. return 1;
  33. }

サンプルコードの解説

まず引数のVstEvents構造体は以下のように定義されている。
変数 説明
numEvents VstInt32 VSTイベントの数。
reserved VstIntPtr 使われていない変数。0で固定
events [2] VstEvent * VSTイベントへのポインタ。numEvents分だけVSTイベントが格納されている。

ホストアプリケーションからのVSTイベント自体は上記のVstEvents構造体のVstEvent * events[]に格納されている。
VstEvent構造体は以下のように定義されている。
変数 説明
type VstInt32 VSTイベントのタイプ。実装されているタイプは以下の2つのみ。
kVstMidiType…data[ ]に保存されているデータがMIDIメッセージであることを示す
kVstSysExType…data[ ]に保存されているデータがMIDI System Exclusiveメッセージであることを示す
byteSize VstInt32 VstEvent構造体のtypeとbyteSizeを除いたバイト数。24固定。
deltaFrames VstInt32 processReplacing()関数内でMIDIメッセージの処理タイミング。
0~sampleFramesの範囲の値を持つ。
flags VstInt32 使われていない変数。
data[16] char 実際のVSTイベントデータ。typeよって内容が変わる。

サンプルコードでは、最初にMIDIメッセージを保存するバッファを初期化している。(3~5行目)
midimsgnum = 0;
memset(midimsgbuf, 0, sizeof(MidiMessage) * MIDIMSG_MAXNUM); 

次にVSTイベントの数だけ処理するループを作成している。(8~29行目)
// VSTイベントの回数だけループをまわす。
int loops = (events->numEvents);
for (int i = 0;i < loops; i++)
{
	:
	:
} 

ループの中で与えられたVSTイベントがMIDIメッセージか確認し、MIDIメッセージならばバッファに保存する(12~28行目)
バッファに保存する際、VstEvent構造体のままでは扱いにくいため、VstMidiEvent構造体(後述)に型変換している。
if ((events->events[i])->type == kVstMidiType)
{
	VstMidiEvent *midievent = (VstMidiEvent*)(events->events[i]);
 
	midimsgbuf[midimsgnum].deltaFrames = midievent->deltaFrames;
	midimsgbuf[midimsgnum].message = midievent->midiData[0] & 0xF0; // MIDIメッセージ
	midimsgbuf[midimsgnum].channel = midievent->midiData[0] & 0x0F; // MIDIチャンネル
	midimsgbuf[midimsgnum].data1   = midievent->midiData[1]; // MIDIデータ1
	midimsgbuf[midimsgnum].data2   = midievent->midiData[2]; // MIDIデータ2
	midimsgnum++;
} 

VstMidiEvent構造体については以下のように定義されている。
変数 説明
type VstInt32 VstEvent構造体と同じ。
byteSize VstInt32 VstEvent構造体と同じ。
deltaFrames VstInt32 VstEvent構造体と同じ。
flags VstInt32 使われていない変数。
noteLength VstInt32 用途不明
noteOffset VstInt32 用途不明
midiData [4] char MIDIメッセージ。
midiData[0]…MIDIステータス(メッセージ)とMIDIチャンネルが入っている。
midiData[1]…MIDIメッセージのデータ1
midiData[2]…MIDIメッセージのデータ2
midiData[3]…将来的な拡張のため予約。0が入っている。
detune char 用途不明。-64~+63の値が入っている。
noteOffVelocity char 用途不明。0~127の値が入っている。
reserved1 char 将来的な拡張のため予約。0が入っている
reserved2 char 将来的な拡張のため予約。0が入っている





同一カテゴリのTips


項目 No. 概要
MIDIメッセージ処理 No.1 MIDIメッセージ処理で最小構成の自作VSTに追加する変数・関数
No.2 VSTの初期化とMIDIメッセージ処理関連の変数の初期化
No.3 ホストアプリケーションからMIDIメッセージを受け取る方法
No.4 MIDIメッセージをprocessReplacing()関数中で処理する方法
No.5 MIDIメッセージ処理で作成したVSTのサンプルソースコード全体(暫定版)


javascript plugin Error : このプラグインで利用できない命令または文字列が入っています。
最終更新:2013年08月06日 01:53