use super::{PitchTy, Pitches};
use crate::PyMod;
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[repr(transparent)]
pub struct Pitch(pub PitchTy);
impl Pitch {
pub const MOD: PitchTy = crate::MODULUS;
pub fn new(pitch: PitchTy) -> Self {
Self(pitch)
}
pub fn into_inner(self) -> PitchTy {
self.0
}
pub const fn get(&self) -> &PitchTy {
&self.0
}
pub fn get_mut(&mut self) -> &mut PitchTy {
&mut self.0
}
pub fn set(&mut self, val: PitchTy) {
self.0 = val;
}
}
impl Pitch {
pub fn class(&self) -> Pitches {
Pitches::try_from_value(self.0.pymod(Self::MOD).abs()).unwrap()
}
pub fn into_class(self) -> Pitches {
self.class()
}
pub fn map<F>(self, f: F) -> Self
where
F: Fn(PitchTy) -> PitchTy,
{
Self(f(self.0))
}
pub fn map_mut<F>(&mut self, mut f: F)
where
F: FnMut(&mut PitchTy),
{
f(&mut self.0)
}
pub fn map_once<F>(self, f: F) -> Self
where
F: FnOnce(PitchTy) -> PitchTy,
{
Self(f(self.0))
}
pub fn abs(self) -> Self {
self.map(|p| p.abs())
}
pub fn absmod(self) -> Self {
self.map(|p| p.pymod(Self::MOD).abs())
}
pub fn pymod(self) -> Self {
self.map(|p| p.pymod(Self::MOD))
}
}
impl AsRef<PitchTy> for Pitch {
fn as_ref(&self) -> &PitchTy {
&self.0
}
}
impl AsMut<PitchTy> for Pitch {
fn as_mut(&mut self) -> &mut PitchTy {
&mut self.0
}
}
impl core::borrow::Borrow<PitchTy> for Pitch {
fn borrow(&self) -> &PitchTy {
&self.0
}
}
impl core::borrow::BorrowMut<PitchTy> for Pitch {
fn borrow_mut(&mut self) -> &mut PitchTy {
&mut self.0
}
}
impl Default for Pitch {
fn default() -> Self {
Self(super::Natural::default().pitch())
}
}
impl core::ops::Deref for Pitch {
type Target = PitchTy;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl core::ops::DerefMut for Pitch {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
impl core::fmt::Debug for Pitch {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_tuple(&self.class().to_string())
.field(&self.0)
.finish()
}
}
impl core::fmt::Display for Pitch {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}({})", self.class(), self.0)
}
}
macro_rules! impl_fmt {
(@impl $trait:ident) => {
impl ::core::fmt::$trait for Pitch {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
::core::fmt::$trait::fmt(&self.0, f)
}
}
};
($($trait:ident),* $(,)?) => {
$(
impl_fmt!(@impl $trait);
)*
};
}
impl_fmt!(Binary, LowerHex, Octal, UpperHex);
impl From<PitchTy> for Pitch {
fn from(pitch: PitchTy) -> Self {
Self(pitch)
}
}
impl From<Pitch> for PitchTy {
fn from(pitch: Pitch) -> Self {
pitch.0
}
}
impl From<Pitches> for Pitch {
fn from(pitch: Pitches) -> Self {
Self(pitch.value())
}
}
impl From<Pitch> for Pitches {
fn from(pitch: Pitch) -> Self {
pitch.class()
}
}