パート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を指定できます。
// 4 chars, single quotes. At least one capital letter #define PLUG_UNIQUE_ID 'Ipef' // make sure this is not the same as BUNDLE_MFR #define PLUG_MFR_ID 'Acme'
IDは、プラグインの一般的なカタログ化にとって重要です。 ここで登録できます 。 56行目以降は、プラグインの起動時に表示されるボリュームノブのIDとイメージへのパスをさらに決定します。
// Unique IDs for each image resource. #define KNOB_ID 101 // Image resource locations for this plug. #define KNOB_FN "resources/img/knob.png"
ナビゲータで検索し、 リソース→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に設定します。
次に、コンストラクターの実装が開始されます。 プラグインの属性が設定されます:
//arguments are: name, defaultVal, minVal, maxVal, step, label GetParam(kGain)->InitDouble("Gain", 50., 0., 100.0, 0.01, "%");
これまでの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