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
//! 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)
}
}