より実用的にしたいので、フィルターの傾斜をきつくかけるようにしたいです。
2つのフィルターを準備して処理をつなげてみよう〜
シンプルなハイパスフィルターを改造しています。今回は、ハイパスフィルターのカーブを急にするべく、slopeというパラメータを追加してみました。まずは、1オクターブあたり-12dbとなるような設定ができるように、してみました。
この記事は、以前作成したシンプルなハイパスフィルターを改良するものですので、こちらの記事もご参照ください。
AudioProcessorValueTreeStateの設定手順
ミニマムでシンプルなフィルタープラグイン、カットオフ周波数可変の処理
こんな人の役に立つかも
・JUCEのフィルタープラグインを作成したい人
・JUCEのDSPモジュールでハイパスフィルターを作成したい人
・JUCEのプラグインプログラミングをしている人
改造の方向性
単体のフィルターが1オクターブあたり-6dbとなる減衰なので、これを直列に2つ繋げるようにしました。
フィルターを元々、2つ準備してトグルスイッチをオンとすることでもう一つのフィルターがオンとなるようなシンプルな仕組みで実装を行いました。
プロセッサ側
PluginProcessor.h
まずは、PluginProcessor.hの「●●AudioProcessor」(私の作成しているプラグインではfilter_plugin01AudioProcessorクラスで、●●にはプロジェクト名が任意で入ります。)クラスにもう一つのフィルターを作成します。
「MyFilter2」というオブジェクトをprivateなメンバとして保持します。
そして、このフィルターをGUIでオンオフしたいので、オンオフの数値も「slope_12db」というパラメータで制御したいと思います。
private:
FilterProcessor MyFilter;
//[1]新たにフィルターオブジェクトを宣言します。
FilterProcessor MyFilter2;
//...略...
//[2]もう一つのフィルターを通すかどうかをパラメータとして保持します。
std::atomic<float>* slope_12db = nullptr;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Filter_plugin01AudioProcessor)
};
PluginProcessor.cpp
コンストラクタで追加したフィルターオブジェクトを初期化します。また、2個目のフィルターをオンオフするパラメータを「slope-12db」というIDで作成しました。
Filter_plugin01AudioProcessor::Filter_plugin01AudioProcessor()
#ifndef JucePlugin_PreferredChannelConfigurations
//...略...
#endif
,MyFilter()
,MyFilter2()//[1]メンバイニシャライザで初期化しました。
,parameters(*this, nullptr, juce::Identifier("APVTSTutorial"),
{
//...略...
0.70710678f)
//[2]パラメータも追加します。
,
std::make_unique<juce::AudioParameterBool>("slope-12db",//ID
"Slope -12DB",//name
false)
})
{
//...略...
//[3]MyFilter2オブジェクトの設定を行います。
MyFilter2.setCutoffParam(cutoffParam);
MyFilter2.setQParam(QParam);
//[4]オンオフのパラメータをAPVTSと紐付けます。
slope_12db = parameters.getRawParameterValue("slope-12db");
float val = *slope_12db;
}
コンストラクタの中の処理として、[3]ではMyFilter2オブジェクトにパラメータのポインタを与えて、オブジェクト内でも利用できるように設定します。
今回、Qパラメータは、共有するような形で設定しています。そのため、2つ目のフィルターをオンにしたら、Qによるカットオフ付近の膨らみが二倍になってしまうので、このあたりはもう少し考慮が必要な雰囲気です。ここの処理の仕方は、プラグインの個性にもなってくるのだと思います。
[4]では、2つ目のフィルターをオンオフするためのパラメータをslope_12dbのメンバに紐づけています。パラメータの紐付けは、AudioProcessorValueTreeStateの設定手順も参考にしていただければと思います。
音声処理関数
prepareToPlayとreleaseResources関数にそれぞれMyFilter2を追加します。
void Filter_plugin01AudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
{
MyFilter.prepareToPlay(sampleRate,samplesPerBlock);
MyFilter2.prepareToPlay(sampleRate,samplesPerBlock);//追加しました。
}
void Filter_plugin01AudioProcessor::releaseResources()
{
MyFilter.releaseResources();
MyFilter2.releaseResources();//追加しました。
}
次に、processBlockの処理を記載します。
void Filter_plugin01AudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
MyFilter.processBlock(buffer,midiMessages);
//追加しました。
if(*slope_12db >= 1.0f){
MyFilter2.processBlock(buffer,midiMessages);
}
}
slope_12db変数の値をもとに、MyFilter2を処理するかどうかを決めます。値としてはfloat型の変数ですが、APVTSとしてはboolとして扱いますので、トグルボタンのオンオフによって、ここには1.0fまたは0.0fの値が現れます。
トグルボタンをオンにして、1.0fになったら、processBlockでは直列で2つのハイパスフィルターが処理されることになります。
めちゃくちゃどストレートな処理・・・
この考えが私の限界です・・・
エディタ側
次に、2つ目のパラメータをオンオフするためのトグルボタンをGUIに配置して、先ほどのパラメータ「slope-12db」と紐付けます。
PluginEditor.h
GUIのトグルボタンを作成するためにいくつかのオブジェクトを準備します。
class Filter_plugin01AudioProcessorEditor : public juce::AudioProcessorEditor
{
public:
//...略...
//[1]publicなメンバにボタンアタッチメントクラスのオブジェクトを作成します。
typedef juce::AudioProcessorValueTreeState::ButtonAttachment ButtonAttachment;
private:
//...略...
//[2]トグルボタンなどを準備します。
juce::ToggleButton slope_12db_button;
std::unique_ptr<ButtonAttachment> slope12dbAttachment;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Filter_plugin01AudioProcessorEditor)
};
次に、コンストラクタでボタンを可視化して、アタッチメントオブジェクトを使って、パラメータに紐付けを行います。
Filter_plugin01AudioProcessorEditor::Filter_plugin01AudioProcessorEditor (Filter_plugin01AudioProcessor& p, juce::AudioProcessorValueTreeState& vts)
: AudioProcessorEditor (&p), valueTreeState(vts)//audioProcessor (p)
{
//...略...
//ボタンを初期化して、パラメータに紐付けます。
addAndMakeVisible(slope_12db_button);
slope12dbAttachment.reset (new ButtonAttachment (valueTreeState, "slope-12db", slope_12db_button));
setSize (400, 300);
}
最後に、resized関数で、ボタンをGUIに配置します。
void Filter_plugin01AudioProcessorEditor::resized()
{
//...略...
//GUIに配置します。
slope_12db_button.setBounds(10, 90, 30, 30);
}