61 scope.all_sound_off =
false;
66 return channel < 16u && ((
channel_mask >> channel) & 1u) != 0u;
84 return std::size_t{scope.all_sound_off} + std::size_t{scope.all_notes_off} +
85 std::size_t{scope.reset_all_controllers} + std::size_t{scope.sustain_off} +
86 std::size_t{scope.pitch_bend_centre};
89inline constexpr unsigned popcount16(std::uint16_t mask) {
91 for (; mask != 0u; mask =
static_cast<std::uint16_t
>(mask & (mask - 1u)))
114 std::int32_t sample_offset = 0) noexcept {
120 event.sample_offset = sample_offset;
124 for (
unsigned ch = 0; ch < 16u; ++ch) {
125 if (!scope.includes_channel(ch))
127 const auto channel =
static_cast<std::uint8_t
>(ch);
128 if (scope.sustain_off && !put(
MidiEvent::cc(channel, kCcSustain, 0)))
130 if (scope.all_notes_off && !put(
MidiEvent::cc(channel, kCcAllNotesOff, 0)))
132 if (scope.all_sound_off && !put(
MidiEvent::cc(channel, kCcAllSoundOff, 0)))
134 if (scope.reset_all_controllers && !put(
MidiEvent::cc(channel, kCcResetAllControllers, 0)))
146template <
typename Fn>
148 Fn&& fn)
noexcept(
noexcept(fn(std::uint8_t{}, std::uint8_t{}))) {
149 for (
unsigned ch = 0; ch < 16u; ++ch) {
150 if (((channel_mask >> ch) & 1u) == 0u)
152 for (
unsigned note = 0; note < 128u; ++note) {
153 if (keys.is_note_on(
static_cast<std::uint8_t
>(ch),
static_cast<std::uint8_t
>(note)))
154 fn(
static_cast<std::uint8_t
>(ch),
static_cast<std::uint8_t
>(note));
164 std::uint16_t channel_mask = 0xFFFFu,
165 std::int32_t sample_offset = 0) noexcept {
171 event.sample_offset = sample_offset;
180inline std::size_t
all_note_offs(std::span<MidiEvent> out, std::uint16_t channel_mask = 0xFFFFu,
181 std::int32_t sample_offset = 0) noexcept {
183 for (
unsigned ch = 0; ch < 16u; ++ch) {
184 if (((channel_mask >> ch) & 1u) == 0u)
186 for (
unsigned note = 0; note < 128u; ++note) {
191 event.sample_offset = sample_offset;
203 const auto& msg =
event.message;
204 if (msg.isController()) {
205 if (msg.getControllerValue() != 0)
207 switch (msg.getControllerNumber()) {
212 case kCcResetAllControllers:
220 if (msg.isPitchWheel() && msg.getPitchWheelValue() == kPitchBendCentre)
Tracks the state of all 128 MIDI keys across 16 channels.
Definition keyboard_state.hpp:35
Polyphonic key tracking with velocity and listener callbacks.
constexpr std::uint8_t kCcSustain
Definition panic.hpp:77
constexpr std::size_t kind_count(const PanicScope &scope)
Definition panic.hpp:83
constexpr std::uint16_t kPitchBendCentre
Definition panic.hpp:81
constexpr std::uint8_t kCcResetAllControllers
Definition panic.hpp:78
constexpr std::uint8_t kCcAllNotesOff
Definition panic.hpp:80
constexpr unsigned popcount16(std::uint16_t mask)
Definition panic.hpp:89
constexpr std::uint8_t kCcAllSoundOff
Definition panic.hpp:79
Definition custom_node_events.hpp:26
PanicMessageKind
One kind of message a panic can contain.
Definition panic.hpp:39
@ reset_all_controllers
CC 121 = 0.
Definition panic.hpp:42
@ all_notes_off
CC 123 = 0, release.
Definition panic.hpp:41
@ sustain_off
CC 64 = 0.
Definition panic.hpp:43
@ pitch_bend_centre
pitch bend 8192
Definition panic.hpp:44
@ all_sound_off
CC 120 = 0, immediate stop.
Definition panic.hpp:40
std::size_t held_note_offs(const MidiKeyboardState &keys, std::span< MidiEvent > out, std::uint16_t channel_mask=0xFFFFu, std::int32_t sample_offset=0) noexcept
Note-off events for exactly the notes keys reports as held, on the channels in channel_mask,...
Definition panic.hpp:163
constexpr std::size_t panic_message_count(const PanicScope &scope)
Number of events panic_messages() will write for scope.
Definition panic.hpp:98
std::size_t all_note_offs(std::span< MidiEvent > out, std::uint16_t channel_mask=0xFFFFu, std::int32_t sample_offset=0) noexcept
Brute-force fallback: a note-off for every key on the channels in channel_mask, whether or not it was...
Definition panic.hpp:180
std::size_t panic_messages(const PanicScope &scope, std::span< MidiEvent > out, std::int32_t sample_offset=0) noexcept
Write the panic messages for scope into out, channel by channel.
Definition panic.hpp:113
std::optional< PanicMessageKind > classify_panic_message(const MidiEvent &event) noexcept
Classify a message as one of the panic kinds, or nullopt for anything else.
Definition panic.hpp:201
void for_each_held_note(const MidiKeyboardState &keys, std::uint16_t channel_mask, Fn &&fn) noexcept(noexcept(fn(std::uint8_t{}, std::uint8_t{})))
Call fn(channel, note) for every key keys reports as held on the channels in channel_mask,...
Definition panic.hpp:147
constexpr std::size_t kMaxNoteOffs
Largest number of events held_note_offs() / all_note_offs() can produce.
Definition panic.hpp:74
constexpr std::size_t kMaxPanicMessages
Largest number of events panic_messages() can produce (16 channels x 5).
Definition panic.hpp:71
Timestamped MIDI event combining a choc::midi::ShortMessage with timing info.
Definition message.hpp:32
static MidiEvent cc(uint8_t channel, uint8_t controller, uint8_t value)
Create a Control Change event.
Definition message.hpp:64
static MidiEvent note_off(uint8_t channel, uint8_t note, uint8_t velocity=0)
Create a Note Off event.
Definition message.hpp:54
static MidiEvent pitch_bend(uint8_t channel, uint16_t value)
Create a Pitch Bend event.
Definition message.hpp:73
Which channels and which message kinds a panic covers.
Definition panic.hpp:48
bool reset_all_controllers
Definition panic.hpp:54
std::uint16_t channel_mask
Bit n set means channel n (0-15) is included. Default: all 16.
Definition panic.hpp:50
bool all_notes_off
Definition panic.hpp:53
static constexpr PanicScope release_only()
Panic that lets release tails ring out (no CC 120).
Definition panic.hpp:59
bool sustain_off
Definition panic.hpp:55
bool all_sound_off
Immediate-stop CC 120. Clear for a release-only panic.
Definition panic.hpp:52
constexpr bool includes_channel(unsigned channel) const
Definition panic.hpp:65
bool pitch_bend_centre
Definition panic.hpp:56