VST3プラグイン開発03 – はじめてのVST3プラグイン

はじめてのVST3プラグイン

前回はVST3のプラグインを作成する際のVisual Studioのプロジェクト作成について記載いたしましたので、今回はさっそくVST3プラグインを作成します。

今回作成するプラグインは下記のとおりです。

  • パラメーターはなし
  • 入力をそのまま出力する
  • 入力バス、出力バスは1つで、共にステレオ(2ch)

上記にある「バス」についての概念は次回あたりで記載できればと思います。

このVST3プラグインのサンプルソースファイルはこちらからダウンロードできます→vst3dev_20210403
ZIPファイルの中の「vst3dev01_はじめてのVST3プラグイン」フォルダが今回のサンプルソースファイルになります。

コンパイル・ビルドの方法は簡単にこちらでご説明しております。ご参考までに。→サンプルソースファイルのビルド方法

はじめてのVST3プラグイン作成の流れ

はじめてのVST3プラグインでは、主に下記の3つを実装します。

  • FUIDの作成
  • プラグイン情報の設定
  • 音声処理クラスの作成

ここで作成するはじめてのVST3プラグインのサンプルは実行時に一部のホストアプリケーション(Sonar、VSTHost等のDAW)でエラー(例外)が発生する場合がございます。
エラー発生の際は「VST3プラグインのパラメーター実装方法1」まで進めていただき、再度試していただきますようお願いします。

FUIDの作成

VST3プラグイン開発ではFUIDというIDが必要となります。

VST3はMicrosoftのCOM(Component Object Model)と呼ばれる仕様(規格)を参考に設計されており、このCOMではグローバル一意識別子(GUID)と呼ばれるIDをクラスに関連付けます。
VST3でもCOMと同様にFUIDと呼ばれるIDを音声処理クラスと次々回するパラメーター操作クラスに関連付ける決まりになっています。

FUIDはGUID生成ツールを使用して取得する必要があります。
Visual StudioにもGUID生成ツールが付属しているため、下記の手順で取得します。

  1. Visual Studioのメニューから「ツール」→「GUIDの作成」を選択。
  2. 「4.レジストリ形式」にチェックを入れ「コピー」ボタンを押す
  3. クリップボードにGUIDがコピーされるので、メモ帳などに貼り付ける。


※GUID生成ツールを立ち上げるか、「新規GUID」ボタンを押すと、新しいGUIDが生成されます。

取得したFUIDはグローバルのFUIDクラスに設定します。取得したGUIDとFUIDは区切りが異なるため、下記のようにGUIDを8桁ずつ区切ってFUIDクラスの引数にします。

  【例】
  発行されたGUIDが
    {01234567-89AB-CDEF-0123-456789ABCDEF}
  の場合、FUIDクラスの引数には
    FUID ProcessorUID (0x01234567, 0x89ABCDEF, 0x01234567, 0x89ABCDEF);
  と8桁ずつ区切ったものを指定する。

実際のコードは下記のとおりです。(VST3の開発では名前空間を指定する必要がありますので忘れないようご注意ください。)

【myvst3fuid.h】

VST3プラグインを作成する際にFUIDは使いまわさないように注意してください。
同じFUIDのVST3プラグインが複数あると作ったVST3プラグインを正常に認識してくれない場合があります。

プラグイン情報の設定

次にVST3プラグイン情報の設定を行います。

ここで設定する内容はホストアプリケーション(DAWなど)が音声処理クラスパラメーター操作クラスを呼び出すための情報になります。
一部の内容はホストアプリケーション(DAWなど)に表示されることがあります。

VST3プラグイン情報はマクロを使って下記のように定義・作成します。
(製作者情報などは#define定義していますが、BEGIN_FACTORY_DEFマクロやDEF_CLASS2に直接指定しても問題ありません。)

【factory.cpp】

それぞれのマクロの概要については下記の通りです。

  • BEGIN_FACTORY_DEFマクロ
  • 概要 VST3プラグイン情報をホストアプリケーションに知らせるためのクラス(CPluginFactoryクラス)を作成するマクロ。
    このマクロの後にDEF_CLASS2マクロを使用して音声処理クラス等の情報を設定する。
    最後はEND_FACTORYマクロを呼び出す。
    引数

    1つ目 VST3プラグイン製作者の名前。
    2つ目 VST3プラグインに関するのURL。
    3つ目 VST3プラグインに連絡先eMailアドレス。
  • DEF_CLASS2マクロ
  • 概要 VST3プラグイン内にある音声処理クラス・パラメーター操作クラスの情報を設定するマクロ。
    BEGIN_FACTORY_DEFマクロとEND_FACTORYマクロの中で呼び出す。
    引数

    1つ目 音声処理クラス・パラメーター操作クラスのFUID。
    (事前に設定したFUIDクラスをINLINE_UID_FROM_FUIDマクロを使って設定する。)
    2つ目 PClassInfo::kManyInstancesを指定する。(現時点ではこれ以外指定できない。)
    3つ目 DEF_CLASS2マクロで記載しているクラスの種類。
    音声処理クラスの場合…kVstAudioEffectClass、パラメーター操作クラスの場合…kVstComponentControllerClassを指定する。
    4つ目 VST3プラグインの名前。
    5つ目 音声処理クラスの場合…Vst::kDistributable、パラメーター操作クラスの場合…0を指定する。(現時点ではこれ以外指定できない。)
    6つ目 VST3プラグインのカテゴリ。とりあえずエフェクタならVst::PlugType::kFx、インストルメントならVst::PlugType::kInstrumentを選ぶとよい。
    カテゴリについてはこちら → VSTプラグインのカテゴリ一覧の一覧を参照
    音声処理クラスにはカテゴリを設定するが、パラメーター操作クラスは0とする。
    7つ目 VST3プラグインのバージョン。
    8つ目 kVstVersionStringを指定する。(現時点ではこれ以外指定できない。)
    9つ目 音声処理クラス・パラメーター操作クラスの生成関数のポインタ。
    基本的に「Steinberg::Vst::<クラス名>::createInstance」にする。(クラス名は音声処理クラス・パラメーター操作クラスのクラス名)

DLLファイルの初期化、終了処理関数のInitModule()関数とDeinitModule()については、VST SDK 3.7.2以降 不要な関数のためコメントアウトしています。
VST SDK 3.7.1以前のものを使用している場合は、InitModule()関数とDeinitModule()のコメントアウトを外してください。
詳細は割愛いたします。基本的にtrueを返すだけで問題ありません。

音声処理を行うクラスの作成

最後にVST3プラグインの中心となる音声処理を行うクラスを作成します。

音声処理クラスはVST SDKにあるAudioEffectクラスを継承して下記のように宣言します。
(VST3の開発では名前空間を指定する必要がありますので忘れないようご注意ください。)

【processor.h】

【processor.cpp】

initialize()関数について

initialize()関数は名前のとおり、クラスの初期化を行う関数です。
引数のcontextについては継承元のinitialize()関数に渡す以外に使用することはほとんどありませんので説明は省略します。

ここでは、継承元のinitialize()関数を呼び出した後、addAudioInput()関数・addAudioOutput()関数を呼び出し、入力と出力のバスを定義しています。

バス構成やaddAudioInput()関数・addAudioOutput()関数については次回の「VST3のバスについて」で説明いたします。

開発するVST3プラグイン固有の初期化(音声処理に使う変数やクラスの初期化など)が必要な場合も、このinitialize()関数内で実施します。
(今回は特に固有の初期化を行う必要がないため、何も実施していません。)

setBusArrangements()関数について

setBusArrangements()関数はバス構成が変更されたとき呼び出されます。(「入力バスがモノラルからステレオに変更された」「出力バスが新たに接続された」等)
詳細な説明はここでは省略いたします。

setBusArrangements()関数等についてはバスの概要と合わせて次回の「VST3のバスについて」で説明いたします。

process()関数について

process()関数は実際に音声の処理を行う関数です。
引数のProcessData& dataには処理に必要な一通りの情報(パラメーターの変更内容や音声データの入力・出力バッファのポインタなど)が入っています。

56行目~59行目では、音声データが入っている入力バッファ・出力バッファを使いやすいよう、Sample32型のポインタ変数に代入しています。(Sample32型は32bit浮動小数点型でfloatの再定義です。)

【processor.cpp】

引数dataのinputs[]、outputs[]の配列サイズは入力バス・出力バスの数と同じになります。入力バス・出力バスの数はそれぞれdata.numInputs・data.numOutputsで取得できます
厳密には違いますが、基本的には入力バス・出力バスの数はaddAudioInput()関数・addAudioOutput()関数を呼び出した回数になります。
今回はaddAudioInput()関数・addAudioOutput()関数を1回ずつ呼び出しているので、data.inputs[0]とdata.outputs[0]のみとなります。(それぞれの配列サイズは1です。)
(例えばaddAudioInput()関数を3回呼び出すと、data.inputs[]の配列サイズは3となります。)

メンバー変数data.inputs[]のchannelBuffers32[][]配列には入力音声データが入っています。2次元配列になっており各次元の配列サイズは
 channelBuffers32[バスのチャンネル数][音声データのサイズ]
となります。
チャンネル数は、data.inputs[x].numChannelsで取得できます。今回、addAudioInput()関数で「SpeakerArr::kStereo」を指定しているので、右チャンネルと左チャンネルで2チャンネル(=配列サイズは2)となります。
ステレオ(SpeakerArr::kStereo)以外にモノラル(SpeakerArr::kMono、配列サイズは1)や5.1ch(SpeakerArr::k51、配列サイズは6)など、他のバス構成もありますので詳しくはVST SDKのマニュアルなどを参照してください。
音声データのサイズはメンバー変数data.numSamplesで指定されます。

メンバー変数data.outputs[]は出力音声データを書き出すためのバッファとなります。内容はメンバー変数data.inputs[]と同様です。

以上から、使いやすいように定義したSample32型のポインタ変数inL・inR・outL・outRはそれぞれ下記のようになります。

  • inL…ステレオ 左チャンネルの入力音声データが入った配列(配列の頭のポインタ)
  • inR…ステレオ 右チャンネルの入力音声データが入った配列(配列の頭のポインタ)
  • outL…ステレオ 左チャンネルの出力音声データを書き込むための配列(配列の頭のポインタ)
  • outR…ステレオ 右チャンネルの出力音声データを書き込むための配列(配列の頭のポインタ)

なお、引数dataの他のメンバー変数の説明については省略いたします。
主なメンバー変数ついては「VST3プラグインのパラメーター実装方法1」などで順次説明させていただきます。

続いて、61行目~66行目では音声処理を実施しています

【processor.cpp】

今回は特に何もせず入力音声データをそのまま出力しています。(入力音声バッファのデータを出力音声バッファにコピーしているだけです。)

最後はkResultTrueを返して終了します。

ソースファイルのビルド

上記4つのファイル(processor.h、processor.cpp、myvst3fuid.h、factory.cpp)を作成した後、ビルドするとVST3プラグインが作成されます。
Visual Studioのプロジェクトフォルダを標準の状態から変更していない場合、下記に<プロジェクト名>.vst3というファイルで作成されます。
(コンパイル・ビルドの方法はこちらでもご説明しております。→サンプルソースファイルのビルド方法)

  • C:\Users\<ユーザ名>\source\repos\<プロジェクト名>\x64\debug\<プロジェクト名>.vst3

作成したVST3プラグインは下記のVST3専用フォルダへのコピーする必要があります。
一部のホストアプリケーションを除いて、下記のVST3専用フォルダ以外に.vst3ファイルがあっても認識してくれません。

  • C:\Program Files\Common Files\VST3\

今回のVST3プラグインはフォルダ構成を気にせず、上記フォルダ内に保存すれば認識されるはずです。

なお、上記フォルダにコピーしたにもかかわらず、作成したVSTプラグインが認識されない場合は、「VST3プロジェクトの作成」の補足にある、「モジュール定義ファイル追加について」を試すか、「プラグイン情報の設定」のコードの中のBEGIN_FACTORY_DEF~END_FACTORYまでを「extern “C” {}」で括ってみてください。

また、ここでのVST3のサンプルは実行時に一部のホストアプリケーション(Sonar、VSTHost等)でエラー(例外)が発生する場合がございます。
エラー発生の際は「VST3プラグインのパラメーター実装方法1」まで進めていただき、再度試していただきますようお願いします。

最後に

以上でとりあえず音声処理を行えるVST3を作成することができるはずです。

このVST3プラグインのサンプルソースファイルはこちらからダウンロードできます → vst3dev_20210403.zip
コンパイル・ビルドの方法は簡単にこちらでご説明しております。→サンプルソースファイルのビルド方法

次回は、バスについての概念を記載できればと思います。

 次回→VST3のバスについて

VST3プラグイン作りの情報はこちらにもございます → はじめてのVST3プラグイン作り

ご指摘やご質問などがございましたら、コメント欄か掲示板Twitterでご連絡いただければと思います。

掲示板
■Twitterアカウント:@vstcpp   URL:https://twitter.com/vstcpp


One thought on “VST3プラグイン開発03 – はじめてのVST3プラグイン

  1. 大変有益な記事の作成、ありがとうございます。勉強させていただいております。
    この記事では入力データをそのまま出力していますがステレオの左右を逆にしたいと思い、processor.cppの一部を
    outL[i] = inR[i];
    outR[i] = inL[i];
    に書き換えてみましたが、どうもうまくいかないようです(モノラルのようになってしまいます)。
    もし原因や改善策などがございましたらご教示いただければ幸いです。

    1. sagamatさん

      書き込みありがとうございます。
      いくつかのDAWは入力・出力バッファが同じポインタになっている場合があります。

       // いくつかのDAWではoutL[i]とinL[i]が同じバッファの場合がある。
       outL[i] = inR[i]; // outL[i]とinL[i]が同じバッファ場合、ここでinL[i]もinR[i]と同じ値になる。
       outR[i] = inL[i]; // すでにinL[i]がinR[i]と同じ値なので、outR[i]はinR[i]と同じになる。(モノラルのようになる)

      解決策として、一時的な変数にinL[i]・inR[i]の値を代入して利用します。

       Sample32 tmpL = inL[i];
       Sample32 tmpR = inR[i];
       outL[i] = tmpR;
       outR[i] = tmpL;

      1. うつぼかずら様

        ありがとうございます!
        ご教示いただいた解決策を試してみたところ、希望通りに動作いたしました。
        お忙しいところご対応いただき感謝申し上げます。

コメントを残す