1use crate::{IntoPitch, Octave, Pitch, Pitches};
6
7#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
8#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
9pub struct Note {
10 pub(crate) octave: Octave,
11 pub(crate) pitch: Pitch,
12}
13
14impl Note {
15 pub fn new(octave: Octave, pitch: impl IntoPitch) -> Self {
16 Self {
17 octave,
18 pitch: pitch.into_pitch(),
19 }
20 }
21 pub fn from_pitch(pitch: impl IntoPitch) -> Self {
24 Self {
25 octave: Octave::default(),
26 pitch: pitch.into_pitch(),
27 }
28 }
29 pub fn class(&self) -> Pitches {
34 self.pitch.class()
35 }
36
37 pub const fn octave(&self) -> &Octave {
39 &self.octave
40 }
41 pub fn octave_mut(&mut self) -> &mut Octave {
43 &mut self.octave
44 }
45 pub const fn pitch(&self) -> &Pitch {
47 &self.pitch
48 }
49 pub fn pitch_mut(&mut self) -> &mut Pitch {
51 &mut self.pitch
52 }
53 pub fn set_octave(&mut self, octave: Octave) {
55 self.octave = octave;
56 }
57 pub fn set_pitch(&mut self, Pitch(pitch): Pitch) {
59 self.pitch.set(pitch);
60 }
61 pub fn with_octave(self, octave: Octave) -> Self {
63 Self { octave, ..self }
64 }
65 pub fn with_pitch(self, Pitch(pitch): Pitch) -> Note {
67 Note {
68 octave: self.octave,
69 pitch: Pitch(pitch),
70 }
71 }
72}
73
74impl core::fmt::Display for Note {
79 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
80 write!(f, "{}.{}", self.class(), self.octave)
81 }
82}
83
84unsafe impl Send for Note {}
85
86unsafe impl Sync for Note {}
87
88impl From<(Octave, Pitch)> for Note {
89 fn from((octave, pitch): (Octave, Pitch)) -> Self {
90 Self { octave, pitch }
91 }
92}
93
94impl From<Note> for (Octave, Pitch) {
95 fn from(note: Note) -> Self {
96 (note.octave, note.pitch)
97 }
98}
99
100impl From<Note> for Pitch {
101 fn from(note: Note) -> Self {
102 note.pitch
103 }
104}
105
106impl From<Pitch> for Note {
107 fn from(pitch: Pitch) -> Self {
108 Self {
109 octave: Octave::default(),
110 pitch,
111 }
112 }
113}