//--------------------------------------------------------------
//  可変 IIR フィルタのクラス
//
//  2022/12/17, Copyright (c) 2022 MIKAMI, Naoki
//--------------------------------------------------------------

#include "BilinearDesignLH.hpp"
#include "IIR_CascadeV.hpp"

#ifndef VARIABLE_IIR_FILTER_HPP
#define VARIABLE_IIR_FILTER_HPP

namespace Mikami
{
    class VariableIir
    {
    public:
        // コンストラクタ
        VariableIir(int order, float fs, float fc0, BilinearDesign::Type type)
            : ORDER_(order), design_(order, fs), coefs_((order+1)/2)
        {
            // 最初に実行されるフィルタの設計
            design_.Execute(fc0, type, coefs_, g0_);
            // 最初に実行される LPF の係数を設定
            iirFilter_.SetCoefs(order, coefs_, g0_);
            Validate();
        }

        // IIR フィルタの実行
        float Execute(float xn) { return (this->*fPtr_)(xn); }

        // フィルタを設計し，パラメータをを設定する
        void SetParameters(float fc, BilinearDesign::Type type)
        {
            design_.Execute(fc, type, coefs_, g0_);     // フィルタの設計
            iirFilter_.SetCoefs(ORDER_, coefs_, g0_);   // 設計されたフィルタ係数の設定
        }

        // フィルタの遅延器をクリア
        void Clear() { iirFilter_.Clear(); }

        // IIR フィルタの処理を有効にする
        void Validate() { fPtr_ = &VariableIir::Filtering; }

        // IIR フィルタの処理を無効にする
        void Invalidate() { fPtr_ = &VariableIir::Through; }
            
    private:
        const int ORDER_;   // 次数

        BilinearDesign design_;         // フィルタ設計用オブジェクト生成
        Array<BiquadV::Coefs> coefs_;   // 設計された係数
        float g0_;                      // 設計された利得定数
        IirCascadeV iirFilter_;
        float (VariableIir::*fPtr_)(float);     // メンバ関数ポインタ
        
        float Through(float xn) { return xn; }  // そのまま出力
        float Filtering(float xn)               // フィルタを実行して出力
        {   return iirFilter_.Execute(xn); }

        // コピー･コンストラクタ，代入演算子禁止禁止のため
        VariableIir(const VariableIir&);
        VariableIir& operator=(const VariableIir&);
    };
}
#endif  // VARIABLE_IIR_FILTER_HPP
