VSTe 何も音響処理をしない入力をそのまま出力する処理
概要
まずは、基礎として何もしないエフェクト処理を作ってみたいと思います。こつこつ手作業版のプロジェクトを仕上げていくイメージですが、最初の方は自動生成したVSTプロジェクトでは既にもう準備されている部分になるので、自動生成されたプロジェクトの構造とも見比べながらやってみたいと思います。
- 1.自動生成されたプロジェクトでも読み込まれているdllmain.cppを取り込む作業をします。
- ソリューションエクスプローラのプロジェクト名を右クリックして表示されるメニューから[追加]-[既存の項目]を選択するか[Shift]+[Alt]+[A]キーを押します。
- VSTのSDKの中のC:¥SDK¥VST_SDK¥vst3sdk¥public.sdk¥source¥main¥dllmain.cppファイルを選択します。
- このファイルは変更を加えませんが、エントリポイント(プログラムが起動したときに最初に呼び出される関数)となる。
- BOOL WINAPI DllMain (HINSTANCE hInst, DWORD dwReason, LPVOID /*lpvReserved*/)
- という関数を含んでいます。開始関数は自分で作るのではなく、配布されているSDKセットの関数を取り込むのが普通なようです。dllmain.cppとは長い付き合いになりそうですね。
- 2.ヘッダファイルとソースファイルの組み合わせを追加します。
- ソリューションエクスプローラのプロジェクト名を右クリックして表示されるメニューから[追加]-[新しい項目]を選択するか[Ctrl]+[Shift]+[A]キーを押します。
- 表示されるダイアログで、myvst.h と myvst.cpp としましょうか?好きなファイル名でいいです。自動生成版では4つのヘッダファイルと3つのソースファイルに分割して記述されていて、
- $(Prefix)cids.h
- $(Prefix)controller.h
- $(Prefix)processor.h
- version.h
- $(Prefix)controller.cpp
- $(Prefix)processor.cpp
- $(Prefix)entry.cpp
に記述されます。コツコツ版ではmyvst.hとmyvst.cppというファイル名に集約することにしたいと思います。
- 3.myvst.h に以下のようなコードを記述します。
#pragma once
#include "pluginterfaces\base\funknown.h"
#include "public.sdk/source/vst/vstaudioeffect.h"
#include "public.sdk/source/vst/vsteditcontroller.h"
#include "public.sdk/source/main/pluginfactory.h"
namespace Steinberg {
namespace Vst {
#define MYVST_VENDOR "VST Company" // VSTを提供する組織名
#define MYVST_URL "https://wiki.yo-net.jp/" // WebサイトのURL
#define MYVST_EMAIL "mailto:xxxx@yo-net.jp" // メールアドレス
#define MYVST_VSTNAME "MyVST Name" // VSTの名前
#define MYVST_VERSION "0" // VSTのバージョン
#define MYVST_SUBCATEGORIES Vst::PlugType::kFx // VSTのサブカテゴリ
static const FUID ProcessorUID(0x1923FE24, 0x425D4929, 0xB5758504, 0x86D2D555);
static const FUID ControllerUID(0xFA81F9F7, 0x7968462D, 0xB9396332, 0x343FB4D1);
class MyVSTProcessor : public AudioEffect
{
public:
MyVSTProcessor();
tresult PLUGIN_API initialize(FUnknown* context) SMTG_OVERRIDE;
tresult PLUGIN_API process(ProcessData& data) SMTG_OVERRIDE;
static FUnknown* createInstance(void*) { return (IAudioProcessor*)new MyVSTProcessor(); }
};
class MyVSTController : public EditController
{
public:
tresult PLUGIN_API initialize(FUnknown* context) SMTG_OVERRIDE;
static FUnknown* createInstance(void*) { return (IEditController*)new MyVSTController(); }
};
}
}
- 4.myvst.cpp に以下のようなコードを記述します。
using namespace Steinberg;
using namespace Steinberg::Vst;
//------------------------------------------------------------------------
// VST Plug-in Entry
//------------------------------------------------------------------------
// Windows: do not forget to include a .def file in your project to export
// GetPluginFactory function!
//------------------------------------------------------------------------
BEGIN_FACTORY_DEF ("VST Company",
"https://wiki.yo-net.jp",
"mailto:xxxx@yo-net.jp")
//---First Plug-in included in this factory-------
// its kVstAudioEffectClass component
DEF_CLASS2 (INLINE_UID_FROM_FUID(ProcessorUID),
PClassInfo::kManyInstances, // cardinality
kVstAudioEffectClass, // the component category (do not changed this)
MYVST_VSTNAME, // here the Plug-in name (to be changed)
Vst::kDistributable, // means that component and controller could be distributed on different computers
MyVSTVSTCategory, // Subcategory for this Plug-in (to be changed)
MYVST_VERSION, // Plug-in version (to be changed)
kVstVersionString, // the VST 3 SDK version (do not changed this, use always this define)
MyVSTProcessor::createInstance) // function pointer called when this component should be instantiated
// its kVstComponentControllerClass component
DEF_CLASS2 (INLINE_UID_FROM_FUID (ControllerUID),
PClassInfo::kManyInstances, // cardinality
kVstComponentControllerClass,// the Controller category (do not changed this)
MYVST_VSTNAME "Controller", // controller name (could be the same than component name)
0, // not used here
"", // not used here
MYVST_VERSION, // Plug-in version (to be changed)
kVstVersionString, // the VST 3 SDK version (do not changed this, use always this define)
MyVSTController::createInstance)// function pointer called when this component should be instantiated
//----for others Plug-ins contained in this factory, put like for the first Plug-in different DEF_CLASS2---
END_FACTORY
MyVSTProcessor::MyVSTProcessor()
{
setControllerClass(ControllerUID);
}
tresult PLUGIN_API MyVSTProcessor::initialize(FUnknown* context)
{
tresult result = AudioEffect::initialize(context);
if (result == kResultTrue)
{
addAudioInput(STR16("AudioInput"), SpeakerArr::kStereo);
addAudioOutput(STR16("AudioOutput"), SpeakerArr::kStereo);
}
return result;
}
tresult PLUGIN_API MyVSTProcessor::process(ProcessData& data)
{
if (data.numInputs != 1 || data.numOutputs != 1)
{
return kResultTrue;
}
if (data.inputs[0].numChannels != 2 || data.outputs[0].numChannels != 2)
{
return kResultTrue;
}
Sample32* inL = data.inputs[0].channelBuffers32[0];
Sample32* inR = data.inputs[0].channelBuffers32[1];
Sample32* outL = data.outputs[0].channelBuffers32[0];
Sample32* outR = data.outputs[0].channelBuffers32[1];
for (int32 i = 0; i < data.numSamples; i++)
{
outL[i] = inL[i];
outR[i] = inR[i];
}
return kResultTrue;
}
result PLUGIN_API MyVSTController::initialize(FUnknown* context)
{
tresult result = EditController::initialize(context);
return result;
}