Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
keyboard_state.hpp
Go to the documentation of this file.
1#pragma once
2
5
7#include <array>
8#include <cstdint>
9#include <functional>
10#include <vector>
11
12namespace pulp::midi {
13
36public:
38 std::function<void(uint8_t channel, uint8_t note, uint8_t velocity)> on_note_on;
40 std::function<void(uint8_t channel, uint8_t note)> on_note_off;
41
46 void process(const MidiEvent& event) {
47 auto msg = event.message;
48
49 if (msg.isNoteOn()) {
50 uint8_t ch = msg.getChannel0to15();
51 uint8_t note = msg.getNoteNumber();
52 uint8_t vel = msg.getVelocity();
53
54 if (vel == 0) {
55 // Note on with velocity 0 = note off
56 set_key(ch, note, 0);
57 if (on_note_off) on_note_off(ch, note);
58 } else {
59 set_key(ch, note, vel);
60 if (on_note_on) on_note_on(ch, note, vel);
61 }
62 } else if (msg.isNoteOff()) {
63 uint8_t ch = msg.getChannel0to15();
64 uint8_t note = msg.getNoteNumber();
65 set_key(ch, note, 0);
66 if (on_note_off) on_note_off(ch, note);
67 } else if (msg.isController()) {
68 const uint8_t cc = msg.getControllerNumber();
69 if (cc == 120 || cc == 123)
70 all_notes_off(msg.getChannel0to15());
71 }
72 }
73
75 bool is_note_on(uint8_t channel, uint8_t note) const {
76 return velocity(channel, note) > 0;
77 }
78
80 uint8_t velocity(uint8_t channel, uint8_t note) const {
81 if (channel >= 16 || note >= 128) return 0;
82 return state_[channel][note];
83 }
84
86 int notes_held(uint8_t channel) const {
87 if (channel >= 16) return 0;
88 int count = 0;
89 for (int i = 0; i < 128; ++i) {
90 if (state_[channel][i] > 0) ++count;
91 }
92 return count;
93 }
94
96 int total_notes_held() const {
97 int count = 0;
98 for (int ch = 0; ch < 16; ++ch) count += notes_held(static_cast<uint8_t>(ch));
99 return count;
100 }
101
103 bool any_notes_held() const {
104 for (int ch = 0; ch < 16; ++ch) {
105 for (int n = 0; n < 128; ++n) {
106 if (state_[ch][n] > 0) return true;
107 }
108 }
109 return false;
110 }
111
113 int lowest_note(uint8_t channel) const {
114 if (channel >= 16) return -1;
115 for (int i = 0; i < 128; ++i) {
116 if (state_[channel][i] > 0) return i;
117 }
118 return -1;
119 }
120
122 int highest_note(uint8_t channel) const {
123 if (channel >= 16) return -1;
124 for (int i = 127; i >= 0; --i) {
125 if (state_[channel][i] > 0) return i;
126 }
127 return -1;
128 }
129
132 for (int ch = 0; ch < 16; ++ch) {
133 for (int n = 0; n < 128; ++n) {
134 if (state_[ch][n] > 0) {
135 state_[ch][n] = 0;
136 if (on_note_off) on_note_off(static_cast<uint8_t>(ch),
137 static_cast<uint8_t>(n));
138 }
139 }
140 }
141 }
142
144 void all_notes_off(uint8_t channel) {
145 if (channel >= 16) return;
146 for (int n = 0; n < 128; ++n) {
147 if (state_[channel][n] > 0) {
148 state_[channel][n] = 0;
149 if (on_note_off) on_note_off(channel, static_cast<uint8_t>(n));
150 }
151 }
152 }
153
155 void reset() {
156 for (auto& ch : state_) ch.fill(0);
157 }
158
159private:
160 std::array<std::array<uint8_t, 128>, 16> state_{};
161
162 void set_key(uint8_t ch, uint8_t note, uint8_t vel) {
163 if (ch < 16 && note < 128) state_[ch][note] = vel;
164 }
165};
166
167} // namespace pulp::midi
Tracks the state of all 128 MIDI keys across 16 channels.
Definition keyboard_state.hpp:35
bool any_notes_held() const
Check if any note is held on any channel.
Definition keyboard_state.hpp:103
uint8_t velocity(uint8_t channel, uint8_t note) const
Get the velocity of a held note (0 if not held).
Definition keyboard_state.hpp:80
int total_notes_held() const
Count total notes held across all channels.
Definition keyboard_state.hpp:96
void reset()
Reset all state without firing callbacks.
Definition keyboard_state.hpp:155
std::function< void(uint8_t channel, uint8_t note)> on_note_off
Called when a note turns off.
Definition keyboard_state.hpp:40
void all_notes_off()
Release all notes on all channels.
Definition keyboard_state.hpp:131
int highest_note(uint8_t channel) const
Get the highest held note on a channel (-1 if none).
Definition keyboard_state.hpp:122
std::function< void(uint8_t channel, uint8_t note, uint8_t velocity)> on_note_on
Called when a note turns on.
Definition keyboard_state.hpp:38
int lowest_note(uint8_t channel) const
Get the lowest held note on a channel (-1 if none).
Definition keyboard_state.hpp:113
void process(const MidiEvent &event)
Process a MIDI event.
Definition keyboard_state.hpp:46
int notes_held(uint8_t channel) const
Count how many notes are currently held on a channel.
Definition keyboard_state.hpp:86
bool is_note_on(uint8_t channel, uint8_t note) const
Check if a specific note is currently held on a channel.
Definition keyboard_state.hpp:75
void all_notes_off(uint8_t channel)
Release all notes on a specific channel.
Definition keyboard_state.hpp:144
Definition custom_node_events.hpp:26
Timestamped MIDI event combining a choc::midi::ShortMessage with timing info.
Definition message.hpp:32