ot-tools-io 0.8.2

A library crate for reading/writing binary data files used by the Elektron Octatrack DPS-1.
Documentation
use crate::Defaults;
use ot_tools_io_derive::{ArrayDefaults, AsMutDerive, AsRefDerive, BoxedArrayDefaults};
use serde::{Deserialize, Serialize};
use std::array::from_fn;

/// Values of a Track's main LFO parameters page.
/// Note that the speed and depth settings in the LFO Setup menu are looking at these values too.
#[derive(
    Copy,
    Clone,
    Debug,
    Eq,
    Hash,
    Ord,
    PartialEq,
    PartialOrd,
    Serialize,
    Deserialize,
    AsMutDerive,
    AsRefDerive,
)]
pub struct LfoParamsValues {
    pub spd1: u8,
    pub spd2: u8,
    pub spd3: u8,
    pub dep1: u8,
    pub dep2: u8,
    pub dep3: u8,
}

impl Default for LfoParamsValues {
    fn default() -> Self {
        Self {
            spd1: 32,
            spd2: 32,
            spd3: 32,
            dep1: 0,
            dep2: 0,
            dep3: 0,
        }
    }
}

/// First set of values for a Track's LFO Setup page.
#[derive(
    Copy,
    Clone,
    Debug,
    Default,
    Eq,
    Hash,
    Ord,
    PartialEq,
    PartialOrd,
    Serialize,
    Deserialize,
    AsMutDerive,
    AsRefDerive,
)]
pub struct LfoParamsSetup1 {
    pub lfo1_pmtr: u8,
    pub lfo2_pmtr: u8,
    pub lfo3_pmtr: u8,
    pub lfo1_wave: u8,
    pub lfo2_wave: u8,
    pub lfo3_wave: u8,
}

/// Second set of values for a Track's LFO Setup page.
#[derive(
    Copy,
    Clone,
    Debug,
    Default,
    Eq,
    Hash,
    Ord,
    PartialEq,
    PartialOrd,
    Serialize,
    Deserialize,
    AsMutDerive,
    AsRefDerive,
)]
pub struct LfoParamsSetup2 {
    pub lfo1_mult: u8,
    pub lfo2_mult: u8,
    pub lfo3_mult: u8,
    pub lfo1_trig: u8,
    pub lfo2_trig: u8,
    pub lfo3_trig: u8,
}

/// A custom LFO Design -- array of 16 values.
/// 0 -> 127 values (above line) maps to 0 -> 127.
/// -1 -> -127 values (above line) seems to map to 255 -> 128.
#[derive(
    Copy,
    Clone,
    Debug,
    Eq,
    Hash,
    Ord,
    PartialEq,
    PartialOrd,
    Serialize,
    Deserialize,
    AsMutDerive,
    AsRefDerive,
    ArrayDefaults,
    BoxedArrayDefaults,
)]
pub struct CustomLfoDesign(pub [u8; 16]);

/// Default is a 16 length array with zero values
impl Default for CustomLfoDesign {
    fn default() -> Self {
        Self(from_fn(|_| 0))
    }
}

#[cfg(test)]
mod custom_lfo_design {
    use crate::parts::lfos::CustomLfoDesign;
    use crate::parts::test_helper::get_default_test_bank;
    use crate::OtToolsIoError;

    #[test]
    fn default_audio() -> Result<(), OtToolsIoError> {
        let b = get_default_test_bank()?;
        for x in b.parts_unsaved[0].audio_tracks_custom_lfo_designs.iter() {
            assert_eq!(x, &CustomLfoDesign::default());
        }
        Ok(())
    }

    #[test]
    fn default_midi() -> Result<(), OtToolsIoError> {
        let b = get_default_test_bank()?;
        for x in b.parts_unsaved[0].midi_tracks_custom_lfos.iter() {
            assert_eq!(x, &CustomLfoDesign::default());
        }
        Ok(())
    }
}

/// LFO Interpolation mask.
/// Indicates which LFO steps should have values interpolated when LFO is triggered.
/// Not sure exactly how the calculation works yet.
#[derive(
    Copy,
    Clone,
    Debug,
    Eq,
    Hash,
    Ord,
    PartialEq,
    PartialOrd,
    Serialize,
    Deserialize,
    AsMutDerive,
    AsRefDerive,
    ArrayDefaults,
    BoxedArrayDefaults,
)]
pub struct CustomLfoInterpolationMask(pub [u8; 2]);

impl Default for CustomLfoInterpolationMask {
    fn default() -> Self {
        Self(from_fn(|_| 0))
    }
}

#[cfg(test)]
mod custom_lfo_mask {
    use crate::parts::lfos::CustomLfoInterpolationMask;
    use crate::parts::test_helper::get_default_test_bank;
    use crate::OtToolsIoError;

    #[test]
    fn default_audio() -> Result<(), OtToolsIoError> {
        let b = get_default_test_bank()?;
        for x in b.parts_unsaved[0]
            .audio_tracks_custom_lfos_interpolation_masks
            .iter()
        {
            assert_eq!(x, &CustomLfoInterpolationMask::default());
        }
        Ok(())
    }

    #[test]
    fn default_midi() -> Result<(), OtToolsIoError> {
        let b = get_default_test_bank()?;
        for x in b.parts_unsaved[0]
            .midi_tracks_custom_lfos_interpolation_masks
            .iter()
        {
            assert_eq!(x, &CustomLfoInterpolationMask::default());
        }
        Ok(())
    }
}