JUCEでアプリケーション開発、音声処理のカスケード6、FilterProcessor

1_プログラミング

引き続き、フィルターの実装を行っていきます。

フィルターを組み合わせると、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;
};
タイトルとURLをコピーしました