LoFiBeats・84分の作業用BGMを作成しました!

JUCEプラグイン開発、シンプルなハイパスフィルターの細かな改良、スライダーskewとスロープパラメータのスライダー化

1_プログラミング

細かな改良をいくつか行いました。

市販のプラグインも研究してみるといいかも~

「シンプルなハイパスフィルター」の以前の実装記事の続きとなります。

デジタルフィルタの基礎とパラメータついて調査

ミニマムでシンプルなフィルタープラグインを実装

AudioProcessorValueTreeStateの設定手順

ミニマムでシンプルなフィルタープラグイン、カットオフ周波数可変の処理

Qパラメータを追加

スロープを急にする(-12db)

今回は、シンプルなハイパスフィルターに細かな変更を加えました。一つ目は、カットオフ周波数のスライダーにskewを追加して、中央を1khzとしました。二つ目は、スロープのパラメータをスライダーにして、-18db/octまでの減衰を行うことができるようにしました。

スポンサーリンク

こんな人の役にたつかも

・JUCEでEQを実装したい人

・JUCEのDSPモジュール、フィルターを利用したい人

・JUCEでハイパスフィルタープラグインを実装したい人

カットオフ周波数のスライダーのskew

カットオフ周波数を操作するスライダーの中心を1Kにしました。

PluginEditor.cppに次のようにプログラムを追加しました。

//PluginEditor.cpp========================================================================

Filter_plugin01AudioProcessorEditor::Filter_plugin01AudioProcessorEditor (Filter_plugin01AudioProcessor& p, juce::AudioProcessorValueTreeState& vts)
    : AudioProcessorEditor (&p), valueTreeState(vts)//audioProcessor (p)
{
    addAndMakeVisible(cutoffSlider);
    cutoffAttachment.reset(new SliderAttachment(valueTreeState, "cutoff", cutoffSlider));
    //次のプログラムを追加しました。
    cutoffSlider.setRange(20.0, 22000.0);
    cutoffSlider.setSkewFactorFromMidPoint(1000.0);

//...略...
    setSize (400, 300);
}

AudioProcessorValueTreeStateでパラメータを管理した時、スライダーの中央値を決める「setSkewFactorFromPoint」関数が、「setRange」を行なっていないと効いてこないという点が注意です。これは、以前の記事で模索した内容となります。

slopeパラメータをスライダー化

スロープパラメータをスライダーで制御するように変更しました。

スクショのように、0以上、1未満の時は1つのフィルターが効くので、-6db/octの減衰となり、1以上2未満の時は2つのハイパスフィルターが直列に連結されて-12db/octになります。スライダー値が2の時は3個のハイパスフィルターが連結されて-18db/octとなります。

実装

PluginProcessor.h

PluginProcessor.hに以下のプログラムを追加しました。追加するクラスは、プラグインのクラスになります。私のプロジェクト名はFilter_plugin01なので、Filter_plugin-1AudioProcessorクラスに追加しました。

class Filter_plugin01AudioProcessor  : public juce::AudioProcessor
{
public:
//...略...    
private:
    FilterProcessor MyFilter;
    FilterProcessor MyFilter2;
    //[1]三つ目のフィルターオブジェクトを準備しました。
    FilterProcessor MyFilter3;
    
//...略...
    //[2]slopeというパラメータを準備します。
    std::atomic<float>* slope = nullptr;
    
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Filter_plugin01AudioProcessor)
};

[1]で、3つ目のハイパスフィルターオブジェクトを定義しました。今回は、3つ直列に通すことで-18db/octを実現します。

AudioProcessorValueTreeStateのパラメータにslopeを追加します。そのために、[2]のポインタを準備します。

PluginProcessor.cpp

[1]のように、AudioProcessorValueTreeStateで「slope」というパラメータを追加しました。0~2までの値を取る「AudioParameterFloat」で作成しています。

Filter_plugin01AudioProcessor::Filter_plugin01AudioProcessor()

//...略...
            ,
            std::make_unique<juce::AudioParameterBool>("slope-12db",      // parameterID
                                                        "Slope -12DB",     // parameter name
                                                        false)
            //[1]APVTSのパラメータにFloatでパラメータを追加しました。
            ,
            std::make_unique<juce::AudioParameterFloat>("slope",      // parameterID
                                                        "Slope",     // parameter name
                                                        0.0f,     // min
                                                        2.0f, // max
                                                        0.0f)
        })
{
//...略...    
    //[2]slopeパラメータを紐付けます。そして、MyFilter3オブジェクトの初期化も行います。
    slope = parameters.getRawParameterValue("slope");
    MyFilter3.setCutoffParam(cutoffParam);
    MyFilter3.setQParam(QParam);
}

[2]では、slopeを先ほど定義したprivateなメンバ変数「slope」に紐づけ、また、MyFilter3オブジェクトの初期化を行っています。

次に、音声処理にMyFilter3を追加していきます。

prepareToPlay関数、releaseResources関数にMyFilter3を追加します。


void Filter_plugin01AudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{

//...略...
    //[1]追加しました。
    MyFilter3.prepareToPlay(sampleRate,samplesPerBlock);
}

void Filter_plugin01AudioProcessor::releaseResources()
{

//...略...
    //[2]追加しました。
    MyFilter3.releaseResources();
}

重要な、ProcessBlock関数です。今までboolで条件分岐していましたが、これをslopeのスライダー値で判定するように変更します。

void Filter_plugin01AudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    //以下の内容に変更しました。
    MyFilter.processBlock(buffer,midiMessages);
    if(*slope >= 1.0f && *slope <2.0f){
        MyFilter2.processBlock(buffer,midiMessages);
    }
    else if(*slope >=2.0f){
        MyFilter2.processBlock(buffer,midiMessages);
        MyFilter3.processBlock(buffer,midiMessages);
    }
}

0以上1未満、1以上2未満、2のとき、という3つの状態でハイパスフィルターの数が増えていきます。

PluginEditor.h

ここからはGUIに関する実装です。

エディタ側に、sliderコンポーネントを準備します。

class Filter_plugin01AudioProcessorEditor  : public juce::AudioProcessorEditor
{
//...略...   
    //スライダーと、アタッチメントオブジェクトを準備しました。
    juce::Slider SlopeSlider;
    std::unique_ptr<SliderAttachment> SlopeSliderAttachment;
    
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Filter_plugin01AudioProcessorEditor)
};

PluginEditor.cpp

準備したスライダーオブジェクトの設定を行います。エディタ側のコンストラクタにSlopeSliderを可視化して、slopeパラメータにアタッチメントで紐づけを行います。

Filter_plugin01AudioProcessorEditor::Filter_plugin01AudioProcessorEditor (Filter_plugin01AudioProcessor& p, juce::AudioProcessorValueTreeState& vts)
    : AudioProcessorEditor (&p), valueTreeState(vts)//audioProcessor (p)
{

//...略...

    //以下の内容を追加しました。
    cutoffSlider.setRange(20.0, 22000.0);
    cutoffSlider.setSkewFactorFromMidPoint(1000.0);
    addAndMakeVisible(SlopeSlider);
    SlopeSliderAttachment.reset(new SliderAttachment(valueTreeState, "slope", SlopeSlider));
    setSize (400, 300);
}

最後に、resized関数でスライダーをGUIに配置しました。

void Filter_plugin01AudioProcessorEditor::resized()
{

//...略...
    //SlopeSliderをGUIに配置しました。
    SlopeSlider.setBounds(10, 130, 200, 30);
}

改良点

改良点として、スライダーの見た目をLookAndFeelクラスで整えていきたいと思いました。特に、スロープは、現状だと連続的な値を示すスライダーになってしまっているので、3段階に変化するレバーのような見た目の離散的な変化の見た目となるようなスライダー、(レバーに近い??)に変更していきたいと思いました。

APVTSのパラメータ追加も慣れてきました♪

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