//--------------------------------------------------------------
//  可変フィルタ用のクラス
//  （SD_PlayerSkeleton の派生クラス）
//
//  2017/04/13, Copyright (c) 2017 MIKAMI, Naoki
//--------------------------------------------------------------

#include "VariableIirFilter.hpp"

namespace Mikami
{
    VariableIirFilter::VariableIirFilter(string str,
                                         BtwthDesignerDrawer &obj)
        : SD_PlayerSkeleton(str, true),     // 第２引数は true にする
          lpHp_(BG_LEFT_, 197, BG_WIDTH_/2, BG_HEIGHT_,
                2, (string[]){"LPF", "HPF"}, 0, 0, 2, 0),
          onOff_(BG_LEFT_, 235, BG_WIDTH_/2, BG_HEIGHT_,
                 2, (string[]){"ON", "OFF"}, 0, 0, 2, 0),
          drawerObj_(obj),
          ORDER2_(drawerObj_.GetOrder()/2),
          ck_(ORDER2_), hn_(ORDER2_),
          typeLH_(BilinearDesign::LPF), on_(true)
    {
        // 周波数特性の描画
        drawerObj_.DrawResponse();

        // フィルタの準備
        drawerObj_.GetCoefficients(ck_, g0_);
        for (int k=0; k<ORDER2_; k++) hn_[k] = Biquad(ck_[k]);
    }

    // １ブロック分の信号処理の実行
    void VariableIirFilter::SignalProcessing()
    {
        // １ブロック分のデータを SD から読み込む
        sdReader_.ReadAndToMono(sn_);

        while (!mySai_.IsXferred()) {}  // データの転送が終わるまで待つ
        //--------------------------------------------------------------
        // １ブロック分の信号処理を行い，その結果を出力する
        for (int n=0; n<BUFF_SIZE_; n++)
        {
            // 縦続形の IIR フィルタ
            float yn = g0_*sn_[n];
            for (int k=0; k<ORDER2_; k++) yn = hn_[k].Execute(yn);

            // 音響信号の出力，左右チャンネルに同じものを出力する
            int16_t value = on_ ? (int16_t)yn : sn_[n];
            mySai_.Output(value, value);
        }
        //--------------------------------------------------------------
    }

    // 可変フィルタの遮断周波数変更
    void VariableIirFilter::Modefy()
    {
        // フィルタ処理の有効／無効切り替え
        if (onOff_.Touched(0)) on_ = true;
        if (onOff_.Touched(1)) on_ = false;

        // フィルタの周波数特性の変更
        int num = 0;
        if (lpHp_.GetTouchedNumber(num))
        {
            Clear();
            typeLH_ = (BilinearDesign::Type)num;
        }
        if (drawerObj_.ReDesignAndDraw(ck_, g0_, typeLH_))
            for (int k=0; k<ORDER2_; k++)
                hn_[k].SetCoefficients(ck_[k]);
    }
}
