トップページ


MIDIメッセージ処理

MIDIメッセージにあわせて動作するVSTのサンプルである。
下記VSTはSynthとしてロードされ、常にノイズを発生させる。実行時は音量に注意してほしい。
ノイズのボリュームをMIDI CC7でコントロールできる。

サンプルコード全体

ソースコードのダウンロード→ここをクリック

  1. // ============================================================================================
  2. // インクルードファイル
  3. // ============================================================================================
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "audioeffectx.h"
  7.  
  8. // ============================================================================================
  9. // 設計情報の記入
  10. // ============================================================================================
  11. #define MY_VST_INPUT_NUM 2 //入力数。モノラル入力=1、ステレオ入力=2
  12. #define MY_VST_OUTPUT_NUM 2 //出力数。モノラル出力=1、ステレオ出力=2
  13.  
  14. #define MY_VST_UNIQUE_ID 'SMPL' //ユニークID
  15. //公開する場合は以下URLで発行されたユニークIDを入力する。
  16. //http://ygrabit.steinberg.de/~ygrabit/public_html/index.html
  17.  
  18. #define MY_VST_PRESET_NUM 1 //プリセットプログラムの数
  19. #define MY_VST_PARAMETER_NUM 0 //パラメータの数
  20.  
  21. // ============================================================================================
  22. // MIDI処理用の定義
  23. // ============================================================================================
  24. #define MIDIMSG_MAXNUM 255
  25.  
  26. struct MidiMessage
  27. {
  28. VstInt32 deltaFrames; //MIDIメッセージを処理するタイミング
  29. unsigned char message; //MIDIメッセージ番号
  30. unsigned char channel; //MIDIチャンネル
  31. unsigned char data1; //MIDIデータ1
  32. unsigned char data2; //MIDIデータ2
  33. };
  34.  
  35. // ============================================================================================
  36. // VSTの基本となるクラス
  37. // ============================================================================================
  38. class MyMidiSampleVST : public AudioEffectX
  39. {
  40. protected:
  41. int midimsgnum; //受け取ったMIDIメッセージの数
  42. MidiMessage midimsgbuf[MIDIMSG_MAXNUM]; //受け取ったMIDIメッセージを保管するバッファ
  43.  
  44. // ノイズのボリューム
  45. float volume;
  46. public:
  47. MyMidiSampleVST (audioMasterCallback audioMaster);
  48.  
  49. // 音声信号を処理するメンバー関数
  50. virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames);
  51.  
  52. // MIDIメッセージをホストアプリケーションから受け取るためのメンバー関数
  53. VstInt32 processEvents (VstEvents* events);
  54. };
  55.  
  56.  
  57. // ============================================================================================
  58. // このVSTのを生成するための関数
  59. // ============================================================================================
  60. AudioEffect* createEffectInstance (audioMasterCallback audioMaster)
  61. {
  62. //newでこのVSTを生成したポインタを返す
  63. return new MyMidiSampleVST (audioMaster);
  64. }
  65.  
  66. MyMidiSampleVST::MyMidiSampleVST (audioMasterCallback audioMaster)
  67. : AudioEffectX (audioMaster, MY_VST_PRESET_NUM, MY_VST_PARAMETER_NUM)
  68. {
  69. //VSTの初期化を行う。
  70.  
  71. //以下の関数を呼び出して入力数、出力数等の情報を設定する。
  72. //必ず呼び出さなければならない。
  73. setNumInputs (MY_VST_INPUT_NUM); //入力数の設定
  74. setNumOutputs (MY_VST_OUTPUT_NUM); //出力数の設定
  75. setUniqueID (MY_VST_UNIQUE_ID); //ユニークIDの設定
  76.  
  77. isSynth (true); //このVSTがSynthかどうかのフラグを設定。
  78. //Synthの場合…true、Effectorの場合…false
  79.  
  80. canProcessReplacing (); //このVSTが音声処理可能かどうかのフラグを設定。
  81. //音声処理を行わないVSTはないので必ずこの関数を呼び出す。
  82.  
  83. //上記の関数を呼び出した後に初期化を行う
  84. midimsgnum = 0;
  85. memset(midimsgbuf, 0, sizeof(MidiMessage) * MIDIMSG_MAXNUM);
  86.  
  87. volume = 1.0f;
  88. }
  89.  
  90. void MyMidiSampleVST::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames)
  91. {
  92. //入力、出力は2次元配列で渡される。
  93. //入力は-1.0f~1.0fの間で渡される。
  94. //出力は-1.0f~1.0fの間で書き込む必要がある。
  95. //sampleFramesが処理するバッファのサイズ
  96. float* outL = outputs[0]; //出力 左用
  97. float* outR = outputs[1]; //出力 右用
  98.  
  99. // midieventlistの読み込み位置
  100. int midimsg_cursol = 0;
  101.  
  102. for (int i = 0; i < sampleFrames; i++)
  103. {
  104. //ここで音声処理を行う。
  105.  
  106. // MIDIメッセージがあるか確認
  107. if ( midimsgnum > 0)
  108. {
  109. // MIDIメッセージを処理するタイミングかどうかを確認する。
  110. if( midimsgbuf[midimsg_cursol].deltaFrames <= i)
  111. {
  112. // MIDIメッセージがコントロールチェンジのボリューム変更(CC7)であった場合
  113. if( midimsgbuf[midimsg_cursol].message == 0xB0
  114. && midimsgbuf[midimsg_cursol].data1 == 7)
  115. {
  116. volume = (float)( midimsgbuf[midimsg_cursol].data2) / 127.0f;
  117. }
  118.  
  119. // midimsgbufからMIDIメッセージを読み出したので
  120. // 読み込み位置を進め、MIDIメッセージの数を減らす
  121. midimsgnum--;
  122. midimsg_cursol++;
  123. }
  124. }
  125.  
  126. //出力バッファへ書き込む。
  127. outL[i] = volume * (float)((rand() % 256) -128) / 255.0f;
  128. outR[i] = volume * (float)((rand() % 256) -128) / 255.0f;
  129. }
  130. }
  131.  
  132. // MIDIメッセージを処理するメンバー関数
  133. // processReplacing()の前に必ず1度だけ呼び出される。
  134. //
  135. VstInt32 MyMidiSampleVST::processEvents (VstEvents* events)
  136. {
  137. // MIDIのリストを初期化します。
  138. midimsgnum = 0;
  139. memset(midimsgbuf, 0, sizeof(MidiMessage) * MIDIMSG_MAXNUM);
  140.  
  141. // VSTイベントの回数だけループをまわす。
  142. int loops = (events->numEvents);
  143. for (int i = 0;i < loops; i++)
  144. {
  145. // 与えられたイベントがMIDIならばmidimsgbufにストックする
  146. if ((events->events[i])->type == kVstMidiType)
  147. {
  148. VstMidiEvent *midievent = (VstMidiEvent*)(events->events[i]);
  149.  
  150. midimsgbuf[midimsgnum].deltaFrames = midievent->deltaFrames;
  151. midimsgbuf[midimsgnum].message = midievent->midiData[0] & 0xF0; // MIDIメッセージ
  152. midimsgbuf[midimsgnum].channel = midievent->midiData[0] & 0x0F; // MIDIチャンネル
  153. midimsgbuf[midimsgnum].data1 = midievent->midiData[1]; // MIDIデータ1
  154. midimsgbuf[midimsgnum].data2 = midievent->midiData[2]; // MIDIデータ2
  155. midimsgnum++;
  156.  
  157. // MIDIメッセージのバッファがいっぱいの場合はループを打ち切る。
  158. if (i >= MIDIMSG_MAXNUM)
  159. {
  160. break;
  161. }
  162. }
  163. }
  164.  
  165. // 1を返しておく
  166. return 1;
  167. }





同一カテゴリの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日 02:02