//////// フィルタ ////////////////////////////////
struct F_COEFS { float b0_a0, b1_a0, b2_a0,
                              a1_a0, a2_a0; };
struct F_COEFS Fil_table[6][121]; // フィルタ係数群テーブル
static volatile uint32_t Fil_cut = 120; // カットオフ設定値
static volatile uint32_t Fil_res = 0;   // レゾナンス設定値

static void Fil_init() {
  for (uint32_t res = 0; res < 6; ++res) {
    for (uint32_t cut = 0; cut < 121; ++cut) {
      float f0    = 19912.1F
                   * powf(2, (cut - 120.0F) / 12);
      float w0    = 2 * PI * f0 / FS;
      float q     = powf(sqrtf(2), res - 1.0F);
      float alpha = sinf(w0) / (2 * q);
      float b0    = (1 - cosf(w0)) / 2;
      float b1    =  1 - cosf(w0);
      float b2    = (1 - cosf(w0)) / 2;
      float a0    =  1 + alpha;
      float a1    = -2 * cosf(w0);
      float a2    =  1 - alpha;
      Fil_table[res][cut].b0_a0 = b0 / a0;
      Fil_table[res][cut].b1_a0 = b1 / a0;
      Fil_table[res][cut].b2_a0 = b2 / a0;
      Fil_table[res][cut].a1_a0 = a1 / a0;
      Fil_table[res][cut].a2_a0 = a2 / a0;
    }
  }
}
static inline float Fil_process(float x0) {
  static uint32_t f_counter = 0;       // フィルタ処理回数
  static uint32_t curr_cut  = 0;       // カットオフ現在値
  uint32_t        targ_cut  = Fil_cut; // カットオフ目標値
  uint32_t delta = ((++f_counter & 0xF) == 0);
  curr_cut += (curr_cut < targ_cut) * delta;
  curr_cut -= (curr_cut > targ_cut) * delta;
  struct F_COEFS* coefs =
    &Fil_table[Fil_res][curr_cut];

  static float x1 = 0, x2 = 0, y1 = 0, y2 = 0;
  float y0 = (coefs->b0_a0 * x0)
      + (coefs->b1_a0 * x1) + (coefs->b2_a0 * x2)
      - (coefs->a1_a0 * y1) - (coefs->a2_a0 * y2);
  x2 = x1; y2 = y1; x1 = x0; y1 = y0;
  return y0;
}
