引き続き、フィルターの実装を行っていきます。
フィルターを組み合わせると、EQとか作れそうだ~
JUCEプログラミングチュートリアル、エフェクトを数珠繋ぎで実装するためのプラグイン、CascadePluginの3つ目のエフェクトであるフィルターを実装します。ベースクラスを継承して、作成していきます。
進めているチュートリアルは次のページの「Implimenting a filter」になります。
こんな人の役に立つかも
・JUCEフレームワークに入門したい人
・VST、AUプラグイン開発の最初の一歩を踏み出したい人
・JUCEのチュートリアルをやっている人
Filterクラスの実装
今回実装するフィルターは、カットオフ周波数が1kHzのハイパスフィルターを実装するようです。1kHz以下の低い音を遮断するようなフィルターです。
ベースクラスを継承
フィルターのクラス「FilterProcessor」を「PluginProcessor.h」の前回実装したGainProcessorの下に記載していきます。
class FilterProcessor : public ProcessorBase
{
public:
FilterProcessor() {}
//...
const juce::String getName() const override { return "Filter"; }
private:
juce::dsp::ProcessorDuplicator<juce::dsp::IIR::Filter<float>, juce::dsp::IIR::Coefficients<float>> filter;
};
引き続き、プラグインの基本構造である関数、「prepareToPlay」「processBlock」「reset」の関数を追記していきます。
prepareToPlay
ここでは、フィルターのパラメータ設定を行います。
void prepareToPlay(double sampleRate, int samplesPerBlock) override
{
//①IIR::CoefficientsクラスのmakeHighPass関数でハイパスフィルターの設定を行います。
*filter.state = *juce::dsp::IIR::Coefficients<float>::makeHighPass(sampleRate, 1000.0f);
//②フィルターのDSPモジュールへサンプルレートとオーディオバッファ数を渡します。
juce::dsp::ProcessSpec spec{ sampleRate, static_cast<juce::uint32> (samplesPerBlock), 2 };
filter.prepare(spec);
}
①のようにして、ハイパスフィルターの設定を行うことができるようです。「dsp::IIR::Coefficients」の「makeHighPass」関数でハイパスフィルターを設定できます。他にもローパスやノッチ、バンドパスなど、基本的なフィルターが関数として準備されています。
次のページで、フィルターの関数を確認することができます。
processBlock関数
processBlock関数に関しては、他のプロセッサクラスと同じように、オーディオバッファをDSPモジュールに渡す流れのプログラムを追記するだけです。
void processBlock(juce::AudioSampleBuffer& buffer, juce::MidiBuffer&) override
{
juce::dsp::AudioBlock<float> block(buffer);
juce::dsp::ProcessContextReplacing<float> context(block);
filter.process(context);
}
DSPモジュールを利用する場合、ほぼ、機能がモジュールから提供されるので、prepareToPlayでの機能設定がメインの音声処理になってくるのですね。
reset関数
今までのプロセッサクラスと同じように、DSPモジュール(今回はfilter)のリセット関数を呼び出します。
void reset() override
{
filter.reset();
}
だんだん、形も見慣れてきましたね~
プログラム全体
今回追記したFilterクラスの全体プログラムになります。
class FilterProcessor : public ProcessorBase
{
public:
FilterProcessor() {}
void prepareToPlay(double sampleRate, int samplesPerBlock) override
{
*filter.state = *juce::dsp::IIR::Coefficients<float>::makeHighPass(sampleRate, 1000.0f);
juce::dsp::ProcessSpec spec{ sampleRate, static_cast<juce::uint32> (samplesPerBlock), 2 };
filter.prepare(spec);
}
void processBlock(juce::AudioSampleBuffer& buffer, juce::MidiBuffer&) override
{
juce::dsp::AudioBlock<float> block(buffer);
juce::dsp::ProcessContextReplacing<float> context(block);
filter.process(context);
}
void reset() override
{
filter.reset();
}
const juce::String getName() const override { return "Filter"; }
private:
juce::dsp::ProcessorDuplicator<juce::dsp::IIR::Filter<float>, juce::dsp::IIR::Coefficients<float>> filter;
};