シリーズのすべての投稿:
パート1.紹介とセットアップパート2.コードの学習パート3. VSTおよびAUパート4.デジタル歪みパート5.プリセットとGUIパート6.信号合成パート7. MIDIメッセージの受信パート8.仮想キーボードパート9.封筒パート10. GUIの改善パート11.フィルターパート12.低周波発振器パート13.再設計パート14.ポリフォニー1パート15.ポリフォニー2パート16.アンチエイリアス
テストプロジェクトを詳しく見てみましょう。 最も重要なファイルは
resource.h 、
MyFirstPlugin.hおよび
MyFirstPlugin.cppです。 現時点では、プラグインはシンプルなボリュームコントロールです。
学習コード
定数、フラグ、画像ソース
ナビゲーターで
resource.hを開きます。 このファイルには、プラグインの名前、バージョン、一意のID、GUIの画像ソースへのリンクなどの定数が含まれています。 行23〜26では、一意のIDを指定できます。
IDは、プラグインの一般的なカタログ化にとって重要です。
ここで登録でき
ます 。 56行目以降は、プラグインの起動時に表示されるボリュームノブのIDとイメージへのパスをさらに決定します。
ナビゲータで検索し、
リソース→img→knob.pngを開きます。 これは、サイズが48 x 48ピクセルの60の異なるペン位置を持つスプライトです。 プラグインを起動してノブを回しても、ハンドルの画像は回転しません。 プログラムは、このスプライトの対応する部分のみを表示します。
なぜ回転しないのですか? ペンにいくつかのノッチがあり、影を落としていると想像してください。 次に、回転中に影も回転します。 あなたが知っているように、これは実際には起こりません。
以下のresource.hで、プラグインウィンドウのサイズを設定できます。
#define GUI_WIDTH 300 #define GUI_HEIGHT 300
値をいじってプラグインを実行します。
プラグインクラスインターフェイス
MyFirstPlugin.hを開き
ます 。 プラグインクラスのインターフェイスが含まれています。
public
部分には、コンストラクタ、デストラクタ、およびクラスの3つのメンバー関数が含まれます。
- サンプリングレートが変更されると、
Reset
が呼び出されます。 OnParamChange
は、プラグインのパラメーターが変更されたとき、たとえばノブを回したときに呼び出されます。ProcessDoubleReplacing
はプラグインの中核です。 着信オーディオの処理が実行されるのは、その中にあります。
private
部分には、現在のボリューム値を格納する
double
変数のみがあります。
実装
興味深い部分に進みます!
MyFirstPlugin.cppを開き
ます 。 すぐに、
enum
タイプの興味深いレシーバーが表示されます。
enum EParams { kGain = 0, kNumParams };
kGain = 0
設定し、その後に
kNumParams
を置くと、
kNumParams
はプラグインパラメーターの数になります(この場合は1)。
次の
enum
は、
resource.hで説明されている定数を使用し、プラグインウィンドウでハンドル座標を設定します。
enum ELayout { kWidth = GUI_WIDTH, kHeight = GUI_HEIGHT, kGainX = 100, kGainY = 100, kKnobFrames = 60 };
また、
knob.pngのフレーム数を60に設定します。
次に、コンストラクターの実装が開始されます。 プラグインの属性が設定されます:
これまでのGUIでは、値もパーセント記号も表示されませんが、値は
0
から
100
まで変化できます。 デフォルト値は
50
です。 値のグラデーションが円上で均一ではないことに気付くかもしれません。 これは
SetShape(2.)
です。 これを
SetShape(1.)
に置き換えると、値の分布は線形になります。 非線形動作を定義するのは
SetShape
です。
次に、デザイナーは目的のサイズのグラフィックコンテキストを作成し、背景の赤色を設定します。
IGraphics* pGraphics = MakeGraphics(this, kWidth, kHeight); pGraphics->AttachPanelBackground(&COLOR_RED);
その後、
knob.pngがロードされ、画像を含む新しい
IKnobMultiControlが作成され、GUIにアタッチされます。
IKnobMultiControl
は、インターフェイスハンドルのクラスです。
スプライト内のフレーム数を示すためにkKnobFramesパラメーターがどのように渡されるかに注意してください。
IBitmap knob = pGraphics->LoadIBitmap(KNOB_ID, KNOB_FN, kKnobFrames); pGraphics->AttachControl(new IKnobMultiControl(this, kGainX, kGainY, kGain, &knob));
最後に、デザイナーはグラフィックスコンテキストをバインドし、プラグインのデフォルトプリセットを作成します。
MakeDefaultPreset((char *) "-", kNumPrograms);
OnParamChange
見て
OnParamChange
(ファイルの最後)。
IMutexLock
は、後で説明する概念である
ストリーミングセキュリティを提供します。 それ以外は、変更するパラメーターに応じたオプションのセットです。
case kGain: mGain = GetParam(kGain)->Value() / 100.; break;
覚えているように、
kGain
は0から100に変化します。したがって、値を100で除算した後、0から1の値を
mGain
クラスのメンバーに
mGain
ます。
そこで、GUIを作成し、
mGain
などのパラメーター
mGain
バインドするプロセスを少し見てみました。 プラグインが着信オーディオを処理する方法を見てみましょう。 この場合、オーディオストリームは
double
データ型で表されるサンプルのシーケンスであり、各サンプルには特定の時点での信号振幅が含まれています。
ProcessDoubleReplacing
関数に渡される最初のパラメーターは
double** inputs
です。
double*
を使用して、
double*
シーケンスを渡すことができます。 ただし、プラグインは2つのチャネル(ステレオ)またはそれ以上を処理するため、サンプルのシーケンスをいくつか必要とし、これを
double**
と通信します。 関数の最初の2行はこれを示しています。
double* in1 = inputs[0]; double* in2 = inputs[1];
in1
はサンプルの最初のシーケンス(左チャネル)を示し、
in2
は右チャネルのサンプルを示します。 出力バッファーに対して同様のアクションを実行した後、入力バッファーと出力バッファーの要素を反復処理できます。
for (int s = 0; s < nFrames; ++s, ++in1, ++in2, ++out1, ++out2) { *out1 = *in1 * mGain; *out2 = *in2 * mGain; }
サンプルごとに、入力値を取得し、
mGain
を乗算して出力バッファーに書き込みます。
nFrames
は、チャネルごとに使用可能なサンプル数を示しているため、バッファの長さがわかります。
プラグインをスタンドアロンアプリケーションとして実行すると、コンピューターにマイクが内蔵されている場合、スピーカーから自分の声が聞こえることに気づいたかもしれません。 これは、アプリケーションがデフォルトでこのマイクを入力ソースとして使用するためです。 これ(および他の何か)を変更するには、
設定に移動し
ます 。
Reset
機能でブレークポイントを設定します。 右側の
サンプリングレートを変更し、変更を適用します。 デバッガーは、
Reset
機能でコードの実行を中断します。
lldb
機能する右下で、
print GetSampleRate()
と入力し
print GetSampleRate()
。
デバッガから任意の関数を呼び出して、正しい値を確認することもできます。 表示されたら
、左上の[
停止]をクリックして続行することにします。
次に、コードからプラグインを作成し、ホストにアップロードします。 これは次の投稿のトピックになります。
それまでの間、
追加の読書
いくつかのギャップを埋めるために
、本発明のオリ・ラーキン氏
によるこれらのスライドを読むことを強くお勧めします。
WDL-OLに関する重要な説明の一部が含まれています。
元の記事:
martin-finke.de/blog/articles/audio-plugins-003-examining-the-code