use crate::{IntoPitch, Octave, Pitch, Pitches};
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct Note {
pub(crate) octave: Octave,
pub(crate) pitch: Pitch,
}
impl Note {
pub fn new(octave: Octave, pitch: impl IntoPitch) -> Self {
Self {
octave,
pitch: pitch.into_pitch(),
}
}
pub fn from_pitch(pitch: impl IntoPitch) -> Self {
Self {
octave: Octave::default(),
pitch: pitch.into_pitch(),
}
}
pub fn class(&self) -> Pitches {
self.pitch.class()
}
pub const fn octave(&self) -> &Octave {
&self.octave
}
pub fn octave_mut(&mut self) -> &mut Octave {
&mut self.octave
}
pub const fn pitch(&self) -> &Pitch {
&self.pitch
}
pub fn pitch_mut(&mut self) -> &mut Pitch {
&mut self.pitch
}
pub fn set_octave(&mut self, octave: Octave) {
self.octave = octave;
}
pub fn set_pitch(&mut self, Pitch(pitch): Pitch) {
self.pitch.set(pitch);
}
pub fn with_octave(self, octave: Octave) -> Self {
Self { octave, ..self }
}
pub fn with_pitch(self, Pitch(pitch): Pitch) -> Note {
Note {
octave: self.octave,
pitch: Pitch(pitch),
}
}
}
impl core::fmt::Display for Note {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}.{}", self.class(), self.octave)
}
}
unsafe impl Send for Note {}
unsafe impl Sync for Note {}
impl From<(Octave, Pitch)> for Note {
fn from((octave, pitch): (Octave, Pitch)) -> Self {
Self { octave, pitch }
}
}
impl From<Note> for (Octave, Pitch) {
fn from(note: Note) -> Self {
(note.octave, note.pitch)
}
}
impl From<Note> for Pitch {
fn from(note: Note) -> Self {
note.pitch
}
}
impl From<Pitch> for Note {
fn from(pitch: Pitch) -> Self {
Self {
octave: Octave::default(),
pitch,
}
}
}