weresocool_core 1.0.43

***** WereSoCool __!Now In Stereo!__ ****** Make cool sounds. Impress your friends.
Documentation
use crate::generation::Op4D;
use num_rational::Rational64;
use serde::{Deserialize, Serialize};
use weresocool_ast::{NameSet, OscType, PointOp, ASR};
use weresocool_instrument::Basis;
use weresocool_shared::r_to_f64;

#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum EventType {
    On,
    Off,
}

#[derive(Debug, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct TimedOp {
    pub t: Rational64,
    pub event_type: EventType,
    pub voice: usize,
    pub event: usize,
    pub attack: Rational64,
    pub decay: Rational64,
    pub reverb: Rational64,
    pub asr: ASR,
    pub portamento: Rational64,
    pub osc_type: OscType,
    pub fm: Rational64,
    pub fa: Rational64,
    pub pm: Rational64,
    pub pa: Rational64,
    pub g: Rational64,
    pub l: Rational64,
    pub names: Vec<String>,
}

impl TimedOp {
    pub fn to_op_4d(&self, basis: &Basis) -> Op4D {
        let zero = Rational64::new(0, 1);
        let is_silent = (self.fm == zero && self.fa < Rational64::new(20, 1)) || self.g == zero;
        let y = if is_silent {
            0.0
        } else {
            r_to_f64(basis.f).mul_add(r_to_f64(self.fm), r_to_f64(self.fa))
        };
        let z = if is_silent {
            0.0
        } else {
            r_to_f64(basis.g) * r_to_f64(self.g)
        };
        Op4D {
            l: r_to_f64(self.l) * r_to_f64(basis.l),
            t: r_to_f64(self.t) * r_to_f64(basis.l),
            x: ((r_to_f64(basis.p) + r_to_f64(self.pa)) * r_to_f64(self.pm)),
            y: y.log10(),
            z,
            voice: self.voice,
            event: self.event,
            names: self.names.to_owned(),
        }
    }

    #[allow(clippy::missing_const_for_fn)]
    pub fn to_point_op(&self) -> PointOp {
        PointOp {
            fm: self.fm,
            fa: self.fa,
            pm: self.pm,
            pa: self.pa,
            g: self.g,
            l: self.l,
            reverb: Some(self.reverb),
            attack: self.decay,
            decay: self.decay,
            asr: self.asr,
            portamento: self.portamento,
            osc_type: self.osc_type,
            names: NameSet::new(),
        }
    }

    pub fn from_point_op(
        point_op: &PointOp,
        time: &mut Rational64,
        voice: usize,
        event: usize,
    ) -> Self {
        let timed_op = Self {
            fm: point_op.fm,
            fa: point_op.fa,
            pm: point_op.pm,
            pa: point_op.pa,
            attack: point_op.attack,
            osc_type: point_op.osc_type,
            decay: point_op.decay,
            reverb: point_op
                .reverb
                .unwrap_or_else(|| Rational64::from_integer(0)),
            asr: point_op.asr,
            portamento: point_op.portamento,
            g: point_op.g,
            l: point_op.l,
            t: *time,
            event_type: EventType::On,
            voice,
            event,
            names: point_op.names.to_vec(),
        };

        *time += point_op.l;

        timed_op
    }
}