音声処理クラスでの音声処理準備
前回はVST3ホストでVST3プラグインから音声処理クラスを取得する方法について記載いたしました。
今回は取得した音声処理クラスで音声処理の準備を行うプログラムの説明を実施します。
今回作成するプラグインは下記のとおりです。
- VST3プラグインを読み込む
- VST3プラグインから音声処理クラスを作成する
- 音声処理クラスの情報(入出力数など)を取得する(new)
- 音声処理クラスで音声処理の準備を行う(new)
実際に音声処理を行う一歩手前までとなります。
このVST3プラグインのサンプルソースファイルはこちらからダウンロードできます→vst3host_20210410
ZIPファイルの中の「vst3host03_音声処理クラスでの音声処理準備」フォルダが今回のサンプルソースファイルになります。
なお、Visual Studioのプロジェクトは「コンソールアプリケーション」で作成しております。
プロジェクト設定などは「Visual Studioのプロジェクト設定」もご参照ください。
今回の説明内容
本ページでは、前回説明したVST3プラグインの利用の流れ(下記)のうち、4.についての内容を説明します。
なお、前回までで説明した内容については、説明を省略させていただきます。
- VST3プラグインのファイル(.vst3ファイル)をホストアプリケーションに組み込む(読み込む)
- VST3プラグインのファイル内にある音声処理クラスとパラメーター操作クラスの一覧を取得
- 音声処理クラスとパラメーター操作クラスの一覧から必要なクラスのインスタンスを作成
- 作成した音声処理クラスとパラメーター操作クラスのインスタンスを初期化
VST3ホストのソースコード
まず、ソースコードは下記となります。今回説明する点については、ハイライトしております。説明は後述します。
【main.cpp】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
// ここからVSTホストに必要なヘッダ // VST3ファイルの読込に必要 // module_win32.cppをプロジェクトに追加すること // ※ module_win32.cppはWindows用なので、Linuxの場合はmodule_linux.cpp、 // macOSの場合はmodule_mac.mmをかわりに追加する。(たぶん) #include "public.sdk/source/vst/hosting/module.h" // 読み込んだVST3ファイルから各クラスを取得するため必要 // plugprovider.cppをプロジェクトに追加すること #include "public.sdk/source/vst/hosting/plugprovider.h" // plugproviderで必要なプラグインコンテキスト用のヘッダ #include "public.sdk/source/vst/hosting/hostclasses.h" // ホスト用クラスを使用するときに必要なネームスペース using namespace VST3::Hosting; // ここからVSTプラグイン関係(音声処理クラスやパラメーター操作クラス)のヘッダ #include "pluginterfaces/base/funknown.h" #include "pluginterfaces/base/ftypes.h" #include "pluginterfaces/vst/vsttypes.h" #include "pluginterfaces/vst/ivstaudioprocessor.h" #include "pluginterfaces/vst/ivsteditcontroller.h" // 音声処理クラスやパラメーター操作クラスの使用時に必要なネームスペース using namespace Steinberg; using namespace Steinberg::Vst; // ここからそれ以外のヘッダ #include <stdio.h> using namespace std; // メイン関数はここから int main() { string path = u8".\\vst_file_name.vst3"; // VST3プラグインのパス string error; // VST3プラグインのファイルを読み込みに失敗したときのエラー用 // --------------------------------------------------------------------------- // PluginContextを作成・セットアップする // PluginContextはVST3プラグインがホストアプリ名やインターフェイスの対応状況を取得したり、 // allocateMessage()でIMessageを取得するために必要。(詳細は割愛) HostApplication pluginContext; PluginContextFactory::instance().setPluginContext(&pluginContext); // --------------------------------------------------------------------------- // Moduleクラスを使用してVST3プラグインのファイルを読み込む shared_ptr<Module> module = Module::create(path, error); if (!module) { // 読み込みに失敗したら終了 printf("Error : VST3ファイルの読込に失敗\n"); printf(" : path = %s\n", path.c_str()); return 1; } // --------------------------------------------------------------------------- // PluginFactoryクラスを取得する // PluginFactoryクラスはVST3プラグインファイル内にあるプラグイン情報取得や音声処理クラスと // パラメータ操作クラスを列挙・作成するクラス PluginFactory factory = module->getFactory(); // PluginFactoryクラスでVST3プラグインファイル内にあるクラスを列挙しながら // 音声処理クラスのみをaudioClassInfoにコピーする // VST3プラグインファイル内には複数の音声処理クラスが存在する場合があるため一度列挙する vector<ClassInfo> audioClassInfo; for (ClassInfo classInfo : factory.classInfos()) { // 音声処理クラスはカテゴリーがkVstAudioEffectClassとなっているものとなる // (ちなみにパラメータ操作クラスはkVstComponentControllerClass ) if (classInfo.category() == kVstAudioEffectClass) { audioClassInfo.push_back(classInfo); } } // VST3プラグインファイル内に音声処理クラスがなかった場合は終了する。 if (audioClassInfo.size() == 0) { printf("Error : VST3ファイル内に音声処理クラスがありません。\n"); return 1; } // --------------------------------------------------------------------------- // PlugProviderクラスを作成する // PlugProviderクラスはPluginFactoryクラスとClassInfoクラスから音声処理クラスを // 作成・初期化するクラス shared_ptr<PlugProvider> plugProvider; plugProvider = make_shared<PlugProvider>(factory, audioClassInfo[0], true); // PlugProviderクラスが正常に作成できたかチェック if (!plugProvider) { // 読み込みに失敗したら終了 printf("Error : PlugProviderクラスの作成に失敗\n"); return 1; } printf("最初に見つかった音声処理クラス「%s」を作成・初期化しました。\n\n", audioClassInfo[0].name().c_str()); // --------------------------------------------------------------------------- // PlugProviderクラスから音声処理クラスを取得する。(音声処理クラスは初期化済み) IComponent* component = plugProvider->getComponent(); // 音声処理クラスはIComponentクラスとIAudioProcessorクラスを継承している // PlugProviderクラスから取得できるのはIComponentクラスのみなので、 // IComponentクラス取得後、queryInterfaceでIAudioProcessorクラスも取得する IAudioProcessor* processor; component->queryInterface(IAudioProcessor::iid, (void**)&processor); if (processor == nullptr) { printf("Error : 音声処理クラスの実装が不十分なため失敗\n"); return 1; } // --------------------------------------------------------------------------- // 取得した音声処理クラスのセットアップを行う。(その1) // 音声入出力を確認する。 printf("==================== 音声入出力の情報 ====================\n"); // 音声入力情報の取得 int32 audioInNum = component->getBusCount(kAudio, kInput); printf("音声入力バスは %d 個あります。\n", audioInNum); // 各音声入力バスの情報を取得する for (int i = 0; i < audioInNum; i++) { // バスの情報(名称・チャンネル数など)を取得する BusInfo busInfo; component->getBusInfo(kAudio, kInput, i, busInfo); // スピーカー構成のビットを取得する SpeakerArrangement arr = 0; processor->getBusArrangement(kInput, i, arr); printf(" 音声入力バス %2d個目 … バス名: %S チャンネル数(スピーカー構成フラグ):%dch (0x%08llx)\n", i + 1, busInfo.name, busInfo.channelCount, arr); } printf("\n"); // 音声出力情報の取得(音声入力と同様の処理なので詳細なコメントは割愛) int32 audioOutNum = component->getBusCount(kAudio, kOutput); printf("音声出力バスは %d 個あります。\n", audioOutNum); for (int i = 0; i < audioOutNum; i++) { BusInfo busInfo; component->getBusInfo(kAudio, kOutput, i, busInfo); SpeakerArrangement arr = 0; processor->getBusArrangement(kOutput, i, arr); printf(" 音声出力バス %2d個目 … バス名: %S チャンネル数(スピーカー構成フラグ):%dch (0x%08llx)\n", i + 1, busInfo.name, busInfo.channelCount, arr); } printf("\n"); // --------------------------------------------------------------------------- // 取得した音声処理クラスのセットアップを行う。(その2) // イベント(MIDI)入出力を確認する。 printf("================== イベント入出力の情報 ==================\n"); // イベント(MIDI等)入力情報の取得 int32 eventInNum = component->getBusCount(kEvent, kInput); printf("イベント入力バスは %d 個あります。\n", eventInNum); // 各イベント入力バスの情報を取得する for (int i = 0; i < eventInNum; i++) { // バスの情報(名称・チャンネル数など)を取得する BusInfo busInfo; component->getBusInfo(kEvent, kInput, i, busInfo); printf(" イベント入力バス %2d個目 … バス名: %S MIDIチャンネル数:%dch\n", i + 1, busInfo.name, busInfo.channelCount); } printf("\n"); // イベント(MIDI等)出力情報の取得(イベント入力と同様の処理なので詳細なコメントは割愛) int32 eventOutNum = component->getBusCount(kEvent, kOutput); printf("イベント出力バスは %d 個あります。\n", eventOutNum); for (int i = 0; i < eventInNum; i++) { BusInfo busInfo; component->getBusInfo(kEvent, kInput, i, busInfo); printf(" イベント出力バス %2d個目 … バス名: %S MIDIチャンネル数:%dch\n", i + 1, busInfo.name, busInfo.channelCount); } printf("\n"); // --------------------------------------------------------------------------- // 取得した音声処理クラスのセットアップを行う。(その3) // 対応しているビット数・レイテンシなどを確認する。 printf("=================== その他 音声処理情報 ==================\n"); // 音声のサンプリングビット数 printf("音声入出力の対応ビット数\n"); tresult resSampleBit32 = processor->canProcessSampleSize(kSample32); tresult resSampleBit64 = processor->canProcessSampleSize(kSample64); printf(" 32bit対応 … %s 64bit対応 … %s \n", (resSampleBit32 != kResultFalse) ? "対応" : "非対応", (resSampleBit64 != kResultFalse) ? "対応" : "非対応"); uint32 latency = processor->getLatencySamples(); printf("プラグインのレイテンシ … %d\n", latency); uint32 tailSample = processor->getTailSamples(); printf("プラグインのテイルサンプル … %d\n", tailSample); printf("\n"); // --------------------------------------------------------------------------- // 取得した音声処理クラスのセットアップを行う。(その4) // 音声処理するためにセットアップする。 printf("============== 音声処理クラスのセットアップ ==============\n"); // セットアップのために音声処理クラスを非アクティブにする processor->setProcessing(false); component->setActive(false); // サンプリングレート、ブロックサイズ等をProcessSetup構造体に設定。 // プラグインが対応しているサンプリングレート・ブロックサイズは取得できないので、 // VSTホスト側でサンプリングレート・ブロックサイズを適当に設定して、 // setupProcessing()でkResultOkとなるパターンを探す必要がある。 SampleRate sampleRate = 44100.0; int32 blockSize = 512; ProcessSetup setup{ kRealtime, kSample32, blockSize, sampleRate }; if (processor->setupProcessing(setup) != kResultOk) { printf("Error : 音声処理クラスのセットアップに失敗\n"); printf(" : 32bit、サンプリングレート %.1lfHz、ブロックサイズ %dに非対応\n", sampleRate, blockSize); } else { printf("音声処理クラスのセットアップが完了\n"); printf("プラグインは32bit、サンプリングレート %.1lfHz、ブロックサイズ %dに対応\n", sampleRate, blockSize); } printf("\n"); // セットアップ完了後、音声処理クラスをアクティブにする component->setActive(true); // アクティブ時はsetActive(true)をsetProcessing(true)より先に。 processor->setProcessing(true); // ~~~~ // 本来はここでcomponentを使用して音声処理クラスで音声処理などを行う。 // ~~~~ // --------------------------------------------------------------------------- // 終了処理 // 終了前に音声処理クラスを非アクティブにする processor->setProcessing(false); component->setActive(false); // IAudioProcessorはrelease()を呼び出して解放する。 processor->release(); // IComponentクラスはPlugProviderクラスで解放する。 // PlugProviderクラス自体はmake_sharedで作成されるので解放は不要。 plugProvider->releasePlugIn(component, nullptr); // Moduleクラスはmake_sharedで作成されているので解放は不要。 // PluginFactoryクラスは解放の必要は特にない。 printf("終了します\n"); return 0; } |
音声処理の準備について
VSTホストアプリケーションでは、PlugProviderクラスからIComponentクラスとIAudioProcessorクラスの取得が終わった後、下記の4つの内容を実施して音声処理の準備をします。
IComponentクラスとIAudioProcessorクラスの取得については前回の内容を確認してください。
- 音声入出力の確認
- イベント入出力の確認
- レイテンシ・ビット数などを確認
- 音声処理するためにセットアップ
上記の順番については特については特に決まりはありませんが、「4.」については音声処理の直前がいいと思われます。(明確な根拠はありません。)
音声入出力の確認
まず、音声入力の確認をしています。
音声入力の数、つまりオーディオ入力バスの数はIComponentクラスのgetBusCount()関数で取得します。
「オーディオバス」で「入力方向」のバスの情報を取得するので、getBusCount()関数にはkAudioとkInputを指定しています。
- getBusCount()関数
概要 | VST3プラグインのバスの数を取得する関数。 | ||
---|---|---|---|
戻り値 | 型 | 概要 | |
int32 | VST3プラグインのバスの数。 | ||
引数 | 型 | 変数名 | 概要 |
MediaType | type | 取得するバスの種類。kAudioとkEventが指定でき、kAudioはオーディオバス、kEventはイベントバスが取得できる。 (MediaTypeはlongの再定義) |
|
BusDirection | dir | 取得するバスの方向。kInputとkOutputが指定でき、kInputは入力バス、kOutputは出力バスが取得できる。 (BusDirectionはlongの再定義) |
続いて、オーディオ入力バスの数だけforループでバスの詳細な情報を取得しています。
オーディオ入力バスの詳細な情報はIComponentクラスのgetBusInfo()関数とIAudioProcessorクラスのgetBusArrangement()関数で取得しています。
VST3のバスについてなどもご確認ください。
- getBusInfo()関数
概要 | 指定したバスの情報を取得する関数。 | ||
---|---|---|---|
戻り値 | 型 | 概要 | |
tresult | バス情報の取得に成功したかどうかの結果。 取得に成功した場合…kResultTrue、取得に失敗した場合…kResultFalse |
||
引数 | 型 | 変数名 | 概要 |
MediaType | type | 取得するバスの種類。情報取得したいバスがオーディオバスのときはkAudio、イベントバスのときはkEventを指定する。 | |
BusDirection | dir | 取得するバスの方向。情報取得したいバスが入力のときはkInput、出力のときはkOutputを指定する。 | |
int32 | index | 取得するバスの番号。0~getBusCount()関数で取得した値の範囲で指定する。 | |
BusInfo& | bus | バス情報が格納されるBusInfo構造体への参照。 |
- getBusArrangement()関数
概要 | 指定したオーディオバスのスピーカー構成を取得する関数。 | ||
---|---|---|---|
戻り値 | 型 | 概要 | |
tresult | スピーカー構成の取得に成功したかどうかの結果 取得に成功した場合…kResultTrue、取得に失敗した場合…kResultFalse |
||
引数 | 型 | 変数名 | 概要 |
BusDirection | dir | 取得するバスの方向。情報取得したいバスが入力のときはkInput、出力のときはkOutputを指定する。 | |
int32 | index | 取得するバスの番号。0~getBusCount()関数で取得した値の範囲で指定する。 | |
SpeakerArrangement& | arr | スピーカー構成が格納されるSpeakerArrangement型変数への参照。(SpeakerArrangementはunsigned __int64の再定義) |
【main.cpp】
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
// --------------------------------------------------------------------------- // 取得した音声処理クラスのセットアップを行う。(その1) // 音声入出力を確認する。 printf("==================== 音声入出力の情報 ====================\n"); // 音声入力情報の取得 int32 audioInNum = component->getBusCount(kAudio, kInput); printf("音声入力バスは %d 個あります。\n", audioInNum); // 各音声入力バスの情報を取得する for (int i = 0; i < audioInNum; i++) { // バスの情報(名称・チャンネル数など)を取得する BusInfo busInfo; component->getBusInfo(kAudio, kInput, i, busInfo); // スピーカー構成のビットを取得する SpeakerArrangement arr = 0; processor->getBusArrangement(kInput, i, arr); printf(" 音声入力バス %2d個目 … バス名: %S チャンネル数(スピーカー構成フラグ):%dch (0x%08llx)\n", i + 1, busInfo.name, busInfo.channelCount, arr); } printf("\n"); |
つぎに音声出力の確認をします。内容は音声入力とほぼ同様なので詳細は割愛いたします。
【main.cpp】
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
// 音声出力情報の取得(音声入力と同様の処理なので詳細なコメントは割愛) int32 audioOutNum = component->getBusCount(kAudio, kOutput); printf("音声出力バスは %d 個あります。\n", audioOutNum); for (int i = 0; i < audioOutNum; i++) { BusInfo busInfo; component->getBusInfo(kAudio, kOutput, i, busInfo); SpeakerArrangement arr = 0; processor->getBusArrangement(kOutput, i, arr); printf(" 音声出力バス %2d個目 … バス名: %S チャンネル数(スピーカー構成フラグ):%dch (0x%08llx)\n", i + 1, busInfo.name, busInfo.channelCount, arr); } printf("\n"); |
イベント入出力の確認
次にイベント入出力の確認をしています。
ここも基本的には音声入出力の確認と変わりません。
イベントバス数をIComponentクラスのgetBusCount()関数で取得し、イベントバスの数だけforループでイベントバスの詳細な情報を取得しています。
イベントバスの詳細な情報はIComponentクラスのgetBusInfo()関数で取得しています。(スピーカー構成はないのでgetBusArrangement()関数は使いません)
【main.cpp】
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
// --------------------------------------------------------------------------- // 取得した音声処理クラスのセットアップを行う。(その2) // イベント(MIDI)入出力を確認する。 printf("================== イベント入出力の情報 ==================\n"); // イベント(MIDI等)入力情報の取得 int32 eventInNum = component->getBusCount(kEvent, kInput); printf("イベント入力バスは %d 個あります。\n", eventInNum); // 各イベント入力バスの情報を取得する for (int i = 0; i < eventInNum; i++) { // バスの情報(名称・チャンネル数など)を取得する BusInfo busInfo; component->getBusInfo(kEvent, kInput, i, busInfo); printf(" イベント入力バス %2d個目 … バス名: %S MIDIチャンネル数:%dch\n", i + 1, busInfo.name, busInfo.channelCount); } printf("\n"); // イベント(MIDI等)出力情報の取得(イベント入力と同様の処理なので詳細なコメントは割愛) int32 eventOutNum = component->getBusCount(kEvent, kOutput); printf("イベント出力バスは %d 個あります。\n", eventOutNum); for (int i = 0; i < eventInNum; i++) { BusInfo busInfo; component->getBusInfo(kEvent, kInput, i, busInfo); printf(" イベント出力バス %2d個目 … バス名: %S MIDIチャンネル数:%dch\n", i + 1, busInfo.name, busInfo.channelCount); } printf("\n"); |
レイテンシ・ビット数などの確認
次にVST3プラグインが処理できる音声入出力のビット数とVST3プラグインのレイテンシとテイルサンプルを確認をしています。
処理できる音声入出力のビット数はIAudioProcessorクラスのcanProcessSampleSize()関数を使うことで確認できます。
- canProcessSampleSize()関数
概要 | VST3プラグインが処理できる音声入出力のビット数を確認するための関数。 | ||
---|---|---|---|
戻り値 | 型 | 概要 | |
tresult | 指定したビット数に対応しているかどうかの結果 対応している場合…kResultTrue、対応していない場合…kResultFalse |
||
引数 | 型 | 変数名 | 概要 |
int32 | symbolicSampleSize | ビット数の指定。32bit浮動小数点(float型)に対応しているか確認する場合はkSample32、64bit浮動小数点(double型)に対応しているか確認する場合はkSample64を指定する |
プラグインのレイテンシはIAudioProcessorクラスのgetLatencySamples()関数を使うことで確認できます。
また、テイルサンプルはIAudioProcessorクラスのgetTailSamples()関数で確認できます。ここでは詳細は割愛いたします。
【main.cpp】
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
// --------------------------------------------------------------------------- // 取得した音声処理クラスのセットアップを行う。(その3) // 対応しているビット数・レイテンシなどを確認する。 printf("=================== その他 音声処理情報 ==================\n"); // 音声のサンプリングビット数 printf("音声入出力の対応ビット数\n"); tresult resSampleBit32 = processor->canProcessSampleSize(kSample32); tresult resSampleBit64 = processor->canProcessSampleSize(kSample64); printf(" 32bit対応 … %s 64bit対応 … %s \n", (resSampleBit32 != kResultFalse) ? "対応" : "非対応", (resSampleBit64 != kResultFalse) ? "対応" : "非対応"); uint32 latency = processor->getLatencySamples(); printf("プラグインのレイテンシ … %d\n", latency); uint32 tailSample = processor->getTailSamples(); printf("プラグインのテイルサンプル … %d\n", tailSample); printf("\n"); |
音声処理のためのセットアップ
セットアップの前にVST3プラグインを非アクティブにします。必ず後述するIAudioProcessorクラスのsetupProcessing()関数の前には非アクティブにしてください。
非アクティブにするには、IAudioProcessorクラスのsetProcessing()関数とIComponentクラスのsetActive()関数の引数にfalseを指定してを呼び出します。
setProcessing()関数とsetActive()関数の詳細は割愛いたします。
【main.cpp】
222 223 224 225 226 227 228 229 230 |
// --------------------------------------------------------------------------- // 取得した音声処理クラスのセットアップを行う。(その4) // 音声処理するためにセットアップする。 printf("============== 音声処理クラスのセットアップ ==============\n"); // セットアップのために音声処理クラスを非アクティブにする processor->setProcessing(false); component->setActive(false); |
次にIAudioProcessorクラスのsetupProcessing()関数を使用してVST3プラグインをセットアップします。
VST3プラグインにこれから処理で使用するサンプリングレートやブロックサイズ、ビット数などを指定して通知します
なお、VST3プラグインが対応しているサンプリングレート・ブロックサイズは事前に取得できないので、VSTホスト側でサンプリングレート・ブロックサイズを適当に設定して、setupProcessing()関数が成功するパターンを探す必要があります。
(「まずサンプリングレート96,000Hz、ブロックサイズは32で試して、無理なら次はサンプリングレート48,000Hzブロックサイズは32で試して…」というように成功するパターンを探す必要があります。)
筆者の感覚ですが、サンプリングレートは44,100Hz・48,000Hz・96,000Hzのいずれかでブロックサイズは32~2048ぐらいであれば多くのVST3プラグインが対応しているようです。
- setupProcessing()関数
概要 | VST3プラグインにこれから処理で使用するサンプリングレートやブロックサイズ、ビット数などを指定してセットアップするための関数。 | ||
---|---|---|---|
戻り値 | 型 | 概要 | |
tresult | VST3プラグインがセットアップに成功したかどうかの結果 セットアップに成功した場合…kResultOk、セットアップに失敗した場合…kResultFalse |
||
引数 | 型 | 変数名 | 概要 |
ProcessSetup& | setup | VST3プラグインのセットアップのための情報を格納したProcessSetup構造体への参照。 |
- ProcessSetup構造体
型 | 変数名 | 概要 |
---|---|---|
int32 | processMode | これから行われる音声処理のモード。kRealtime、kPrefetch、kOfflineが指定できる。基本的にkRealtimeでいいはず。(詳細不明) |
int32 | symbolicSampleSize | これから行われる音声処理のビット数。kSample32(32bit浮動小数点…float型)とkSample64(64bit浮動小数点…double型)が指定できる |
int32 | maxSamplesPerBlock | これから行われる音声処理の最大ブロックサイズ。(音声バッファの最大サイズ) |
SampleRate | sampleRate | これから行われる音声処理のサンプリングレート。 |
【main.cpp】
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
// サンプリングレート、ブロックサイズ等をProcessSetup構造体に設定。 // プラグインが対応しているサンプリングレート・ブロックサイズは取得できないので、 // VSTホスト側でサンプリングレート・ブロックサイズを適当に設定して、 // setupProcessing()でkResultOkとなるパターンを探す必要がある。 SampleRate sampleRate = 44100.0; int32 blockSize = 512; ProcessSetup setup{ kRealtime, kSample32, blockSize, sampleRate }; if (processor->setupProcessing(setup) != kResultOk) { printf("Error : 音声処理クラスのセットアップに失敗\n"); printf(" : 32bit、サンプリングレート %.1lfHz、ブロックサイズ %dに非対応\n", sampleRate, blockSize); } else { printf("音声処理クラスのセットアップが完了\n"); printf("プラグインは32bit、サンプリングレート %.1lfHz、ブロックサイズ %dに対応\n", sampleRate, blockSize); } printf("\n"); |
セットアップが終われば、VST3プラグインをアクティブにします。
非アクティブのときとは逆にIComponentクラスのsetActive()関数とIAudioProcessorクラスのsetProcessing()関数の引数にtrueを指定してを呼び出します。
なお、アクティブにするときはsetActive()関数→setProcessing()関数の順に呼び出し、非アクティブにするときはsetProcessing()関数→setActive()関数の順に呼び出す必要があります。
【main.cpp】
252 253 254 |
// セットアップ完了後、音声処理クラスをアクティブにする component->setActive(true); // アクティブ時はsetActive(true)をsetProcessing(true)より先に。 processor->setProcessing(true); |
この後、VST3プラグインに音声データやMIDIデータ、パラメーターの変更情報を与えて音声処理を実施します。
今回 説明が多くなり過ぎるため、次回 説明いたします。
終了処理
最後に終了処理を行います。
終了処理では、アクティブにしたVST3プラグインを非アクティブにします。
その後は前回説明した通り、IAudioProcessorクラスのrelease()関数とplugProviderクラスのreleasePlugIn()関数の呼び出しを行います。
【main.cpp】
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
// --------------------------------------------------------------------------- // 終了処理 // 終了前に音声処理クラスを非アクティブにする processor->setProcessing(false); component->setActive(false); // IAudioProcessorはrelease()を呼び出して解放する。 processor->release(); // IComponentクラスはPlugProviderクラスで解放する。 // PlugProviderクラス自体はmake_sharedで作成されるので解放は不要。 plugProvider->releasePlugIn(component, nullptr); // Moduleクラスはmake_sharedで作成されているので解放は不要。 // PluginFactoryクラスは解放の必要は特にない。 printf("終了します\n"); return 0; |
実行結果サンプル
上記のコードを実行すると下記のような表示となります。読み込んだVST3プラグインは私の作成した「Tempo Sync Filter」となります。
最後に
ここまででようやく音声処理クラスのセットアップが完了となり、実際に音声処理を行うことができるようになります。
次回は、作成した音声処理クラスで実際に音声処理を行うところを説明いたします。
次回→(作成中)
VST3プラグイン作りの情報はこちらにもございます → はじめてのVST3プラグイン作り
ご指摘やご質問などがございましたら、コメント欄か掲示板、Twitterでご連絡いただければと思います。
■掲示板
■Twitterアカウント:@vstcpp URL:https://twitter.com/vstcpp
更新お疲れ様です、うつぼかずらさんの記事を全部拝見しました、それを見ながらプラグインとホストを作っています。
今回の内容について一つ質問があります、ホストがプラグインをセットアップ&アクティブ処理をしないと何かまずいことがありますか、つまりセットアップとアクティブは必須動作ですか?(僕は一番簡単なプラグインとホストを作りましたがセットアップとアクティブ処理はしていないけどプラグインとのやり取りは特に問題なく普通に処理できるから疑問が出てきました)。
他の資料に”プラグインをリアルタイム処理可能な状態にするためには、setprocessingとsetupProcessを呼ぶ”を書いた、僕今回作ったホストはWAVファイルのデータを一気に読み込んでプラグインに渡して、プラグインが処理した後に、一気にホストに返す、再生するの仕様ですから、リアルタイム処理ではないからセットアップ処理がしなくても大丈夫、ということですか?
VST3の規格を見た限り、setActive()・setProcessing()・setupProcessing()は必須だと思われます。
この記事はVST3 SDKの「Workflow Diagrams」をもとに書いていますが、上記の関数の処理によりVST3プラグインは初期状態から処理可能な状態に変わっていく形となります。
上記の関数を呼び出さない場合、リアルタイム処理かどうかにかかわらず、VST3プラグインが正常に動作しない可能性があります。
今回はたまたまVST3プラグインが動いただけと考えるほうがよいと思います。
返信ありがとうございます、そうですね、とりあえず規格通り設定するのは正しい操作ですから、追加するべきです。
SDK3.7.1についたサンプルプラグイン「hostchecker.vst3」のソースから見ると、setActive(true)はsetProcessing(true)の次にやると、Errorと判断されます。そうみると、先にsetActive(true)を実行したほうがいいです。(この順番より何かが違うが全然わかりませんですけど)
ご指摘ありがとうございます。
確かに順番的にsetActive(true)→setProcessing(true)ですね。(falseを指定するときは逆順。)
ドキュメントを見る限りでは下記のような違いがあるようです。
・setActive()…プラグインのメモリの確保・初期化などを行う。音声スレッドでは呼び出さない。
・setProcesssing()…プラグインの初期化を行う。音声スレッドでも呼び出してよい。
回答ありがとうございます。
なるほどね、こうみると、setActive(true)は先にやったほうがいいですね。
ちなみに、hostchecker.vst3はホストをチェックするプラグインと思いますが、どう使いますか?エラーとワーニングがあれば直すか?評点に何か意味がありますか?ご存じでしょうか
hostcheckerはほとんど使ったことがないのでよくわからないです。