rstmt_core/notes/
note_base.rs

1/*
2    Appellation: note <module>
3    Contrib: @FL03
4*/
5use crate::freq::RawFrequency;
6use crate::octave::Octave;
7use crate::pitch::{self, Pitch, PitchClass};
8
9/// The [`NoteBase`] is a generic representation of a musical note
10#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
11#[cfg_attr(
12    feature = "serde",
13    derive(serde::Deserialize, serde::Serialize),
14    serde(deny_unknown_fields, rename_all = "snake_case")
15)]
16#[repr(C)]
17pub struct NoteBase<T, Cls = pitch::C> {
18    pub(crate) class: Cls,
19    pub(crate) octave: Octave,
20    pub(crate) pitch: Pitch<T>,
21}
22
23impl<T, Cls> NoteBase<T, Cls>
24where
25    T: RawFrequency,
26    Cls: PitchClass,
27{
28    pub fn new(pitch: Pitch<T>, octave: Octave) -> Self {
29        Self {
30            class: Cls::new(),
31            octave,
32            pitch,
33        }
34    }
35    /// returns a copy to the index of the note's class
36    pub const fn class(&self) -> &Cls {
37        &self.class
38    }
39    /// returns a copy to the octave of the note
40    pub const fn octave(&self) -> Octave {
41        self.octave
42    }
43    /// returns a mutable reference to the current octave
44    pub const fn octave_mut(&mut self) -> &mut Octave {
45        &mut self.octave
46    }
47    /// set the pitch class of the note
48    pub fn set_class(&mut self, class: Cls) -> &mut Self {
49        self.class = class;
50        self
51    }
52    /// set the octave of the note
53    pub fn set_octave(&mut self, octave: Octave) -> &mut Self {
54        self.octave = octave;
55        self
56    }
57    /// consumes the current instance to create another with the given pitch class
58    pub fn with_class<Pc: PitchClass>(self) -> NoteBase<T, Pc> {
59        NoteBase {
60            class: Pc::new(),
61            octave: self.octave,
62            pitch: self.pitch,
63        }
64    }
65    /// consumes the current instance to create another with the given octave
66    pub fn with_octave(self, octave: Octave) -> Self {
67        Self { octave, ..self }
68    }
69}
70
71impl<C, T> core::fmt::Display for NoteBase<T, C>
72where
73    C: PitchClass,
74    T: RawFrequency,
75{
76    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
77        write!(f, "{}.{}", self.class, self.octave)
78    }
79}
80
81impl<T, C> Default for NoteBase<T, C>
82where
83    T: Default,
84    C: PitchClass,
85{
86    fn default() -> Self {
87        Self {
88            class: C::new(),
89            octave: Octave::default(),
90            pitch: Pitch::default(),
91        }
92    }
93}