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
108
109
110
111
112
113
114
extern crate input;
extern crate pitch_calc as pitch;
pub use pitch::{Letter, Octave};
pub use input::keyboard::Key;
pub type Velocity = f32;
#[derive(Copy, Clone, Debug)]
pub struct MusicalKeyboard {
pub octave: Octave,
pub velocity: Velocity,
pub is_active: bool,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum NoteEvent {
On(Letter, Octave, Velocity),
Off(Letter, Octave),
}
impl MusicalKeyboard {
pub fn new(octave: Octave, velocity: Velocity, is_active: bool) -> MusicalKeyboard {
MusicalKeyboard {
octave: octave,
velocity: velocity,
is_active: is_active,
}
}
pub fn default() -> MusicalKeyboard {
MusicalKeyboard {
octave: 2,
velocity: 1.0,
is_active: true,
}
}
pub fn handle_input(&mut self, ctrl: bool, key: Key, is_pressed: bool) -> Option<NoteEvent> {
let is_active = self.is_active;
match (ctrl, key, is_active, is_pressed) {
(true, Key::K, _ , true) => self.is_active = self.is_active != true,
(false, Key::Z, true, true) => if self.octave > -2 { self.octave -= 1 },
(false, Key::X, true, true) => if self.octave < 12 { self.octave += 1 },
(false, Key::C, true, true) => if self.velocity > 0.0 { self.velocity -= 0.05 },
(false, Key::V, true, true) => if self.velocity < 1.0 { self.velocity += 0.05 },
(false, _, true, true) => return self.maybe_note_on(key),
(false, _, true, false) => return self.maybe_note_off(key),
_ => (),
}
None
}
pub fn maybe_note(&self, key: Key) -> Option<(Letter, Octave)> {
let (octave, letter): (Octave, Letter) = match key {
Key::A => (0, Letter::C),
Key::W => (0, Letter::Csh),
Key::S => (0, Letter::D),
Key::E => (0, Letter::Dsh),
Key::D => (0, Letter::E),
Key::F => (0, Letter::F),
Key::T => (0, Letter::Fsh),
Key::G => (0, Letter::G),
Key::Y => (0, Letter::Gsh),
Key::H => (0, Letter::A),
Key::U => (0, Letter::Ash),
Key::J => (0, Letter::B),
Key::K => (1, Letter::C),
Key::O => (1, Letter::Csh),
Key::L => (1, Letter::D),
Key::P => (1, Letter::Dsh),
Key::Semicolon => (1, Letter::E),
Key::Quote => (1, Letter::F),
_ => return None,
};
Some((letter, octave + self.octave))
}
pub fn maybe_note_on(&self, key: Key) -> Option<NoteEvent> {
self.maybe_note(key).map(|(letter, octave)| NoteEvent::On(letter, octave, self.velocity))
}
pub fn maybe_note_off(&self, key: Key) -> Option<NoteEvent> {
self.maybe_note(key).map(|(letter, octave)| NoteEvent::Off(letter, octave))
}
}