細かな改良をいくつか行いました。
市販のプラグインも研究してみるといいかも~
「シンプルなハイパスフィルター」の以前の実装記事の続きとなります。
AudioProcessorValueTreeStateの設定手順
ミニマムでシンプルなフィルタープラグイン、カットオフ周波数可変の処理
今回は、シンプルなハイパスフィルターに細かな変更を加えました。一つ目は、カットオフ周波数のスライダーに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のパラメータ追加も慣れてきました♪