JUCEでアプリケーション開発、位相反転を行う機能を追加する

1_プログラミング

ゲインプラグインに位相反転の機能を追加します。

実践的なJUCEプログラミングのオーディオ処理の基本が学べるね。

前回までで、ゲインプラグインの基本的な部分が出来上がりました。チュートリアルは、さらに位相の反転を行うことができる機能を追加していきます。結構本格的なゲインプラグインになってきてうれしいです。悲しきかな、macで開発できていないので、AUプラグインには出力されないことです・・・開発用のmacほしいなぁ(Windowsの環境だと基本的にAUには出力できない模様です)

進めているチュートリアルは次のページの「Adding a phase invert parameter」という項目です。

こんな人の役に立つかも

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

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

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

スポンサーリンク

手順を整理

位相反転のプログラムは、今まで見てきた手順の復習のようなイメージです。JUCEプログラミングの基本的な手順をおさらいしながら実装することができるようになっています。

①パラメータ格納用のメンバ変数をクラスに追加

②コンストラクタでパラメータの追加と初期化

③getStateInformationにパラメータ追加

④setStateInformationにパラメータ追加

⑤processBlockに音声処理の追加

⑥prepareToPlayにひとつ前バッファの準備処理を追加

この手順でプログラムを追加していきます。

この順番が基本的なパラメータと処理の追加順になりそうですね。

実装

チュートリアルに沿って、位相反転のパラメータをゲインプラグインに追加していきます。

①パラメータ格納用のメンバ変数をクラスに追加

「PluginProcessor.h」にメンバ変数を追加します。

private:
    //==============================================================================
    juce::AudioParameterFloat* gain;
    juce::AudioParameterBool* invertPhase; //メンバ変数を追加します。
 
    float previousGain;
 
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TutorialProcessor)
};

②コンストラクタでパラメータの追加と初期化

「PluginProcessor.cpp」のコンストラクタにaddParameterでパラメータの追加と初期化を行います。

GainPluginAudioProcessor::GainPluginAudioProcessor()
//...省略...
#endif
{
    addParameter(gain = new juce::AudioParameterFloat("gain", "Gain", 0.0f, 1.0f, 0.8f));
    addParameter(invertPhase = new juce::AudioParameterBool("invertPhase", "Invert Phase", false)); //追加
}

AudioParameterBoolというjuceで準備されたブーリアンのオブジェクトを使って「invertPhase」というパラメータを作成します。初期値は「false」にしておきます。UI表示上の文字列は「Incert Phase」です。

③getStateInformationにパラメータ追加

「gain」パラメータと同様に、「invertPhase」パラメータも保持するようにします。

void GainPluginAudioProcessor::getStateInformation (juce::MemoryBlock& destData)
{
    std::unique_ptr<juce::XmlElement> xml(new juce::XmlElement("ParamTutorial"));
    xml->setAttribute("gain", (double)*gain);
    xml->setAttribute("invertPhase", *invertPhase); //保持するパラメータに追加します。
    copyXmlToBinary(*xml, destData);
}

setAttribute関数に「*invertPhase」で値を渡すだけです。

④setStateInformationにパラメータ追加

同様に、パラメータ読み出し側です。

void GainPluginAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
    std::unique_ptr<juce::XmlElement> xmlState(getXmlFromBinary(data, sizeInBytes));

    if (xmlState.get() != nullptr)
    {
        if (xmlState->hasTagName("ParamTutorial"))
        {
            *gain = (float)xmlState->getDoubleAttribute("gain", 1.0);
            *invertPhase = xmlState->getBoolAttribute("invertPhase", false); //読みだすパラメータを追加します。
        }
    }
}

invertPhaseはブーリアンなので、getBoolAttributeという関数になっているところが注意点です。もし値がなかったらデフォルト値で「false」を入れるような設定になっています。

⑤processBlockに音声処理の追加

パラメータの準備が完了しましたので、実際に位相を反転させるような処理を追加していきます。もちろんprocessBlockに処理追加です。

void GainPluginAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    auto phase = *invertPhase ? -1.0f : 1.0f;  //①3項演算子でphaseの値を入力します。
    auto currentGain = *gain * phase;          //②gainの値にphaseを掛け算してcurrentGainとします。

    //この後の処理はgainを滑らかに調整する処理で、前回と同様です。
    if (currentGain == previousGain)
    {
        buffer.applyGain(currentGain);
    }
    else
    {
        buffer.applyGainRamp(0, buffer.getNumSamples(), previousGain, currentGain);
        previousGain = currentGain;
    }
}

①では、3項演算子を利用して、phaseの値を決めています。さりげなく今気づいたのですが、addParameterで追加されるパラメータはポインタで、基本的に値を得たい場合、アスタリスクで値にアクセスする必要があるようですね^^;

invertPhaseの値がTrueのときは-1.0、falseのとき1.0をauto型の「phase」変数に代入するようになっています。(autoはC++で型を推論してくれるような機能らしいです、ここは、floatになるんでしょうけれどね^^;)

今回のオーディオ処理の要所が⑦の処理です。currentGainとしている値を以前は「gain」の値そのまま利用していましたが、今回はphaseを掛け合わせることで、invertPhaseが「-1.0」のとき、ゲインの値がマイナスになり、波形が反転するようになります。ちなみに、gainの値と掛け合わせるため、先ほどの3項演算子で「-1.0f」または「1.0f」とfloat型の数値にしています。

最後に、gain値をオーディオバッファに「applyGain」で反映させて位相が反転します。

黒色の線で元のオーディオバッファ(音声データの配列)に格納されているサンプル波形、ゲインをマイナス方向で織り込ませることで波形が反転して青の線のようになります。実際には、512サンプルとかなので、上の図のように連続的な波形は少しおかしいのでしょうけれど、イメージ用ということで^^;

⑥prepareToPlayにひとつ前バッファの準備処理を追加

prepareToPlay処理のpreviousGainにもphaseの作用を反映させる必要がありますので、ここでも同様に3項演算子を利用した計算をしてpreviousGainに反映させています。

void GainPluginAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
    auto phase = *invertPhase ? -1.0f : 1.0f;
    previousGain = *gain * phase;
}

オーディオバッファに対するゲインで音量を変化させることで位相の反転ができるんですね。

今回作成したJUCEチュートリアルのVST3プラグイン、「GainPlugin」は、以下のリポジトリからcloneすることで取得できます。

>git clone https://github.com/perfectpanda-works/juce_gain_plugin.git

または、GitHubよりzip形式でダウンロードできますので、ご参考になれば幸いです。

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