use crate::traits::FloatScalar;
use super::biquad::{
bilinear_hp_pair, bilinear_hp_real, bilinear_lp_pair, bilinear_lp_real, BiquadCascade,
};
use super::{validate_design_params, ControlError};
pub fn butterworth_lowpass<T: FloatScalar, const N: usize>(
order: usize,
cutoff: T,
sample_rate: T,
) -> Result<BiquadCascade<T, N>, ControlError> {
validate_design_params::<T, N>(order, cutoff, sample_rate)?;
let two = T::one() + T::one();
let pi = T::from(core::f64::consts::PI).unwrap();
let wa = two * sample_rate * (pi * cutoff / sample_rate).tan();
let c = two * sample_rate;
let n = order;
let nf = T::from(n).unwrap();
let mut sections = [super::biquad::Biquad::passthrough(); N];
let mut idx = 0;
let num_pairs = n / 2;
for k in 0..num_pairs {
let kf = T::from(k).unwrap();
let theta = pi * (two * kf + nf + T::one()) / (two * nf);
let sigma = wa * theta.cos();
let omega = wa * theta.sin();
sections[idx] = bilinear_lp_pair(sigma, omega, wa, c);
idx += 1;
}
if n % 2 == 1 {
let sigma = -wa;
sections[idx] = bilinear_lp_real(sigma, wa, c);
}
Ok(BiquadCascade { sections })
}
pub fn butterworth_highpass<T: FloatScalar, const N: usize>(
order: usize,
cutoff: T,
sample_rate: T,
) -> Result<BiquadCascade<T, N>, ControlError> {
validate_design_params::<T, N>(order, cutoff, sample_rate)?;
let two = T::one() + T::one();
let pi = T::from(core::f64::consts::PI).unwrap();
let wa = two * sample_rate * (pi * cutoff / sample_rate).tan();
let c = two * sample_rate;
let n = order;
let nf = T::from(n).unwrap();
let mut sections = [super::biquad::Biquad::passthrough(); N];
let mut idx = 0;
let num_pairs = n / 2;
for k in 0..num_pairs {
let kf = T::from(k).unwrap();
let theta = pi * (two * kf + nf + T::one()) / (two * nf);
let sigma = wa * theta.cos();
let omega = wa * theta.sin();
sections[idx] = bilinear_hp_pair(sigma, omega, wa, c);
idx += 1;
}
if n % 2 == 1 {
let sigma = -wa;
sections[idx] = bilinear_hp_real(sigma, wa, c);
}
Ok(BiquadCascade { sections })
}