Pure MIDI 1.0 "panic" message generation and classification. More...
#include <pulp/midi/keyboard_state.hpp>#include <pulp/midi/message.hpp>#include <cstddef>#include <cstdint>#include <optional>#include <span>Go to the source code of this file.
Classes | |
| struct | pulp::midi::PanicScope |
| Which channels and which message kinds a panic covers. More... | |
Namespaces | |
| namespace | pulp |
| namespace | pulp::midi |
| namespace | pulp::midi::panic_detail |
Enumerations | |
| enum class | pulp::midi::PanicMessageKind : std::uint8_t { pulp::midi::all_sound_off , pulp::midi::all_notes_off , pulp::midi::reset_all_controllers , pulp::midi::sustain_off , pulp::midi::pitch_bend_centre } |
| One kind of message a panic can contain. More... | |
Functions | |
| constexpr std::size_t | pulp::midi::panic_detail::kind_count (const PanicScope &scope) |
| constexpr unsigned | pulp::midi::panic_detail::popcount16 (std::uint16_t mask) |
| constexpr std::size_t | pulp::midi::panic_message_count (const PanicScope &scope) |
| Number of events panic_messages() will write for scope. | |
| std::size_t | pulp::midi::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. | |
| template<typename Fn> | |
| void | pulp::midi::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, in channel then note order. | |
| std::size_t | pulp::midi::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, in channel then note order. | |
| std::size_t | pulp::midi::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 tracked as held. | |
| std::optional< PanicMessageKind > | pulp::midi::classify_panic_message (const MidiEvent &event) noexcept |
| Classify a message as one of the panic kinds, or nullopt for anything else. | |
Variables | |
| constexpr std::size_t | pulp::midi::kMaxPanicMessages = 16u * 5u |
| Largest number of events panic_messages() can produce (16 channels x 5). | |
| constexpr std::size_t | pulp::midi::kMaxNoteOffs = 16u * 128u |
| Largest number of events held_note_offs() / all_note_offs() can produce. | |
| constexpr std::uint8_t | pulp::midi::panic_detail::kCcSustain = 64 |
| constexpr std::uint8_t | pulp::midi::panic_detail::kCcResetAllControllers = 121 |
| constexpr std::uint8_t | pulp::midi::panic_detail::kCcAllSoundOff = 120 |
| constexpr std::uint8_t | pulp::midi::panic_detail::kCcAllNotesOff = 123 |
| constexpr std::uint16_t | pulp::midi::panic_detail::kPitchBendCentre = 8192 |
Pure MIDI 1.0 "panic" message generation and classification.
A panic silences a receiver: it ends sounding notes, drops sustain, and puts the controllers it may have left displaced back at rest. Everything here is a plain function over caller-owned storage — no allocation, no locks, no state — so it is safe on the audio thread and can be unit tested without a host. The held-note source of truth is MidiKeyboardState; this header only turns its contents (or, as a fallback, "every key") into note-off events.
The messages used are the channel mode and controller messages the MIDI 1.0 specification defines for this purpose:
| Message | Meaning | Receiver behaviour |
|---|---|---|
| CC 120 value 0 | All Sound Off | stop sounding immediately, release tails included |
| CC 123 value 0 | All Notes Off | release held notes through the normal release |
| CC 121 value 0 | Reset All Controllers | controllers return to their defaults |
| CC 64 value 0 | Damper (sustain) off | release notes the pedal was holding |
| Pitch bend 8192 | Pitch wheel centre | undo a bend left displaced |
CC 120 and CC 123 are deliberately different: sending both is the safe panic (the immediate stop covers receivers that implement only one of them), and a "release-only" panic omits CC 120 so tails ring out.