amm_sdk 0.4.0

Abstract Music Manipulation (AMM) Rust SDK
Documentation
use amm_internal::amm_prelude::*;
use amm_macros::{JsonDeserialize, JsonSerialize};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;

#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, JsonDeserialize, JsonSerialize)]
pub enum PitchName {
  #[default]
  Rest,
  A,
  B,
  C,
  D,
  E,
  F,
  G,
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, JsonDeserialize, JsonSerialize)]
pub struct Pitch {
  pub name: PitchName,
  pub octave: u8,
}

#[cfg_attr(target_arch = "wasm32", wasm_bindgen)]
impl Pitch {
  #[must_use]
  pub fn new(name: PitchName, octave: u8) -> Self {
    Self { name, octave }
  }

  #[must_use]
  pub fn new_rest() -> Self {
    Self {
      name: PitchName::Rest,
      octave: 0,
    }
  }

  #[must_use]
  pub fn is_rest(&self) -> bool {
    self.name == PitchName::Rest
  }

  #[must_use]
  #[allow(clippy::cast_possible_wrap)]
  pub(crate) fn value(self) -> (usize, i8) {
    match self.name {
      PitchName::Rest => (0, 0),
      PitchName::A => (1, (12 * self.octave) as i8 - 48),
      PitchName::B => (2, (2 + (12 * self.octave)) as i8 - 48),
      PitchName::C => (3, (3 + (12 * self.octave)) as i8 - 60),
      PitchName::D => (4, (5 + (12 * self.octave)) as i8 - 60),
      PitchName::E => (5, (7 + (12 * self.octave)) as i8 - 60),
      PitchName::F => (6, (8 + (12 * self.octave)) as i8 - 60),
      PitchName::G => (7, (10 + (12 * self.octave)) as i8 - 60),
    }
  }
}

impl Ord for Pitch {
  fn cmp(&self, other: &Self) -> core::cmp::Ordering {
    self.value().1.cmp(&other.value().1)
  }
}

impl PartialOrd for Pitch {
  fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
    Some(self.cmp(other))
  }
}

#[cfg(feature = "print")]
impl core::fmt::Display for PitchName {
  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
    write!(
      f,
      "{}",
      match self {
        Self::Rest => "Rest",
        Self::A => "A",
        Self::B => "B",
        Self::C => "C",
        Self::D => "D",
        Self::E => "E",
        Self::F => "F",
        Self::G => "G",
      }
    )
  }
}

#[cfg(feature = "print")]
impl core::fmt::Display for Pitch {
  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
    write!(
      f,
      "{}",
      if self.name == PitchName::Rest {
        String::new()
      } else {
        format!("{}{}", self.name, self.octave)
      }
    )
  }
}