JUCEでアプリケーション開発、音声処理のカスケード9、updateGraph関数2

1_プログラミング

updateGraph、奥が深いです。

もしかしたらupdateGraphが今回のチュートリアルの一番重要な部分かもしれないですね

引き続きupdateGraph関数を詳細に調査しています。

今回もカスケードプラグイン、チュートリアルページの「Connecting graph nodes together」のupdateGraph関数を読み解いています。

こんな人の役に立つかも

・JUCEフレームワークに入門したい人

・VST、AUプラグイン開発の最初の一歩を踏み出したい人

・JUCEのチュートリアルをやっている人

スポンサーリンク

updateGraph関数の続き

それぞれのスロットの設定が変更されたかどうかを確認します。スロット数分の3回の繰り返し処理で3スロット分の判定を行います。chiceという変数には、choicesの配列に格納されているオブジェクトの直接参照が「getReference」関数で取得できるようです。AudioParameterChoiceクラスのオブジェクトのポインタである、processorSlot1~3のアドレスを示しています。

また、slotには、ReferenceCountedArray(Arrayではない!!)のgetUncheckedでObjectClassPtrが取得されます。

       //2.スロット数分繰り返し処理で各スロットの変化を見ます。
        for (int i = 0; i < 3; ++i)
        {
            //JUCEのArrayのgetRefference。
            auto& choice = choices.getReference(i);
            //JUCEのArrayのgetUnchecked。
            auto  slot = slots.getUnchecked(i);

            //[1]スロットの選択がemptyのときです。
            if (choice->getIndex() == 0)//AudioParameterChoiceクラスのgetIndexを利用しています。
            {
                if (slot != nullptr)
                {
                    mainProcessor->removeNode(slot.get());
                    slots.set(i, nullptr);
                    hasChanged = true;
                }
            }
            //[2]スロットの選択がOscillatorのときです。
            else if (choice->getIndex() == 1)       // [2]
            {
                if (slot != nullptr)
                {
                    if (slot->getProcessor()->getName() == "Oscillator")
                        continue;

                    mainProcessor->removeNode(slot.get());
                }

                slots.set(i, mainProcessor->addNode(std::make_unique<OscillatorProcessor>()));
                hasChanged = true;
            }
            //[3]スロットの選択がGainのときです。
            else if (choice->getIndex() == 2)       // [3]
            {
                if (slot != nullptr)
                {
                    if (slot->getProcessor()->getName() == "Gain")
                        continue;

                    mainProcessor->removeNode(slot.get());
                }

                slots.set(i, mainProcessor->addNode(std::make_unique<GainProcessor>()));
                hasChanged = true;
            }
            //[4]スロットの選択がFilterのときです。
            else if (choice->getIndex() == 3)       // [4]
            {
                if (slot != nullptr)
                {
                    if (slot->getProcessor()->getName() == "Filter")
                        continue;

                    mainProcessor->removeNode(slot.get());
                }

                slots.set(i, mainProcessor->addNode(std::make_unique<FilterProcessor>()));
                hasChanged = true;
            }
        }
//...以下略...

[1]の処理は、スロットのノードを初期化するパターンです。[2]~[4]は、音声処理ノードを追加する処理になります。実質は、1と2~4の2つのパターンのプログラムになりますね。

[1]の処理について

slotは「ObjectClassPtr」なのですが、getでポインタの値が取得できるようです。

いろいろ調べて、どうやらObjectClassPtrは、「ReferenceCountedObjectPtr」とtypedefされているようです。ObjectClassPtrをReferenceCountedObjectPtrのドキュメントで同じものものとして見ることにしました。

「ReferenceCountedObjectPtr」はget関数でオブジェクトのポインタを返しますので、mainProcessorのremoveNode関数は、ノードのポインタを受け取るタイプのremoveNode関数だということもわかります。

ObjectClassPtrについては次のドキュメントを参考に追跡しました。

ReferenceCountedObjectPtrのget関数

AudioProcessorGraphのremoveNode関数

ということで、slot変数は、ノードに対するポインタ、と解釈すれば良さそうです。(AudioProcessorGraph::Nodeクラスのオブジェクトへのポインタ)

[2]〜[4]の処理について

まず、choiceは、「Element type&」を示します。最初にJuceのArrayの「getRefference」関数にて取得されています。ここで取得されるのは、choicesに格納されている、AudioParameterChoiceクラスのオブジェクトへのアドレスということでしょうか。

そのため、choiceは、アロー演算子を利用して、AudioParameterChoiceクラスのgetIndex関数にアクセスすることができます。

ここで取得できるIndexとしては、クラスの最初に定義した

juce::StringArray processorChoices { "Empty", "Oscillator", "Gain", "Filter" };

をコンストラクタにてAudioParameterChoiceに設定していますので、「==0」とすることで、スロットに設定されている音声処理が「empty」である場合を示します。(その他[1]~[3]も同様です。)

slot!=nullptrの意味

「slot!=nullptr」では、slotに何かしらの音声処理ノード(オシレータ、ゲイン、フィルタ)が設定されている場合のみの処理になります。slotが「empty」のとき、[1]の処理でslotにはnullptrが設定されますので、[0]~[3]のこの条件は飛ばされます。[1]~[3]ではそのまま他の音声処理が設定されます。

一方で、以前の設定に何かしらの音声処理(オシレータ、ゲイン、フィルター)が設定されている場合は、一度「slot!=nullptr」の条件でremoveNode関数を呼び出すことで、ノードをリセットしています。

これらの条件をクリアして、最後に、次のように、音声処理ノードをセットします。

slots.set(i, mainProcessor->addNode(std::make_unique<FilterProcessor>()));

slotsは、「ReferenceCountedArray」クラスで、このクラスの関数の「set」で音声処理ノードを設定します。iは、スロット番号で、2つ目の引数に、追加したノードを指定します。

実際の音声処理オブジェクトを追加するのは、「mainProcessor」になりますので、mainProcessorのaddNodeを呼び出してその引数として、音声処理クラス(オシレータ、ゲイン、フィルター)を渡します。

mainProcessorは「AudioProcessorGraph」クラスで、ノードのポインタを返すような関数「addNode」を持っています。

 

今回は文章でだらだらと書きすぎて申し訳ないです。JUCEは、クラスをいかに把握しているかという点も結構重要ですね。

タイトルとURLをコピーしました