// ============================================================================================
// インクルードファイル
// ============================================================================================
#include <stdlib.h>
#include <string.h>
#include "audioeffectx.h"
// ============================================================================================
// 設計情報の記入
// ============================================================================================
#define MY_VST_INPUT_NUM 2 //入力数。モノラル入力=1、ステレオ入力=2
#define MY_VST_OUTPUT_NUM 2 //出力数。モノラル出力=1、ステレオ出力=2
#define MY_VST_UNIQUE_ID 'SMPL' //ユニークID
//公開する場合は以下URLで発行されたユニークIDを入力する。
//http://ygrabit.steinberg.de/~ygrabit/public_html/index.html
#define MY_VST_PRESET_NUM 1 //プリセットプログラムの数
#define MY_VST_PARAMETER_NUM 0 //パラメータの数
// ============================================================================================
// MIDI処理用の定義
// ============================================================================================
#define MIDIMSG_MAXNUM 255
struct MidiMessage
{
VstInt32 deltaFrames; //MIDIメッセージを処理するタイミング
unsigned char message; //MIDIメッセージ番号
unsigned char channel; //MIDIチャンネル
unsigned char data1; //MIDIデータ1
unsigned char data2; //MIDIデータ2
};
// ============================================================================================
// VSTの基本となるクラス
// ============================================================================================
class MyMidiSampleVST : public AudioEffectX
{
protected:
int midimsgnum; //受け取ったMIDIメッセージの数
MidiMessage midimsgbuf[MIDIMSG_MAXNUM]; //受け取ったMIDIメッセージを保管するバッファ
// ノイズのボリューム
float volume;
public:
MyMidiSampleVST (audioMasterCallback audioMaster);
// 音声信号を処理するメンバー関数
virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames);
// MIDIメッセージをホストアプリケーションから受け取るためのメンバー関数
VstInt32 processEvents (VstEvents* events);
};
// ============================================================================================
// このVSTのを生成するための関数
// ============================================================================================
AudioEffect* createEffectInstance (audioMasterCallback audioMaster)
{
//newでこのVSTを生成したポインタを返す
return new MyMidiSampleVST (audioMaster);
}
MyMidiSampleVST::MyMidiSampleVST (audioMasterCallback audioMaster)
: AudioEffectX (audioMaster, MY_VST_PRESET_NUM, MY_VST_PARAMETER_NUM)
{
//VSTの初期化を行う。
//以下の関数を呼び出して入力数、出力数等の情報を設定する。
//必ず呼び出さなければならない。
setNumInputs (MY_VST_INPUT_NUM); //入力数の設定
setNumOutputs (MY_VST_OUTPUT_NUM); //出力数の設定
setUniqueID (MY_VST_UNIQUE_ID); //ユニークIDの設定
isSynth (true); //このVSTがSynthかどうかのフラグを設定。
//Synthの場合…true、Effectorの場合…false
canProcessReplacing (); //このVSTが音声処理可能かどうかのフラグを設定。
//音声処理を行わないVSTはないので必ずこの関数を呼び出す。
//上記の関数を呼び出した後に初期化を行う
midimsgnum = 0;
memset(midimsgbuf, 0, sizeof(MidiMessage) * MIDIMSG_MAXNUM);
volume = 1.0f;
}
void MyMidiSampleVST::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames)
{
//入力、出力は2次元配列で渡される。
//入力は-1.0f~1.0fの間で渡される。
//出力は-1.0f~1.0fの間で書き込む必要がある。
//sampleFramesが処理するバッファのサイズ
float* outL = outputs[0]; //出力 左用
float* outR = outputs[1]; //出力 右用
// midieventlistの読み込み位置
int midimsg_cursol = 0;
for (int i = 0; i < sampleFrames; i++)
{
//ここで音声処理を行う。
// MIDIメッセージがあるか確認
if ( midimsgnum > 0)
{
// MIDIメッセージを処理するタイミングかどうかを確認する。
if( midimsgbuf[midimsg_cursol].deltaFrames <= i)
{
// MIDIメッセージがコントロールチェンジのボリューム変更(CC7)であった場合
if( midimsgbuf[midimsg_cursol].message == 0xB0
&& midimsgbuf[midimsg_cursol].data1 == 7)
{
volume = (float)( midimsgbuf[midimsg_cursol].data2) / 127.0f;
}
// midimsgbufからMIDIメッセージを読み出したので
// 読み込み位置を進め、MIDIメッセージの数を減らす
midimsgnum--;
midimsg_cursol++;
}
}
//出力バッファへ書き込む。
outL[i] = volume * (float)((rand() % 256) -128) / 255.0f;
outR[i] = volume * (float)((rand() % 256) -128) / 255.0f;
}
}
// MIDIメッセージを処理するメンバー関数
// processReplacing()の前に必ず1度だけ呼び出される。
//
VstInt32 MyMidiSampleVST::processEvents (VstEvents* events)
{
// MIDIのリストを初期化します。
midimsgnum = 0;
memset(midimsgbuf, 0, sizeof(MidiMessage) * MIDIMSG_MAXNUM);
// VSTイベントの回数だけループをまわす。
int loops = (events->numEvents);
for (int i = 0;i < loops; i++)
{
// 与えられたイベントがMIDIならばmidimsgbufにストックする
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++;
// MIDIメッセージのバッファがいっぱいの場合はループを打ち切る。
if (i >= MIDIMSG_MAXNUM)
{
break;
}
}
}
// 1を返しておく
return 1;
}