VST Maker
非公式のコミュニティスキルです。ここに記載されているプラグイン、シンセ、フレームワークのベンダーによって作成または推奨されたものではありません。
信頼度タグの読み方:
- (V:ソース) 指定されたソースで確認済み。
- (R) 経験則または好み。測定とリスニングでテストするための初期値であり、決して絶対的なルールではありません。
タグがない場合でも、リリースで依存する前に確認する必要がある標準的な慣行です。
0. 基本ルール
- 構築する前に尋ねること:プラグインの種類(シンセ、エフェクト、コントローラー)、ターゲットOS(Linux、macOS、Windows)、フォーマット(VST3優先;CLAPまたはLV2はオプション)、カラーパレット(決して推測しない;ユーザーがいなければニュートラルなデフォルトを提供)、ライセンス(1を参照)。
- 無料のオープンソースプラグインはオフラインで動作する必要があります:アカウント不要、ライセンスサーバー不要、インストール時や実行時のダウンロード不要。プラグインが必要とするものはすべてバンドルされています。
- 耳で良い音だと決して主張しないでください。それを測定し(12を参照)、最終的な判断はユーザーの耳に委ねてください。
- すべての数値を引用またはテストしてください。数値が経験則である場合は「未確認」と述べてください。
- ユーザーがプログラマーでない場合は、一度に1ステップずつ行ってください。最初は短い回答をし、詳細はリクエストに応じて提供してください。
1. プロジェクト設定とライセンス
- JUCEはデュアルライセンスです:JUCEライセンスとAGPLv3。有料のJUCEプランがない場合はAGPLv3の下で使用する必要があり、AGPLv3はソースコードの公開以上のことを要求します(V:JUCEフォーラム、スタッフの返信)。使用するバージョンの現在のJUCEライセンスを選択する前に読み、どちらが適用されるかをユーザーに伝えてください。記憶から階層価格や収益制限を述べないでください。
- CMakeを使用してください。DSPコードはJUCE GUIタイプに依存しないようにし、ウィンドウなしで単体テストできるようにします。
- まずVST3をビルドしてください。CLAPとLV2はオプションです:現在のJUCEドキュメントとclap-juce-extensionsを確認してから、どちらかを約束してください。
- ホストがVST3をスキャンする場所(V:Steinberg VST 3デベロッパーポータル、プラグインの場所):
- Linux:最初に
$HOME/.vst3/、次に/usr/lib64/vst3/、/usr/lib/vst3/、/usr/local/lib64/vst3/、/usr/local/lib/vst3/。 - macOS:
~/Library/Audio/Plug-ins/VST3/(ユーザー)、/Library/Audio/Plug-ins/VST3/(グローバル)。 - Windows:
C:\Program Files\Common Files\VST3\(グローバル)、%LOCALAPPDATA%\Programs\Common\VST3\(ユーザー、主に開発用)。 - ホストは、特定のProcessor UIDに対して最初に見つかったプラグインを優先順位順にスキャンして使用します。
- Linux:最初に
2. リアルタイムの安全性
processBlockは、ハードデッドラインを持つ高優先度のオーディオスレッドで実行されます。JUCEのドキュメントによると、そこでUIとのやり取りは不可能であり、コードは可変ブロックサイズに対処する必要があります(V:JUCE AudioProcessorドキュメント)。
オーディオスレッドで決して行わないこと:
- メモリの割り当てまたは解放(new、delete、malloc、ベクターや文字列の拡張、
juce::Stringの構築) - 別のスレッドが保持できるロックを取得すること(
std::mutex、CriticalSection) - ファイル、ネットワーク、またはコンソールI/O
- UIまたはMessageManagerの呼び出し
- 例外をスローするか、未知のリアルタイム動作を持つものを呼び出すこと
代わりに:
prepareToPlayで割り当てます(サンプルレートは再生が停止するまで一定です;ブロックサイズはヒントに過ぎず、ドキュメントではホストがそれを超えた場合に備えて防御的にプログラムするように指示されています)(V:JUCEドキュメント)。releaseResourcesまたはデストラクタで解放します。- ロックフリーキュー(
juce::AbstractFifo)またはアトミックを使用して他のスレッドと通信します。UIはタイマーでアトミックをポーリングします;またはオーディオスレッドからAsyncUpdaterをトリガーします。 juce::ScopedNoDenormalsをprocessBlockの先頭に配置します;これは関数が戻るまでアクティブなままなので、ヘルパーはそれを繰り返す必要はありません(V:JUCEフォーラムのコンセンサス、公式ドキュメントではありません)。また、フィードバックパスをデノーマルに減衰できないように設計します。- 推奨読書:Ross Bencina、「Real-time audio programming 101: time waits for nothing」(ここでは引用されていません。このスキルが書かれた時点では取得できませんでした)。
3. パラメータと状態
AudioProcessorValueTreeStateを使用します:ホストオートメーション、アンドゥ、状態保存が付属しています。- ゲイン、周波数、ミックス、ディレイタイムに達するすべてのパラメータをスムーズにします(
juce::SmoothedValue)。そうしないと、ジッパーノイズやクリックが発生します。 - 値がサンプルごとにスムーズ化されていない限り、値をブロックごとに一度ローカルに読み取ります。
- すべてのパラメータに安定した文字列IDを付けます。リリース後にIDの名前を変更したり並べ替えたりしないでください:保存されたプロジェクトとオートメーションが壊れます。新しいIDで新しいパラメータを追加し、状態バージョン番号を保持します。
- 状態またはプリセットからロードされたすべてを検証します:範囲をクランプし、未知のキーを無視し、サイズやカウントを信頼しないでください。
- プロセッサー(DSPと状態)をエディター(UI)から厳密に分離します。プロセッサーはエディターウィンドウを閉じた状態でも完全に動作する必要があります。VST3自体はプラグインをプロセッサーとコントローラーに分割します(V:Steinberg VST 3チュートリアル、「Code your first plug-in」)。
- JUCEがそれらをラップする場合でも知っておく価値のあるVST3の事実(V:同じチュートリアル):パラメータは常に0.0から1.0に正規化されます;ホストがオートメーションできるようにオートメーション可能フラグを設定します;1つの処理ブロックに同じパラメータの複数の変更が含まれる可能性があるため、手書きのプロセッサーはキューを正しく処理する必要があります(チュートリアルは最後の変更のみを適用しますが、これは簡略化です);入力が無音の場合は、無音フラグを設定して尊重し、出力バッファをクリアします;推測する代わりにサポートされていないバスレイアウトを拒否します;入力またはサンプルがない場合でも、保留中のパラメータ変更を適用します。
その他のVST3アーキテクチャの事実(V:Steinberg VST 3デベロッパーポータル、APIドキュメント):
- プロセッサーはコントローラーがロードされていない状態で動作する必要があるため、DSP状態はエディターに依存しません。
process()とsetProcessing()はオーディオスレッドで実行される可能性があります:割り当ては禁止。初期化と終了はUIスレッドで実行されます。- バスとスピーカーの配置は、プラグインが非アクティブな場合にのみ変更できます。非アクティブなバスも含めてすべてのバスにバッファを提供します。入力バッファと出力バッファはメモリを共有する可能性があるため、出力を盲目的にクリアしないでください。
- ノートは
process()内のイベントとして到着します。パラメータの変更は、パラメータキューを通じてサンプル精度で到着します。テンポとトランスポートはプロセスコンテキストで到着します。 - GUIからホストへの編集は、beginEdit、performEdit、endEditの順序で、UIスレッドのみで使用します。
- 状態の復元では、最初にプロセッサーが復元され、次にコントローラーがコンポーネント状態を受け取り、ハンドラーコールバックを起動してはなりません。
process()からプライベートなプロセッサーからコントローラーへのメッセージを送信しないでください;UIスレッドまたはデータ交換APIを使用します。- ユニットはパラメータをグループ化します;MIDIマッピングインターフェースはMIDI CCをパラメータにマップします。
- 必要に応じて読むべきポータルページ:Parameters and Automation、Workflow Diagrams、Multiple Dynamic IO(サイドチェーン)、VST 3 Units、Data Exchange。
4. パフォーマンス:CPU、RAM、GPU
- 最適化する前に測定します(12を参照)。
- CPU(R):ブロックで処理し、パラメータが変更されたときに係数を事前計算し、内部ループでのサンプルごとの分岐や仮想呼び出しを避け、漸化式やテーブルが機能し、測定が速い場合にはサンプルごとの
std::pow、std::exp、std::sinを避けます。 - RAM:一度に事前割り当てし、ボイス間でウェーブテーブルとテーブルを共有し、大きなバッファを
releaseResourcesで解放します。 - GPUとUI:エディターが表示されていて前面にある場合にのみ描画します。非表示の場合はタイマー、メーター、キャンバスアニメーションを一時停止します;オーディオ、オートメーション、MIDIは動作し続けます。再描画レートを制限し、ダーティ領域のみを再描画します(R)。明確に必要であり、Linuxでテストされている場合にのみGPUレンダリングを使用します。
- 非表示または閉じられたエディターは、フレームごとの作業を実行し続けてはなりません。
5. レイテンシー
- プラグインがオーディオを遅延させる場合(ルックアヘッドリミッターやコンプレッサー、リニアフェーズフィルター、オーバーサンプリングフィルター)は、
setLatencySamplesで実際のレイテンシーを報告します(「導入するサンプル遅延の数」、V:JUCEドキュメント)。ホストでレポートが適用されていることを確認します。 - インストゥルメントは、ノートオンからサウンドまでのレイテンシーをゼロに追加します。
- リニアフェーズのオーバーサンプリングフィルターはレイテンシーを追加します;ミニマムフェーズのものは追加しませんが、位相を変更します。意図的に選択し、文書化します。
juce::dsp::Oversamplingはそのレイテンシーを報告します;それを報告します。 - リバーブやディレイでは、ホストがテールをカットしないように
getTailLengthSecondsを正しく保ちます。
6. 音質
エイリアシング
- ナイーブなのこぎり波と方形波は、ナイキストより上の高調波を持ち、非高調波ノイズとして折り返されます。修正方法:帯域制限ステップ法(BLEPファミリー)、微分多項式波形、オクターブごとの帯域制限ウェーブテーブル、またはオーバーサンプリング。
- 公開された方法:微分多項式波形;著者の聴取モデル評価では、4次法がグランドピアノの全範囲で知覚的にエイリアシングがないことがわかりました(V:Välimäki、Nam、Smith、Abel、IEEE TASLP第18巻第4号、2010年)。
- 非線形性(ディストーション、サチュレーション、ウェーブフォールディング、ハードクリップ)は、新しい高調波を生成し、エイリアシングを引き起こします。非線形ステージの周りでオーバーサンプリングするか、逆導関数ベースのアンチエイリアシングを使用します。Zavalishinはウェーブシェーピングのアンチエイリアシングをカバーしています(V:「The Art of VA Filter Design」、セクション6.13)。
- エイリアシングを測定でテストします(12を参照)。オシレーターコードを目で見て判断しないでください。
フィルター
- モデル化されたアナログフィルターには、ゼロディレイフィードバック(トポロジー保存変換)構造を使用します。この本では、第3章(セクション3.9、ゼロディレイフィードバック)、第5章のMoogスタイルラダー、第6章のフィードバックループサチュレーションでそれらをカバーしています(V:Zavalishin、「The Art of VA Filter Design」、改訂版2.1.0、目次)。
- プレーンなイコライザーとユーティリティフィルターには、バイクワッドを使用します。Audio EQ Cookbook(R. Bristow-Johnson、W3C Working Group Note、2021年)は、ローパス、ハイパス、バンドパス、ノッチ、オールパス、ピーキングEQ、シェルフを提供しています(V)。
- カットオフとレゾナンスの変更をスムーズにし、カットオフをナイキストより下にクランプし、レゾナンスを極端な範囲で安定させ、高レゾナンスが音量を急上昇させないようにレベルを補正します。
耳障りではなくスムーズに(R、プロデューサーの実践から;それぞれテストすること)
- 耳障りさは通常、エイリアシング、ハードクリッピング、中高域の強いレゾナンスピーク、フィルタリングされていない高域が多すぎることから生じます。
- ローパスを完全に開いたままのリードは、明るすぎるように聞こえることがあります。明るいリードの場合、約12 kHzのカットオフが出発点としてユーザーから報告された好みの値であり、ルールではありません。
- フィルターフィードバックループ内のサチュレーションは、アナログスタイルのフィルターがスムーズに聞こえる一般的な理由です(V:Zavalishinはフィードバックループサチュレーションをカバーしています;知覚的な主張はR)。
- 非常に小さく、ゆっくりとした変調は、静的なトーンを生き生きと保ちます。例えば、数セントのピッチドリフト。選択する前に変換します:0.1パーセントは約1.7セント、1パーセントは約17セント、17セントは明らかに聞こえるデチューンです。デチューンが目的でない限り、低い側に留まります。
- 厚みのあるサウンドは、レイヤリング、デチューン拡散によるユニゾン、サブオシレーター、ステレオ幅から生まれます。モノラル互換性を確認します(LとRを合計し、中空または打ち消し合うサウンドがないか聞きます)。
ゲインステージングとDC
- 内部チェーンをフロートで、十分なヘッドルームを持って実行します。チェーン内でクリッピングしないでください。唯一のクリッパーまたはリミッターを出力に、意図的に配置します。
- 非対称な非線形性の後、数Hzから数十Hzの範囲の穏やかなハイパスでDCを除去します(R);12のDC測定で確認します。
- プリセットのラウドネスを一致させます(9を参照)。これにより、プリセットを切り替えてもレベルが急変しません。
7. シンセデザイン
- ボイス:すべてのボイスを事前割り当てし、ノートオン時に割り当てないでください。ポリフォニーを定数またはユーザー設定にします。短いフェードでボイスを盗み、ハードカットは避けてください。
- エンベロープ:クリックを避けるために、最小限のアタックとリリースを数ミリ秒使用します;再トリガー時はゼロからではなく、現在のレベルから開始します。
- ユニゾン:ランダムまたは拡散した開始位相、デチューン拡散曲線、ステレオ拡散、ボイス数に応じて増加しないレベル補正。
- スーパーソウ:Roland JP-8000 Super Sawは、互いにデチューンされた7つののこぎり波発振器に似ていると説明されています(V:Wikipedia、Roland JP-8000)。詳細な分析が存在します:Adam Szabo、「How to Emulate the Super Saw」(KTH、2010年)およびAlex Shore(2013年)、両方ともそのページで引用されています。数値を推測する代わりに、デチューン曲線とミキシングについてそれらを読んでください。
- ドリフトとアナログフィール:ピッチとカットオフのゆっくりとしたランダム変調、ボイスごとに、小さく無相関。
- 商用のスーパーソウシンセに見られるアイデア(研究用のみ;独自のコードとデザインを書き、製品のコード、外観、名前、プリセットを決してコピーしないこと)(R、耳と測定で確認):
- オシレーターごとに1つの低速LFO、周波数が黄金比などの無理数比で間隔を空けられているため、組み合わされた動きが可聴的に繰り返されない。
- デチューンとドリフトの深さを一緒にスケーリングする1つの「ドリフト」マクロ、2ページ目に微調整コントロール。
- 独自のコントロールとしてのキートラックハイパス(JP-8000スタイルのスーパーソウサウンドはそれを使用します)。
- オプションの2xまたは4xオーバーサンプリングフィルター;オーバーサンプリングレイテンシーをホストに報告します。
- メーターのdBスケール、ボイスごとのステレオ拡散、サイドチェーン対応エフェクトを確認します:一部の製品が残し、ユーザーが気付くギャップです。
- MIDI:ブロック内の各MIDIイベントのサンプル位置を使用して、ノートがサンプル精度で開始されるようにします。ピッチベンド(デフォルト範囲2半音、設定可能)、サステインペダル、オールノートオフ、リリース付きノートオフを処理します。楽器がリードまたはベース指向の場合は、モノ、レガート、ポルタメントを提供します。
- ウェーブテーブル:オクターブまたはピッチ範囲ごとに帯域制限します;ジッパーノイズを避けるためにフレーム間をクロスフェードします;補間します(線形は安価、高次はCPUコストがかかります。エイリアシングを測定します)。
8. FXデザイン
- コンプレッサーとリミッター:ログ領域で検出し、スムーズなアタックとリリースで、ゲインスムージングを適用し、自動または手動のメイクアップを追加し、先読みする場合はレイテンシーを報告します。チェーンの最後にあるリミッターは、インターサンプルセーフティを約束する場合、トゥルーピークまたはオーバーサンプリングされた天井が必要です。
- マルチバンド:リンウィッツ・ライリークロスオーバーで分割し、バンドがフラットに合計されるようにします;各バンドを処理し;再結合します。クロスオーバーを位相一貫性に保ち、追加されたレイテンシーを報告します。
- ディレイ:フラクショナルディレイ補間、フィードバックパスのダンピングフィルター、テンポシンク、ピンポン、ダッキング、暴走しないようにフィードバック制限。
- リバーブ:フィードバックディレイネットワークまたはDattorroプレートトポロジー(J. Dattorro、「Effect Design Part 1」、JAES 1997);テールの高域をダンプします;メタリックなリンギングを避けるためにディレイラインをわずかに変調します;プリディレイ、ディケイ、ダンピング、サイズ、ミックスを公開します。
- リードに関する一般的な開始実践(耳でテスト)(R):リバーブリターンを200~300 Hzのハイパスで低域から外し、テールの高域をロールオフし、適度なミックスを使用します。
- コーラス、アンサンブル、フェーズ
…
[翻訳のため省略]