use super::{
calc, hz_from_letter_octave, mel_from_letter_octave, perc_from_letter_octave,
scaled_perc_from_letter_octave, step_from_letter_octave, Hz, Letter, Mel, Perc, ScaleWeight,
ScaledPerc, Step, DEFAULT_SCALE_WEIGHT,
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
pub type Octave = i32;
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct LetterOctave(pub Letter, pub Octave);
impl LetterOctave {
#[inline]
pub fn letter_octave(self) -> (Letter, Octave) {
let LetterOctave(letter, octave) = self;
(letter, octave)
}
#[inline]
pub fn letter(self) -> Letter {
let LetterOctave(letter, _) = self;
letter
}
#[inline]
pub fn octave(self) -> Octave {
let LetterOctave(_, octave) = self;
octave
}
#[inline]
pub fn hz(self) -> calc::Hz {
let LetterOctave(letter, octave) = self;
hz_from_letter_octave(letter, octave)
}
#[inline]
pub fn to_hz(self) -> Hz {
Hz(self.hz())
}
#[inline]
pub fn mel(self) -> calc::Mel {
let LetterOctave(letter, octave) = self;
mel_from_letter_octave(letter, octave)
}
#[inline]
pub fn to_mel(self) -> Mel {
Mel(self.mel())
}
#[inline]
pub fn perc(self) -> calc::Perc {
let LetterOctave(letter, octave) = self;
perc_from_letter_octave(letter, octave)
}
#[inline]
pub fn to_perc(self) -> Perc {
Perc(self.perc())
}
#[inline]
pub fn scaled_perc_with_weight(self, weight: ScaleWeight) -> calc::Perc {
let LetterOctave(letter, octave) = self;
scaled_perc_from_letter_octave(letter, octave, weight)
}
#[inline]
pub fn scaled_perc(self) -> calc::Perc {
self.scaled_perc_with_weight(DEFAULT_SCALE_WEIGHT)
}
#[inline]
pub fn to_scaled_perc_with_weight(self, weight: ScaleWeight) -> ScaledPerc {
ScaledPerc(self.scaled_perc_with_weight(weight), weight)
}
#[inline]
pub fn to_scaled_perc(self) -> ScaledPerc {
self.to_scaled_perc_with_weight(DEFAULT_SCALE_WEIGHT)
}
#[inline]
pub fn step(self) -> calc::Step {
let LetterOctave(letter, octave) = self;
step_from_letter_octave(letter, octave)
}
#[inline]
pub fn to_step(self) -> Step {
Step(self.step())
}
}
impl Add for LetterOctave {
type Output = LetterOctave;
#[inline]
fn add(self, rhs: LetterOctave) -> LetterOctave {
(self.to_step() + rhs.to_step()).to_letter_octave()
}
}
impl Sub for LetterOctave {
type Output = LetterOctave;
#[inline]
fn sub(self, rhs: LetterOctave) -> LetterOctave {
(self.to_step() - rhs.to_step()).to_letter_octave()
}
}
impl Mul for LetterOctave {
type Output = LetterOctave;
#[inline]
fn mul(self, rhs: LetterOctave) -> LetterOctave {
(self.to_step() * rhs.to_step()).to_letter_octave()
}
}
impl Div for LetterOctave {
type Output = LetterOctave;
#[inline]
fn div(self, rhs: LetterOctave) -> LetterOctave {
(self.to_step() / rhs.to_step()).to_letter_octave()
}
}
impl Rem for LetterOctave {
type Output = LetterOctave;
#[inline]
fn rem(self, rhs: LetterOctave) -> LetterOctave {
(self.to_step() % rhs.to_step()).to_letter_octave()
}
}
impl Neg for LetterOctave {
type Output = LetterOctave;
#[inline]
fn neg(self) -> LetterOctave {
(-self.to_step()).to_letter_octave()
}
}
impl PartialEq for LetterOctave {
#[inline]
fn eq(&self, other: &LetterOctave) -> bool {
let LetterOctave(letter, octave) = *self;
let LetterOctave(other_letter, other_octave) = *other;
letter == other_letter && octave == other_octave
}
}
impl Eq for LetterOctave {}
impl PartialOrd for LetterOctave {
#[inline]
fn partial_cmp(&self, other: &LetterOctave) -> Option<Ordering> {
let LetterOctave(letter, octave) = *self;
let LetterOctave(other_letter, other_octave) = *other;
match octave.partial_cmp(&other_octave) {
Some(Ordering::Equal) => letter.partial_cmp(&other_letter),
ordering => ordering,
}
}
}
impl Ord for LetterOctave {
#[inline]
fn cmp(&self, other: &LetterOctave) -> Ordering {
self.partial_cmp(other).unwrap()
}
}