1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//! Operations for working with physical or virtual keyboards.
/// A physical or logical key on a real or virtual instrument without any notion of a pitch.
///
/// This struct does *not* represent a musical key, like in "F minor", which is why its name is [`PianoKey`].
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PianoKey {
midi_number: i32,
}
impl PianoKey {
/// Creates a [`PianoKey`] instance from the given MIDI number.
pub fn from_midi_number(midi_number: impl Into<i32>) -> Self {
Self {
midi_number: midi_number.into(),
}
}
/// Returns the MIDI number of this [`PianoKey`].
pub fn midi_number(self) -> i32 {
self.midi_number
}
/// Returns the MIDI number of this [`PianoKey`] if it is in the valid MIDI range [0..128).
///
/// # Examples
///
/// ```
/// # use tune::key::PianoKey;
/// assert_eq!(PianoKey::from_midi_number(-1).checked_midi_number(), None);
/// assert_eq!(PianoKey::from_midi_number(0).checked_midi_number(), Some(0));
/// assert_eq!(
/// PianoKey::from_midi_number(64).checked_midi_number(),
/// Some(64)
/// );
/// assert_eq!(
/// PianoKey::from_midi_number(127).checked_midi_number(),
/// Some(127)
/// );
/// assert_eq!(PianoKey::from_midi_number(128).checked_midi_number(), None);
/// ```
pub fn checked_midi_number(self) -> Option<u8> {
u8::try_from(self.midi_number)
.ok()
.filter(|midi_number| (0..128).contains(midi_number))
}
/// Iterates over all [`PianoKey`]s in the range [`self`..`upper_bound`).
///
/// # Examples
///
/// ```
/// # use tune::key::PianoKey;
/// let midi_key_62 = PianoKey::from_midi_number(62);
/// let midi_key_67 = PianoKey::from_midi_number(67);
///
/// assert_eq!(
/// midi_key_62.keys_before(midi_key_67).collect::<Vec<_>>(),
/// (62..67).map(PianoKey::from_midi_number).collect::<Vec<_>>()
/// );
/// assert!(
/// midi_key_67
/// .keys_before(midi_key_62)
/// .collect::<Vec<_>>()
/// .is_empty()
/// );
/// ```
pub fn keys_before(
self,
upper_bound: PianoKey,
) -> impl DoubleEndedIterator<Item = PianoKey> + ExactSizeIterator<Item = PianoKey> + 'static
{
(self.midi_number..upper_bound.midi_number).map(Self::from_midi_number)
}
/// Counts the number of keys [left inclusive, right exclusive) between `self` and `other`.
///
/// # Examples
///
/// ```
/// # use tune::key::PianoKey;
/// let midi_key_62 = PianoKey::from_midi_number(62);
/// let midi_key_67 = PianoKey::from_midi_number(67);
///
/// assert_eq!(midi_key_62.num_keys_before(midi_key_67), 5);
/// assert_eq!(midi_key_67.num_keys_before(midi_key_62), -5);
/// ```
pub fn num_keys_before(self, other: PianoKey) -> i32 {
other.midi_number - self.midi_number
}
/// Returns the key `num_steps` steps after `self`.
///
/// # Examples
///
/// ```
/// # use tune::key::PianoKey;
/// let midi_key_62 = PianoKey::from_midi_number(62);
/// let midi_key_67 = PianoKey::from_midi_number(67);
///
/// assert_eq!(midi_key_62.plus_steps(5), midi_key_67);
/// assert_eq!(midi_key_67.plus_steps(-5), midi_key_62);
/// ```
pub fn plus_steps(self, num_steps: i32) -> PianoKey {
PianoKey::from_midi_number(self.midi_number + num_steps)
}
}