use crate::clap::plugin::{CommandConsumer, NamClapShared};
use crate::clap::processor::dsp::orchestrator::ScheduledEvent;
use crate::common::params::{ActivationPrecision, RtPluginParams};
use crate::common::spsc::{GcItem, GcOverflowBuffer, RtStatusFlags};
use crate::dsp::adaptive::AdaptiveCompute;
use crate::dsp::cabsim::adapter::CabSimAdapter;
use crate::dsp::gate::{DynamicHysteresis, GateParams};
use crate::dsp::oversample::OversampleEngine;
use crate::dsp::resampler::NamResampler;
use crate::dsp::smoother::ParamSmoother;
use crate::math::common::AlignedVec;
use crate::math::dsp::gain_lut::GainLUT;
use crate::models::StaticModel;
use clack_plugin::host::HostAudioProcessorHandle;
use rtrb::{Consumer, Producer};
use std::sync::Arc;
pub(crate) const BYPASS_XFADE_SAMPLES: usize = 64;
const BYPASS_XFADE_INV: f32 = 1.0 / BYPASS_XFADE_SAMPLES as f32;
#[derive(Clone, Copy)]
pub(crate) struct BypassCrossfader {
pub(crate) target: bool,
pub(crate) active: bool,
pub(crate) mix: f32,
pub(crate) step: f32,
pub(crate) remaining: usize,
}
impl BypassCrossfader {
pub(crate) fn new(initial_bypass: bool) -> Self {
let mix = if initial_bypass { 0.0 } else { 1.0 };
Self {
target: initial_bypass,
active: false,
mix,
step: 0.0,
remaining: 0,
}
}
pub(crate) fn trigger(&mut self, target: bool) {
if self.target == target {
return;
}
self.target = target;
self.active = true;
self.remaining = BYPASS_XFADE_SAMPLES;
if target {
self.step = -BYPASS_XFADE_INV;
} else {
self.step = BYPASS_XFADE_INV;
}
}
}
pub struct NamClapProcessor<'a> {
pub(crate) model_l: Option<Box<StaticModel>>,
pub(crate) cabsim_adapter: Option<CabSimAdapter>,
pub(crate) resampler: Box<NamResampler>,
pub(crate) os_l: Box<OversampleEngine>,
pub(crate) os_r: Box<OversampleEngine>,
pub(crate) params: RtPluginParams,
pub(crate) buf_host_l: AlignedVec<f32>,
pub(crate) buf_host_r: AlignedVec<f32>,
pub(crate) buf_mid_l: AlignedVec<f32>,
pub(crate) buf_mid_r: AlignedVec<f32>,
pub(crate) buf_model_l: AlignedVec<f32>,
pub(crate) buf_model_r: AlignedVec<f32>,
pub(crate) buf_out_l: AlignedVec<f32>,
pub(crate) buf_out_r: AlignedVec<f32>,
pub(crate) buf_os_in_l: AlignedVec<f32>,
pub(crate) buf_os_in_r: AlignedVec<f32>,
pub(crate) buf_os_model_l: AlignedVec<f32>,
pub(crate) buf_os_model_r: AlignedVec<f32>,
pub(crate) silence_hyst: DynamicHysteresis,
pub(crate) mono_hyst: DynamicHysteresis,
pub(crate) process_mono: bool,
pub(crate) scheduled_events: Vec<ScheduledEvent>,
pub(crate) bypass_xfade: BypassCrossfader,
pub(crate) buf_xfade_dry_l: AlignedVec<f32>,
pub(crate) buf_xfade_dry_r: AlignedVec<f32>,
pub(crate) rt_status: Arc<RtStatusFlags>,
pub(crate) adaptive_compute: AdaptiveCompute,
pub(crate) shared: &'a NamClapShared,
pub(crate) smoother_in: ParamSmoother,
pub(crate) smoother_out: ParamSmoother,
pub(crate) model_input_mult_adj: f32,
pub(crate) model_output_mult_adj: f32,
pub(crate) parking_lot: [Option<GcItem>; 16],
pub(crate) cmd_consumer: CommandConsumer<'a>,
pub(crate) slimmable_rx: Consumer<Option<Box<StaticModel>>>,
pub(crate) gc_tx: Producer<GcItem>,
pub(crate) gc_overflow: Arc<GcOverflowBuffer>,
pub(crate) mod_input_gain: f32,
pub(crate) mod_output_gain: f32,
pub(crate) mod_gate_thresh: f32,
pub(crate) cached_threshold_open_sq: f32,
pub(crate) cached_threshold_close_sq: f32,
pub(crate) cached_gate_params: GateParams,
pub(crate) gate_dirty: bool,
pub(crate) cycles_since_telemetry: u32,
pub(crate) prio_checked: bool,
pub(crate) last_seen_generation: u32,
pub(crate) max_frames_count: usize,
pub(crate) last_render_mode: u32,
pub(crate) realtime_activation: ActivationPrecision,
pub(crate) gain_lut: &'static GainLUT,
pub(crate) cabsim_tail_remaining: usize,
pub(crate) host: HostAudioProcessorHandle<'a>,
}