FastLED 3.9.7
Loading...
Searching...
No Matches
Keyboard.cpp
1
2
3
4#include <Arduino.h>
5
6#include "./util.h"
7#include "./color_mapper.h"
8#include "./Keyboard.h"
9#include "./dprint.h"
10
11Key::Key() : on_(false), sustained_(false), sustain_pedal_on_(false),
12 velocity_(0), idx_(0), event_time_(0) {}
13
14void Key::SetOn(uint8_t vel, const ColorHSV& color, uint32_t now_ms) {
15 if (curr_color_.v_ < color.v_) { // if the new color is "brighter" than the current color.
16 velocity_ = vel;
17 curr_color_ = color;
18 event_time_ = now_ms;
19 }
20 orig_color_ = curr_color_;
21 event_time_ = now_ms;
22 on_ = true;
23}
24
25void Key::SetOff(uint32_t now_ms) {
26 orig_color_ = curr_color_;
27 on_ = false;
28 event_time_ = now_ms;
29 sustained_ = false;
30}
31
32void Key::SetSustained() {
33 sustained_ = true;
34}
35
36void Key::Update(uint32_t now_ms, uint32_t delta_ms, bool sustain_pedal_on) {
37 if (sustained_ && !sustain_pedal_on) {
38 sustained_ = false;
39 SetOff(now_ms);
40 }
41 sustain_pedal_on_ = sustain_pedal_on;
42 UpdateIntensity(now_ms, delta_ms);
43}
44
45float Key::VelocityFactor() const { return velocity_ / 127.f; }
46
47float Key::CalcAttackDecayFactor(uint32_t delta_ms) const {
48 bool dampened_key = (idx_ < kFirstNoteNoDamp);
49 float active_lights_factor = ::CalcDecayFactor(
50 sustain_pedal_on_,
51 on_,
52 idx_,
53 VelocityFactor(),
54 dampened_key,
55 delta_ms);
56 return active_lights_factor;
57}
58
59float Key::AttackRemapFactor(uint32_t now_ms) {
60 if (on_) {
61 return ::AttackRemapFactor(now_ms - event_time_);
62 } else {
63 return 1.0;
64 }
65}
66
67float Key::IntensityFactor() const {
68 return intensity_;
69}
70
71void Key::UpdateIntensity(uint32_t now_ms, uint32_t delta_ms) {
72 if (on_) {
73 // Intensity can be calculated by a
74 float intensity =
75 CalcAttackDecayFactor(now_ms - event_time_) *
76 VelocityFactor() *
77 AttackRemapFactor(now_ms);
78
79 // This is FRAME RATE DEPENDENT FUNCTION!!!!
80 // CHANGE TO TIME INDEPENDENT BEFORE SUBMIT.
81 intensity_ = (.9f * intensity) + (.1f * intensity_);
82 } else if(intensity_ > 0.0f) { // major cpu hotspot.
83
84 if (sustain_pedal_on_) {
85 float delta_s = delta_ms / 1000.f;
86 if (intensity_ > .5f) {
87 const float kRate = .12f;
88 // Time flexible decay function. Stays accurate
89 // even as the frame rate changes.
90 // Formula: A = Pe^(r*t)
91 intensity_ = intensity_ * exp(-delta_s * kRate);
92 } else {
93 // Quickly fade at the bottom end of the transition.
94 const float kRate = .05f;
95 intensity_ -= delta_s * kRate;
96 }
97 } else {
98 float delta_s = delta_ms / 1000.f;
99 if (intensity_ > .5f) {
100 const float kRate = 12.0f;
101 // Time flexible decay function. Stays accurate
102 // even as the frame rate changes.
103 // Formula: A = Pe^(r*t)
104 intensity_ = intensity_ * exp(-delta_s * kRate);
105 } else {
106 // Quickly fade at the bottom end of the transition.
107 const float kRate = 2.0f;
108 intensity_ -= delta_s * kRate;
109 }
110
111 }
112 intensity_ = constrain(intensity_, 0.0f, 1.0f);
113 }
114}
115
116void KeyboardState::HandleNoteOn(uint8_t midi_note, uint8_t velocity, int color_selector_value, uint32_t now_ms) {
117 if (0 == velocity) {
118 // Some keyboards signify "NoteOff" with a velocity of zero.
119 HandleNoteOff(midi_note, velocity, now_ms);
120 return;
121 }
122
123#ifdef DEBUG_KEYBOARD
124 dprint("HandleNoteOn:");
125
126 dprint("midi_note = ");
127 dprint(midi_note);
128
129 dprint(", velocity = ");
130 dprintln(velocity);
131 #endif
132
133 float brightness = ToBrightness(velocity);
134
135 dprint("brightness: "); dprintln(brightness);
136
137 ColorHSV pixel_color_hsv = SelectColor(midi_note, brightness,
138 color_selector_value);
139
140 // TODO: Give a key access to the Keyboard owner, therefore it could inspect the
141 // sustained variable instead of passing it here.
142 Key* key = GetKey(midi_note);
143
144 dprint("key indx: "); dprintln(key->idx_);
145
146 key->SetOn(velocity, pixel_color_hsv, now_ms);
147}
148
149void KeyboardState::HandleNoteOff(uint8_t midi_note, uint8_t /*velocity*/, uint32_t now_ms) {
150#ifdef DEBUG_KEYBOARD
151 dprint("HandleNoteOff:");
152
153 dprint("midi_note = ");
154 dprint(midi_note);
155
156 dprint(", velocity = ");
157 dprintln(velocity);
158#endif
159
160 Key* key = GetKey(midi_note);
161
162 if (sustain_pedal_) {
163 key->SetSustained();
164 } else {
165 key->SetOff(now_ms);
166 }
167}
168
169void KeyboardState::HandleControlChange(uint8_t d1, uint8_t d2) {
170 // Note that d1 and d2 just mean "data-1" and "data-2".
171 // TODO: Find out what d1 and d2 should be called.
172 const bool foot_pedal = (d1 == kMidiFootPedal);
173
174 if (foot_pedal) {
175 // Spec says that if that values 0-63 are OFF, otherwise ON.
176 sustain_pedal_ = (d2 >= 64);
177 }
178}
179
180void KeyboardState::HandleAfterTouchPoly(uint8_t note, uint8_t pressure) {
181 dprintln("HandleAfterTouchPoly");
182
183 dprint("\tnote = ");
184 dprint(note);
185
186 dprint(", pressure = ");
187 dprintln(pressure);
188}
189
190KeyboardState::KeyboardState() : sustain_pedal_(false), keys_() {
191 for (int i = 0; i < kNumKeys; ++i) {
192 keys_[i].idx_ = i;
193 }
194}
195
196void KeyboardState::Update(uint32_t now_ms, uint32_t delta_ms) {
197 for (int i = 0; i < kNumKeys; ++i) {
198 keys_[i].Update(now_ms, delta_ms, sustain_pedal_);
199 }
200}
201
202uint8_t KeyboardState::KeyIndex(int midi_pitch) {
203 //return constrain(midi_pitch, 21, 108) - 21;
204 return ::KeyIndex(midi_pitch);
205}
206
207Key* KeyboardState::GetKey(int midi_pitch) {
208 uint8_t idx = KeyIndex(midi_pitch);
209 return &keys_[idx];
210}
211
212
213
Definition Keyboard.h:22