use crate::allocator::clip;
use crate::fixed::{const_lt_u32, NonNegativeFixed};
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct LrcState {
pub mean_error: NonNegativeFixed,
pub var_error: NonNegativeFixed,
pub prev_zeta: NonNegativeFixed,
pub prev_eta: NonNegativeFixed,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct LrcParams {
pub alpha: NonNegativeFixed, pub phi_max: NonNegativeFixed, pub phi_min: NonNegativeFixed, pub zeta_0: NonNegativeFixed, pub zeta_min: NonNegativeFixed, pub zeta_max: NonNegativeFixed, pub eta_0: NonNegativeFixed, pub eta_min: NonNegativeFixed, pub eta_max: NonNegativeFixed, pub k_kappa: NonNegativeFixed, pub k_d: NonNegativeFixed, pub gamma: NonNegativeFixed, pub theta: NonNegativeFixed, }
impl LrcState {
#[inline(always)]
pub fn update(
&mut self,
current_error: NonNegativeFixed,
kappa: NonNegativeFixed,
d_js: NonNegativeFixed,
params: &LrcParams,
) -> (NonNegativeFixed, NonNegativeFixed) {
let alpha = params.alpha;
let one_minus_alpha = NonNegativeFixed::ONE.saturating_sub(alpha);
let mean_next = (one_minus_alpha * self.mean_error) + (alpha * current_error);
let is_lt = const_lt_u32(current_error.val, mean_next.val);
let diff = NonNegativeFixed::from_bits(is_lt.select_u32(
mean_next.val.wrapping_sub(current_error.val),
current_error.val.wrapping_sub(mean_next.val),
));
let diff_sq = diff * diff;
let var_next = (one_minus_alpha * self.var_error) + (alpha * diff_sq);
let penalty = (params.k_kappa * kappa) + (params.k_d * d_js);
let phi = params.phi_max.saturating_sub(penalty);
let phi_safe = clip(phi, params.phi_min, params.phi_max);
let num = params.zeta_0 * phi_safe;
let denom = NonNegativeFixed::ONE + (params.gamma * var_next);
let zeta_next = num.saturating_div(denom);
let zeta_clipped = clip(zeta_next, params.zeta_min, params.zeta_max);
let eta_next = params.eta_0 + (params.theta * var_next);
let eta_clipped = clip(eta_next, params.eta_min, params.eta_max);
self.mean_error = mean_next;
self.var_error = var_next;
self.prev_zeta = zeta_clipped;
self.prev_eta = eta_clipped;
(zeta_clipped, eta_clipped)
}
}