VST3におけるサイレンス処理
process()関数の引数 dataの入力オーディオバスにはサイレンスフラグというものがあり、「音声入出力バッファの値がすべて0の場合、サイレンスフラグを立てる」という決まりがあるようです。
このサイレンスフラグは、「何も音声入力がない場合に無駄な処理を行わないことでコンピューター(CPU)の負荷を下げる」ためにあります。
(多分、このフラグがSteinberg Webサイトにある「VST3新機能」の「パフォーマンスの改善」にあたるものと思われます。)
音声出力にサイレンスフラグを立てるのは、VST3プラグインが複数 接続される可能性を想定しているためです。
自身の作成したVST3プラグインの音声出力は次のVST3プラグインの音声入力となるため、音声出力がすべて0の場合はサイレンスフラグを立てる必要があります。
サイレンスフラグの処理方法はVST3プラグインによって異なります。
「音声入力のサイレンスフラグが立っているようであれば、音声出力もすべて0にしサイレンスフラグを立てる」といった処理を行うVSTプラグインもあれば、シンセサイザーやリバーブ(残響)エフェクトなどのように「音声入力のサイレンスフラグが立っていても、少し前の音声入力やMIDI入力から音声出力を計算し続ける」ものもあります。
実装方法の一例として、「サイレンスフラグが立っている場合は、音声出力もすべて0にする」方法を下記に記載します。
まず音声処理クラスにサイレンス処理を行う関数を実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// サイレンス処理を行う関数 (process()関数内でサイレンスフラグが立っていた場合に呼び出される関数) void MyVSTProcessor::processSilence(Sample32* inL, Sample32* inR, Sample32* outL, Sample32* outR, int32 numSamples) { // 出力を無音にする(0を出力する。ゴミデータなどが残っている場合があるので。) // 入力と出力が同じポインタの場合があるので念のため確認(DAWがCubaseなど) if (inL != outL) { // 出力バッファを0で埋める memset(outL, 0, numSamples * sizeof(float)); } if (inR != outR) { // 出力バッファを0で埋める memset(outR, 0, numSamples * sizeof(float)); } // VST内部の状態などを更新する必要がある場合はここに記載 // 今回は何も更新しないので記載はなし } |
その後、process()関数内の「入力・出力バッファのポインタをわかりやすい変数に格納」の後に上記関数を入れます。
(バイパスパラメーターと合わせて下記のように実装します。)
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 |
// 入力・出力バッファのポインタをわかりやすい変数に格納 // inputs[]、outputs[]はAudioBusの数だけある(addAudioInput()、addAudioOutput()で追加した分だけ) // 今回はAudioBusは1つだけなので 0 のみとなる // channelBuffers32は32bit浮動小数点型のバッファで音声信号のチャンネル数分ある // モノラル(kMono)なら 0 のみで、ステレオ(kStereo)なら 0(Left) と 1(Right) となる 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]; // 入力のバイパスパラメーターを確認 if (bypass == 1.0) { // バイパス処理を行う return processBypass(inL, inR, outL, outR, numSamples); } // 入力のサイレンスフラグを確認 if (data.inputs[0].silenceFlags != 0) { // 入力のサイレンスフラグが立っている場合の処理 // 出力のサイレンスフラグも入力と同じに設定する data.outputs[0].silenceFlags = data.inputs[0].silenceFlags; // 無音にして出力する(データを0にする) return processSilence(inL, inR, outL, outR, numSamples); } // サイレンス状態ではないので通常処理 // numSamplesで示されるサンプル分、音声を処理する for (int32 i = 0; i < data.numSamples; i++) |
silenceFlagsはオーディオバスのSpeakerArrangementと同じであるため、「どのフラグが立っているか?」を判断することで特定のチャンネルだけをサイレンスにすることもできます。
上記以外にもVST3.6についての情報があります。下記をご参照ください。
また、質問やご指摘はコメント欄や掲示板、Twitterでいただけばとおもいます。
■掲示板
■Twitterアカウント:@vstcpp URL:https://twitter.com/vstcpp