VSTe 何も音響処理をしない入力をそのまま出力する処理
プラグイン VSTに戻る。
概要
まずは、基礎として何もしないエフェクト処理を作ってみたいと思います。こつこつ手作業版のプロジェクトを仕上げていくイメージですが、最初の方は自動生成した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(0xA185FDD5, 0xDA405CBE, 0xB54639A5, 0x0DD136ED);
static const FUID ControllerUID(0x68F6FA83, 0x229451BE, 0x98647D8E, 0x25C4A242);
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(); }
};
}
}
static const FUID ProcessorUID(0xA185FDD5, 0xDA405CBE, 0xB54639A5, 0x0DD136ED); static const FUID ControllerUID(0x68F6FA83, 0x229451BE, 0x98647D8E, 0x25C4A242);
- 上記の部分は独自のIDを生成する必要があります。人の真似をすると、そのVSTが使えなくなるといった迷惑がかかります。
- 生成するには、VisualStudioのメニューの[ツール]-[GUIDの作成]で起動されるツールを使って、[コピー]ボタンを押してIDを得ることが出来ます。
- {5A927A38-9B1C-46B9-8563-23473D9C8C62}のような形式ですが、8桁ずつの区切りとして{5A927A38-9B1C46B9-85632347-3D9C8C62}のようなIDを得ます。これに4つの引数となるような0xを先頭に付与した(0x5A927A38, 0x9B1C46B9, 0x85632347, 0x3D9C8C62)のように置き換える手順で得られるのがFUIDです。
- 二つ目のIDを続けて得るには[新規GUID]ボタンを押します。そしてまた[コピー]ボタンです。1秒間に5000万回生成しても重複することはないとされています。
#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のサブカテゴリ
- この部分も独自の値を設定した方がよいでしょう。嘘をつくことになります。重複しても迷惑はあまりかからないでしょう。ただし、問い合わせの連絡がよそに行ってしまうという意味では、URLとEMAILは他人の物は使わないことは重要です。これはVSTホスト側でも取得できる値ですのでDAWによっては、この情報が閲覧できることになります。
- 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;
}
- 5.これで、一旦ビルドできます。何もしない空気のようなVSTeです。ちな、最近のバージョンから必要になっているsdk_common.libを入力ライブラリの追加で忘れていると
- LNK2001 外部シンボル "public: static class Steinberg::FUID const Steinberg::IPlugView::iid" (?iid@IPlugView@Steinberg@@2VFUID@2@B) は未解決です MyVstProject C:\任意のディレクトリ\sdk.lib(vsteditcontroller.obj) 1
というエラーが表示されます。FUIDの関数の中身がsdk_common.libの中に定義されているからだと思われます。sdk.libからsdk_common.libに移ったという感じでしょうか。