1use super::{
2 calc, hz_from_step, letter_octave_from_step, mel_from_step, perc_from_step,
3 scaled_perc_from_step, Hz, Letter, LetterOctave, Mel, Octave, Perc, ScaleWeight, ScaledPerc,
4 DEFAULT_SCALE_WEIGHT,
5};
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8use std::cmp::Ordering;
9use std::ops::{Add, Div, Mul, Neg, Rem, Sub};
10
11#[derive(Debug, Copy, Clone)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub struct Step(pub calc::Step);
15
16impl Step {
17 #[inline]
19 pub fn step(self) -> calc::Step {
20 let Step(step) = self;
21 step
22 }
23
24 #[inline]
26 pub fn hz(self) -> calc::Hz {
27 let Step(step) = self;
28 hz_from_step(step)
29 }
30
31 #[inline]
33 pub fn to_hz(self) -> Hz {
34 Hz(self.hz())
35 }
36
37 #[inline]
39 pub fn letter_octave(self) -> (Letter, Octave) {
40 letter_octave_from_step(self.step())
41 }
42
43 #[inline]
45 pub fn letter(self) -> Letter {
46 let (letter, _) = self.letter_octave();
47 letter
48 }
49
50 #[inline]
52 pub fn octave(self) -> Octave {
53 let (_, octave) = self.letter_octave();
54 octave
55 }
56
57 #[inline]
59 pub fn to_letter_octave(self) -> LetterOctave {
60 let (letter, octave) = self.letter_octave();
61 LetterOctave(letter, octave)
62 }
63
64 #[inline]
66 pub fn mel(self) -> calc::Mel {
67 mel_from_step(self.step())
68 }
69
70 #[inline]
72 pub fn to_mel(self) -> Mel {
73 Mel(self.mel())
74 }
75
76 #[inline]
78 pub fn perc(self) -> calc::Perc {
79 perc_from_step(self.step())
80 }
81
82 #[inline]
84 pub fn to_perc(self) -> Perc {
85 Perc(self.perc())
86 }
87
88 #[inline]
90 pub fn scaled_perc_with_weight(self, weight: ScaleWeight) -> calc::Perc {
91 scaled_perc_from_step(self.step(), weight)
92 }
93
94 #[inline]
96 pub fn scaled_perc(self) -> calc::Perc {
97 self.scaled_perc_with_weight(DEFAULT_SCALE_WEIGHT)
98 }
99
100 #[inline]
102 pub fn to_scaled_perc_with_weight(self, weight: ScaleWeight) -> ScaledPerc {
103 ScaledPerc(self.scaled_perc_with_weight(weight), weight)
104 }
105
106 #[inline]
108 pub fn to_scaled_perc(self) -> ScaledPerc {
109 self.to_scaled_perc_with_weight(DEFAULT_SCALE_WEIGHT)
110 }
111}
112
113impl Add for Step {
114 type Output = Step;
115 #[inline]
116 fn add(self, rhs: Step) -> Step {
117 Step(self.step() + rhs.step())
118 }
119}
120
121impl Sub for Step {
122 type Output = Step;
123 #[inline]
124 fn sub(self, rhs: Step) -> Step {
125 Step(self.step() - rhs.step())
126 }
127}
128
129impl Mul for Step {
130 type Output = Step;
131 #[inline]
132 fn mul(self, rhs: Step) -> Step {
133 Step(self.step() * rhs.step())
134 }
135}
136
137impl Div for Step {
138 type Output = Step;
139 #[inline]
140 fn div(self, rhs: Step) -> Step {
141 Step(self.step() / rhs.step())
142 }
143}
144
145impl Rem for Step {
146 type Output = Step;
147 #[inline]
148 fn rem(self, rhs: Step) -> Step {
149 Step(self.step() % rhs.step())
150 }
151}
152
153impl Neg for Step {
154 type Output = Step;
155 #[inline]
156 fn neg(self) -> Step {
157 Step(-self.step())
158 }
159}
160
161impl PartialEq for Step {
162 #[inline]
163 fn eq(&self, other: &Step) -> bool {
164 self.step() == other.step()
165 }
166}
167
168impl Eq for Step {}
169
170impl PartialOrd for Step {
171 #[inline]
172 fn partial_cmp(&self, other: &Step) -> Option<Ordering> {
173 self.step().partial_cmp(&other.step())
174 }
175}
176
177impl Ord for Step {
178 #[inline]
179 fn cmp(&self, other: &Step) -> Ordering {
180 self.partial_cmp(other).unwrap()
181 }
182}
183
184impl<T> From<T> for Step
185where
186 T: Into<f32>,
187{
188 fn from(t: T) -> Step {
189 Step(t.into())
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::Step;
196
197 macro_rules! t {
198 (
199 $($x:ty),+
200 ) => {
201 fn from(val: f32) {
202 $(
203 assert_eq!(Step::from(val as $x), Step(val));
204 )*
205 }
206
207 #[test]
208 fn test_from_integer() {
209 from(0.0);
210 from(60.0);
211 from(127.0);
212 }
213
214 fn into(val: f32) {
215 $(
216 let actual: Step = (val as $x).into();
217 assert_eq!(actual, Step(val));
218 )*
219 }
220
221 #[test]
222 fn test_into_integer() {
223 into(0.0);
224 into(60.0);
225 into(127.0);
226 }
227 };
228 }
229
230 t!(u8, u16, i8, i16);
231}