つまみ(ノブ)等の実装方法
前回作成したVSTではただGUIウィンドウが開くだけでしたので、パラメーターは一切操作できませんでした。
今回は前回作成したVSTにつまみ(ノブ)やスライダー等を追加し、パラメーターを操作できるようにする方法を説明いたします。
今回作成するプラグインは下記のようなものとなります。
- ボリュームコントロール、トレモロ、パンニングの機能を持つエフェクター
- パラメーターは3つ
- ボリュームコントロール(0.0~1.0の範囲のパラメーター)
- トレモロスピード(0.5~30.0Hzの範囲のパラメーター)
- トレモロタイプ(ボリュームコントロール・トレモロ・パンニングの文字列リストパラメーター)
- 入力バス、出力バスは1つで、共にステレオ(2ch)
- 自作のGUIウィンドウが開く。UIとして下記を実装。
- トレモロタイプを切り替えるコンボボックス
- トレモロスピードを操作するつまみ(ノブ)
- ボリュームを操作するスライダー
なお、ここで説明するVST GUIのバージョンはVST GUI 4.3となります。
VST SDK 3.6.7以前はVST GUIが4.2以下となるため修正等が必要となる可能性があります。各バージョンのSDKが必要な場合のリンクはこちらに記載しております。
このVST3プラグインのサンプルソースファイルはこちらからダウンロードできます→vst3dev_20210403
ZIPファイルの中の「vst3dev10_VST GUI つまみ(ノブ)等の実装方法」フォルダが今回のサンプルソースファイルになります。
コンパイル・ビルドの方法は簡単にこちらでご説明しております。ご参考までに。→サンプルソースファイルのビルド方法
GUIコントロールについて
VST GUIではつまみ(ノブ)やスライダーなど、いくつかのGUIコントロール用のクラスが標準で用意されています。
下記以外のコントロールについては「VST開発TIPS、一覧表、その他」にも記載しております。
【GUIコントロールの一例】
コントロール | 定義済クラス | 概要 | |
---|---|---|---|
ボタン | On/Offボタン | COnOffButton | クリックするごとにオンとオフを切り替えるボタン。 |
キックボタン | CKickButton | クリックした瞬間だけオンになるボタン。 | |
つまみ(ノブ) | つまみ(ノブ) | CKnob | ドラッグすることで値を操作できるつまみ(ノブ)。 |
アニメーションつまみ(ノブ) | CAnimKnob | ドラッグすることで値が操作できるつまみ(ノブ) 値ごとに表示される画像が異なる |
|
スライダー | 縦型スライダー | CVerticalSlider | 上下にドラッグすることで値が操作できるスライダー |
横型スライダー | CHorizontalSlider | 横向きになっただけで縦型スライダーと同じ | |
スイッチ | 縦型スイッチ | CVerticalSwitch | クリックごとに値が切り替わるスイッチ。 |
横型スイッチ | CHorizontalSwitch | 横向きになっただけで縦型スイッチと同じ | |
テキスト | テキストラベル | CTextLabel | 文字列を表示するラベル |
テキストエディット | CTextEdit | 任意の文字列を入力するための入力欄 | |
コンボボックス | COptionMenu | リストから文字列を入力するための入力欄 |
今回のVSTでは上記の中からつまみ(ノブ)、縦型スライダー、コンボボックスを利用いたします。
つまみ(ノブ)の作成関数
まず、つまみ(ノブ)を作成するためcreateKnob()関数を作成します。
関数作成自体は必須ではありませんが、つまみを複数作る場合などに便利なためです。
この関数はVST GUIクラスのメンバー関数として定義しています。
【guieditor.cpp】
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 |
void MyVSTGUIEditor::createKnob(ParamID tag, int x, int y) { // ノブコントロールを作成する // まずは画像ファイルを読み込む CBitmap *backbmp = new CBitmap("knob.png"); CBitmap *handlebmp = new CBitmap("knob_handle.png"); // ノブコントロールのサイズを画像ファイルから取得する CRect size(0, 0, backbmp->getWidth(), backbmp->getHeight()); // ノブコントロールの位置を指定 // 位置を設定(frameの左上が0,0となる) size.offset(x, y); // ノブコントロールの作成 CKnob* control = new CKnob(size, this, tag, backbmp, handlebmp); // パラメーターの現在の値を取得し、コントローラに反映 // controllerは継承元クラスで定義されており、 // GUIEditorクラスを呼び出したコントローラ操作クラスを示す。 ParamValue value = controller->getParamNormalized(tag); control->setValueNormalized(value); // ノブコントロールをフレームに登録 frame->addView(control); // 読み込んだ画像は忘れず解放 backbmp->forget(); handlebmp->forget(); } |
createKnob()関数の引数には、パラメータータグ(ID)と座標(x、y)を指定するようにしています。
コントロールはパラメーターと関連付けるので、パラメータータグ(ID)が必要になります。また、フレーム(描画領域)上の位置を指定するための座標(x、y)が必要になります。
createKnob()関数ではまず、つまみ(ノブ)の背景画像とハンドル画像を読み込んでいます。
次に背景画像からつまみ(ノブ)のサイズを取得し、CRect sizeにそのサイズを設定します。
このsizeはつまみ(ノブ)サイズだけでなくフレーム上の配置位置も兼ねています。CRectのoffset()関数を使用して位置を設定します。
各画像と配置位置・サイズが決まれば、CKnobクラスを作成します。
CKnobクラスのコンストラクタには、「サイズ」「VST GUIクラスのポインタ」「パラメータータグ(ID)」「背景画像」「ハンドル画像」の順に指定します。
これでつまみ(ノブ)が作成できるので、パラメーターの現在の値をつまみ(ノブ)に反映し、フレームに登録すれば表示させることができます。
つまみ(ノブ)の背景画像とハンドル画像はCKnob側に設定されるので不要となるため解放しておきます。
なお、作成・登録したコントロール(ここではCKnobクラス)は解放する必要はありません。frameが破棄されるタイミングで解放されます。
スライダーの作成関数
次にスライダーを作成するためcreateSlider()関数を作成します。
この関数もcreateKnob()関数と同様でVST GUIクラスのメンバー関数として定義しており、作成自体は必須ではありません。
【guieditor.cpp】
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 |
void MyVSTGUIEditor::createSlider(ParamID tag, int x, int y) { // スライダーの作成 // まずは画像ファイルを読み込む CBitmap *backbmp = new CBitmap("slider.png"); CBitmap *handlebmp = new CBitmap("slider_handle.png"); // 画像ファイルからサイズを取得する CRect size; size(0, 0, backbmp->getWidth(), backbmp->getHeight()); size.offset(x, y); // 位置を設定(tergetframeの左上が0,0となる) // スライダーの作成 // スライダーハンドルはスライダー背景画像の上から下まで動かないよう、 // 若干のマージンを持たせる。このマージンは画像によって変わる int bmpmargin = 1; CVerticalSlider* control = new CVerticalSlider(size, this, tag, y + bmpmargin, y + backbmp->getHeight() - (handlebmp->getHeight() + bmpmargin), handlebmp, backbmp); // パラメーターの現在の値を取得し、コントローラに反映 ParamValue value = controller->getParamNormalized(tag); control->setValueNormalized(value); // ノブをフレームに登録 frame->addView(control); // 読み込んだ画像は忘れず解放 backbmp->forget(); handlebmp->forget(); } |
createSlider()関数の引数は、createKnob()関数と同様です。
作成手順もほぼ同じとなっております。
CVerticalSliderクラスのコンストラクタには、「サイズ」「VST GUIクラスのポインタ」「パラメータータグ(ID)」「最大値のときのハンドル位置」「最小値のときのハンドル位置」「背景画像」「ハンドル画像」の順に指定します。
最大値・最小値のハンドル位置の座標は基準がフレーム(配置領域)の左上となっていますのでご注意ください。
コンボボックスの作成関数
コンボボックスも作成するための関数、createCombobox()関数を作成します。
この関数もcreateKnob()関数と同様でVST GUIクラスのメンバー関数として定義しており、作成自体は必須ではありません。
【guieditor.cpp】
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 |
void MyVSTGUIEditor::createCombobox(ParamID tag, int x, int y) { // コンボボックスのサイズを設定(サイズは適当) CRect size; size(0, 0, 60, 16); size.offset(x, y); // コンボボックス作成 COptionMenu* control = new COptionMenu(size, this, tag); // コンボボックスに選択肢を追加する control->addEntry("Volume"); control->addEntry("Tremolo"); control->addEntry("Panning"); // パラメーターの現在の値を取得し、コンボボックス反映 ParamValue value = controller->getParamNormalized(tag); control->setValueNormalized(value); // 小型フォントを指定 control->setFont(kNormalFontSmaller); // 文字色・背景色を設定 control->setFontColor(kWhiteCColor); control->setBackColor(kBlackCColor); control->setFrameColor(kRedCColor); // コンボボックスをフレームに登録 frame->addView(control); } |
createCombobox()関数の引数はcreateKnob()関数と同様です。
createCombobox()関数ではまず、コンボボックスのサイズと位置を設定しています。
設定方法はCKnobやCVerticalSliderなどの他のコントロールと同様です。
サイズと位置の設定がおわれば、COptionMenuクラスを作成します。
COptionMenuクラスのコンストラクタには、「サイズ」「VST GUIクラスのポインタ」「パラメータータグ(ID)」の順に指定します。
コンボボックスは作成するだけだと選択肢が一つもありませんので、選択肢を追加するためaddEntry()関数を使用します。
選択肢はパラメーター操作クラスや音声処理関数と順番を合わせる必要があるので注意ください。
今回は「Volume」「Tremolo」「Panning」の順に合わせています。
【参考:controller.cpp】
31 32 33 34 35 |
// 文字列リストパラメーターを作成、追加 StringListParameter* param2 = new StringListParameter(STR16("Type"), PARAM_TYPE_TAG); param2->appendString(STR16("Volume")); // リスト項目を追加 param2->appendString(STR16("Tremolo")); param2->appendString(STR16("Panning")); |
選択肢追加後は、見た目を整えるためフォントと文字色・背景色を設定しています。
標準で下記のフォントが定義されており、setFont()関数に指定可能です。
その他のフォントを指定する方法は割愛いたします。
定義 | フォント | フォントサイズ |
---|---|---|
kNormalFontVeryBig | Arial | 18 |
kNormalFontBig | Arial | 14 |
kNormalFont | Arial | 12 |
kNormalFontSmall | Arial | 11 |
kNormalFontSmaller | Arial | 10 |
kNormalFontVerySmall | Arial | 9 |
kSymbolFont | Symbol | 13 |
また、文字色・背景色についても下記の色が標準で定義されており、setFontColor()関数など指定可能です。
その他の色の指定方法は割愛いたします。
定義 | 色 | R | G | B | A |
---|---|---|---|---|---|
kTransparentCColor | 透明 | 255 | 255 | 255 | 0 |
kBlackCColor | 黒 | 0 | 0 | 0 | 255 |
kWhiteCColor | 白 | 255 | 255 | 255 | 255 |
kGreyCColor | グレー | 127 | 127 | 127 | 255 |
kRedCColor | 赤 | 255 | 0 | 0 | 255 |
kGreenCColor | 緑 | 0 | 255 | 0 | 255 |
kBlueCColor | 青 | 0 | 0 | 255 | 255 |
kYellowCColor | 黄色 | 255 | 255 | 0 | 255 |
kMagentaCColor | マゼンタ | 255 | 0 | 255 | 255 |
kCyanCColor | シアン | 0 | 255 | 255 | 255 |
最後にコンボボックスをフレーム(配置領域)に登録しています。
コントロールの追加
作成した関数を使って実際にフレーム(配置領域)に各コントロールを追加します。
opne()関数でフレーム(配置領域)作成後に先ほどの各関数を呼び出します。
【guieditor.cpp】
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 |
bool PLUGIN_API MyVSTGUIEditor::open(void* parent, const PlatformType& platformType) { // GUIウィンドウが開かれたときに、UIを作成する // まずはフレーム(配置領域)がすでに作成・設定されているか確認。 // すでに作成・設定されている場合(frameがNULLでない場合)は終了 // frameは継承元クラスで定義されている。 if (frame) { return false; } // 作成するフレームのサイズを設定 CRect size(0, 0, 200, 200); // フレームを作成。作成に失敗したら(NULLなら)終了。 // 引数には、フレームサイズ、自作GUIクラスのポインタを指定する frame = new CFrame(size, this); if (frame == NULL) { return false; } // 作成したフレームに背景画像を設定 CBitmap* cbmp = new CBitmap("background.png"); // リソースから背景画像を読み込む frame->setBackground(cbmp); // フレームに背景画像を設定 cbmp->forget(); // フレームに設定後は背景画像はforgetで解放しておく // 作成したフレームを開く frame->open(parent); // --------------------------------------------- // ここから各コントローラの作成 createCombobox(PARAM_TYPE_TAG, 10, 10); createKnob(PARAM_SPEED_TAG, 20, 35); createSlider(PARAM_DEPTH_TAG, 20, 90); // GUIウィンドウのオープンに成功した場合はtrueを返す return true; } |
コントロール操作時の処理の追加
フレーム(配置領域)に追加しただけでは、操作の結果を取得することができません。
valueChanged()関数を修正し、つまみ(ノブ)やスライダー等が操作されたときにパラメーターに反映させます。
【guieditor.cpp】
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
void MyVSTGUIEditor::valueChanged(CControl* pControl) { // どのパラメーターが操作されたかを取得する。 int32 index = pControl->getTag(); // パラメーターの値を取得する。 float value = pControl->getValueNormalized(); // 取得した値をパラメーターに反映させる controller->setParamNormalized(index, value); // 音声処理クラスに反映した値を通知する controller->performEdit(index, value); } |
valueChanged()関数の引数には操作されたコントローラ(つまみなど)のポインターが渡されます。
最初にパラメータータグ(ID)と値を取得し、それをパラメーター操作クラスに渡して反映しています。
その後、音声処理クラスも同様に値を反映するよう通知しています。
リソースファイル
つまみ(ノブ)とスライダーで画像を使用しています。
これらの画像はリソースから読み込む必要がありますのでリソースファイルにも追加いたします。
追加方法は前回をご参照ください。
【resource.rc】
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <windows.h> #include <commctrl.h> #include <richedit.h> LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL // GUI用イメージ background.png PNG ".\\img\\background.png" knob.png PNG ".\\img\\knob.png" knob_handle.png PNG ".\\img\\knob_handle.png" slider.png PNG ".\\img\\slider.png" slider_handle.png PNG ".\\img\\slider_handle.png" |
最後に
以上でVST GUIにコントロールを追加することができます。
ここでは一部のコントロールの追加方法のみですのが、他のコントロールについてはそのうち記載したいと思います。
なお、今回も詳細な点は省略しておりますので、不明点がございましたら、掲示板かTwitterにてご連絡いただければと思います。
また、「はじめてのVST3プラグイン作り」として作成した記事はここまでとなります。
本シリーズを一通り読んでいただければ、基本的なVSTプラグインであれば作ることができるかと思います。
VSTプラグインの開発を進めていくうえで、足りない部分が出てくるかと思いますが、このシリーズ以外にもいくつか記事にしておりますので、参考にしていただければ幸いです。
このVST3プラグインのサンプルソースファイルはこちらからダウンロードできます → vst3dev_20210403.zip
VST SDK 3.6.7以前の場合 はこちらです。 → 20171126_vst3
コンパイル・ビルドの方法は簡単にこちらでご説明しております。ご参考までに。→サンプルソースファイルのビルド方法
VST3プラグイン作りの情報はこちらにもございます → はじめてのVST3プラグイン作り
ご指摘やご質問などがございましたら、コメント欄か掲示板、Twitterでご連絡いただければと思います。
■掲示板
■Twitterアカウント:@vstcpp URL:https://twitter.com/vstcpp