2004.01.21 内容訂正
自分自身、VSTもCBもよく理解しているわけではないので、誤認や不正確な部分もあるかもしれません。
間違い等を発見しましたらご指摘いただければ幸いです。
また制作、公開にあたっては全て自己責任のもとでお願いします。つまりこの文章の内容を実行したことによる不利益の責任は著者は負いません。
なお転載禁止は常識的として出版物での紹介も、上記のインターネットでの自己責任原則が理解されない恐れがあるので厳禁とします。
リンクやインターネット上での紹介記事は構いませんが、できればご一報いただければと思います。
2)音声処理のアルゴリズムと数学の知識
シンセサイザやエフェクタを1から作るには、多少なりとも音声処理のアルゴリズムや数学を理解する必要があります。
音源のソースコードがあったとしても、サンプリングレートからどのような間隔、フォーマットでホストが用意するバッファにデータを渡すかなど調整が必要になることもあります。
3)英語
SDKのマニュアルは英語で書かれています。マニュアルは一読してから取り組みましょう。
またメーリングリストでも公用語は英語なので、情報を得たいのなら自分で理解しようとする努力が必要です。
メーリングリストとそのアーカイブは貴重な情報源です。投稿しなくても構いませんのでメーリングリストに登録し、わからないことがあったら、まずマニュアルとメーリングリストのアーカイブから情報を探すことをお勧めします。
1)CBメインウインドウのファイル(F)->新規作成(N)で新規作成ダイアログを開き、その中から、DLLウイザードを選択する。
2)DLLウイザードダイアログで、VC++スタイルを選択します。なおVCL使用はVCLを使用しない限りチェックしないでください。
2)インクルードパスを通す。
同じくvstsdk2\source\commonディレクトリにあるヘッダーファイルに対しパスが通るように、includeパスの設定をするか、必要なヘッダーファイルをプロジェクトに直接登録してください。
3)Unit1.cppを削除する。
Unit1.cppにはDLLMainが書かれてますが、サンプル内にDLLMainがあるのでそちらを使います。
4).defを登録する。
vstsdk2\winデイレクトリにある.defファイルをプロジェクトに登録します。
1).defファイルを修正する。
.def内のmainをmain=_mainに書き換えます。
2)各サンプルのSetUniqueIDの引数を4文字の文字定数からCCONSTマクロに書き換える。
ex)
SetUniqueID('ADly'); ->SetUniqueID(CCONST('A','D','l','y'));
3)FPUの初期化コード追加
CBのバージョン5以上(?)では取れたバグらしいのですが、FPUの初期化コードを明示する必要があるそうです。
_control87(PC_64|MCW_EM,MCW_PC|MCW_EM);
をPluginのコンストラクタなど初期化部分に追記でください。
以上でGUIを使用していないサンプルはコンパイルできるはずです。
1.パラメータ識別子
各パラメータは識別子によって管理され、ホストからアクセスされます。
その定義は、vstsynth.hに列挙型で定義されており、パラメータ数を増やすには、この定義に識別子を追加します。
kNumParamsはいくつパラメータがあるかを示すもので、パラメータ識別子の列挙の最後に必ず必要です。
よってパラメータの追加をするときは、0からkNumParamsの間に行ってください。
2.関数
パラメータ操作に関する関数を以下に示します。
プログラムのデータ構成を変更したらこれらを適宜変更する必要があります。
1)setProgram 指定されたプログラムより全てのパラメータを取得します。
2)setProgramName プログラム名を現在選択されているプログラムに格納します。
3)getProgramName プログラム名を現在選択されているプログラムより取得します。
4)getParameterLabel パラメータの単位をテキストで返します。
5)getParameterDisplay パラメータの値をテキストで返します。数値以外も可です。
6)getParameterName パラメータの名前をテキストで返します。
7)setParameter ホストからの値をパラメータと現在選択されているプログラムに格納します。
8)getParameter パラメータをホストに返します。
9)getProgramNameIndexed プログラム名を指定されたプログラムより取得します。
10)copyProgram 現在選択されているプログラムから指定されたプログラムに内容を全てコピーします。
なおホストがパラメータとして扱う数値はfloatで0から1.0の間のみなので適宜、型変換とスケーリングが必要になります。
processおよびprocessReplacingは、必要なデータの個数を要求してきます。
要求された分だけ、信号を生成(計算)しoutバッファに格納して返却してください。
なお信号の値はfloatで-1.0〜1.0の範囲です。
またMIDIイベントはデータの位置(deltaFrames)でイベントの実行位置を指定してきますので、キューを作り、そのポジションになったらMIDIイベントに対する動作を反映するようにするとより正確な演奏となります。
processEventsはイベント情報としてVstEvents構造体を引数に持ち、このメンバーmidiData[n]には2もしくは3バイトのMidiコマンドが格納されています。
MidiコマンドをMidi規格に従ってコマンド解釈し、信号処理部を駆動してください。
またVstEvents構造体のメンバーdeltaFramesが信号処理部のprocessに対するイベントの実行位置の情報となります。
1)ソフトベンダーとしての契約を最初だけする必要があります。SDKのdocの中にある契約書'Steinberg
VST PlugIns SDK Licensing Agreement'を印刷し、必要事項を記載してsteinbergに送付するだけです。
2)IDをID取得ページより取得し、関数UniqueIDの引数を変更してください。
3)ドキュメントやパッケージには、SDKに入っているLicensing Agreementに従って、Steinbergの権利表示が必要です。
※VST2.3よりVST GUIのソースコードが公開されています。
しかしこのコードはCBのエラーチェックが厳しいためかそのままではエラーが出ます。
ですが、大半のエラーはキャストに関するエラーで適切なキャストに修正(キャストでごまかす??)することでコンパイルが通せます。
下記方法はVCLで強引にHWNDを取得するなどしているためか動作が不安定な点があります。
VCLを使用するよりは、VSTGUIライブラリをコンパイルして使用することをお勧めします。
1)AEffEditor::open
Editorオープン時の関数で引数 ptrはウインドウハンドル(HWND)そのものです。
ここで後述のコンストラクタTForm1((HWND)ptr)でnewします。
最後のTForm::Showでウインドウを表示します。
2)AEffEditor::close
Editorクローズ時の関数です。ウインドウをnewで生成しているので、deleteしてください。
1)Top,Leftは、コンストラクタで(0,0)にしておかないと、ホストの用意したウインドウ上にうまく描画されません。
2)オブジェクトインスペクタでTForm1のBorderStyleをbsNoneにしないと、タイトルバーがホストが用意しているものの下にも表示されてしまいます。
3)子コントロールのクラスを動的に生成するにはTComponentをNULLとしてでなければできません。
コントロールを子にしたい場合は、コントロールクラス生成後、TForm::InsertControlで手作業でコントロールクラスを子として登録する必要があります。
4)イベントメッセージの一部はホストでキャッチされて、メインウインドウやその子コントロールにはディスパッチされません。
おもにGUIに必要となるMouseWheelとKey入力はSDK2.1より拡張され使用できるようになりました。
マニュアルには書いてないので記します。
なおホストによってはこれらの機能に対応してないので注意が必要です。
※Cubase VST32 5.1は対応してましたが、Cubasis VST3.0は対応してませんでした。
1.MouseWheel
AudioEffectXの派生クラスにvenderSpecificメンバーを以下のようにオバーロードします。
なおこのときeditorクラスのメンバーonWheelがイベント応答関数になります。
long VOPM::vendorSpecific (long lArg1, long lArg2, void* ptrArg, float
floatArg)
{
//MouseWhell Enable
if (editor && lArg1
==CCONST( 's','t','C','A') && lArg2 == CCONST('W','h','e','e'))
{
return editor->onWheel (floatArg) == true ? 1 : 0;
}
else
{
return AudioEffectX::vendorSpecific (lArg1, lArg2, ptrArg, floatArg);
}
}
※VOPMはAudioEffectXの派生クラス
2.Key入力
AEffEditor::onKeyDown (VstKeyCode &Key)がSDK2.1で追加されたキーイベント応答関数です。
Key.characterが文字コードになります。
5)その他
マニュアルにはない機能、拡張された機能は、ヘッダーファイルやメーリングリストに情報があることがあります。