Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
message.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <cstddef>
5
6// choc_MIDI.h's Message::operator== calls `memcmp` unqualified and includes no
7// string header of its own. The call is type-dependent, so ADL runs at the point
8// of instantiation and finds nothing (the arguments are pointers to a
9// fundamental type); the name can only be resolved by ordinary lookup at the
10// point of the template's *definition*. So the declaration has to precede this
11// include, not merely exist in the instantiating TU.
12//
13// `<string.h>` rather than `<cstring>` on purpose: CHOC needs global `::memcmp`,
14// and only the C header is guaranteed to declare names in the global namespace
15// ([depr.c.headers]) — `<cstring>` only guarantees `std::memcmp`. libc++ happens
16// to expose the global one transitively via `<string>`, which is why this
17// compiled on macOS and broke the GCC/libstdc++ Linux build.
18#include <string.h>
19
20#include <choc/audio/choc_MIDI.h>
21
22namespace pulp::midi {
23
32struct MidiEvent {
33 choc::midi::ShortMessage message;
34 int32_t sample_offset = 0;
35 double timestamp = 0.0;
36
38 const uint8_t* data() const { return message.data(); }
40 uint32_t size() const { return message.length(); }
41
46 static MidiEvent note_on(uint8_t channel, uint8_t note, uint8_t velocity) {
47 const auto status = static_cast<uint8_t>(0x90 | (channel & 0x0F));
48 const auto note_byte = static_cast<uint8_t>(note & 0x7F);
49 const auto velocity_byte = static_cast<uint8_t>(velocity & 0x7F);
50 return {choc::midi::ShortMessage(status, note_byte, velocity_byte), 0, 0.0};
51 }
52
54 static MidiEvent note_off(uint8_t channel, uint8_t note, uint8_t velocity = 0) {
55 const auto status = static_cast<uint8_t>(0x80 | (channel & 0x0F));
56 const auto note_byte = static_cast<uint8_t>(note & 0x7F);
57 const auto velocity_byte = static_cast<uint8_t>(velocity & 0x7F);
58 return {choc::midi::ShortMessage(status, note_byte, velocity_byte), 0, 0.0};
59 }
60
64 static MidiEvent cc(uint8_t channel, uint8_t controller, uint8_t value) {
65 const auto status = static_cast<uint8_t>(0xB0 | (channel & 0x0F));
66 const auto controller_byte = static_cast<uint8_t>(controller & 0x7F);
67 const auto value_byte = static_cast<uint8_t>(value & 0x7F);
68 return {choc::midi::ShortMessage(status, controller_byte, value_byte), 0, 0.0};
69 }
70
73 static MidiEvent pitch_bend(uint8_t channel, uint16_t value) {
74 value &= 0x3FFF;
75 return {choc::midi::ShortMessage(
76 static_cast<uint8_t>(0xE0 | (channel & 0x0F)),
77 static_cast<uint8_t>(value & 0x7F),
78 static_cast<uint8_t>((value >> 7) & 0x7F)), 0, 0.0};
79 }
80
87 static MidiEvent poly_pressure(uint8_t channel, uint8_t note, uint8_t pressure) {
88 const auto status = static_cast<uint8_t>(0xA0 | (channel & 0x0F));
89 const auto note_byte = static_cast<uint8_t>(note & 0x7F);
90 const auto pressure_byte = static_cast<uint8_t>(pressure & 0x7F);
91 return {choc::midi::ShortMessage(status, note_byte, pressure_byte), 0, 0.0};
92 }
93
95 static MidiEvent program_change(uint8_t channel, uint8_t program) {
96 const auto status = static_cast<uint8_t>(0xC0 | (channel & 0x0F));
97 const auto program_byte = static_cast<uint8_t>(program & 0x7F);
98 return {choc::midi::ShortMessage(status, program_byte, 0), 0, 0.0};
99 }
100
101 bool is_note_on() const { return message.isNoteOn(); }
102 bool is_note_off() const { return message.isNoteOff(); }
103 bool is_cc() const { return message.isController(); }
104 bool is_pitch_bend() const { return message.isPitchWheel(); }
105 bool is_program_change() const { return message.isProgramChange(); }
106 bool is_poly_pressure() const {
107 return message.isAftertouch();
108 }
109
111 uint8_t channel() const { return message.getChannel0to15(); }
112 uint8_t note() const { return message.getNoteNumber().note; }
113 uint8_t velocity() const { return message.getVelocity(); }
114 uint8_t cc_number() const { return message.getControllerNumber(); }
115 uint8_t cc_value() const { return message.getControllerValue(); }
116};
117
118} // namespace pulp::midi
Definition custom_node_events.hpp:26
Timestamped MIDI event combining a choc::midi::ShortMessage with timing info.
Definition message.hpp:32
uint8_t cc_value() const
Definition message.hpp:115
uint8_t note() const
Definition message.hpp:112
bool is_pitch_bend() const
Definition message.hpp:104
static MidiEvent cc(uint8_t channel, uint8_t controller, uint8_t value)
Create a Control Change event.
Definition message.hpp:64
bool is_program_change() const
Definition message.hpp:105
uint8_t cc_number() const
Definition message.hpp:114
static MidiEvent program_change(uint8_t channel, uint8_t program)
Create a Program Change event.
Definition message.hpp:95
const uint8_t * data() const
Raw MIDI byte data (for format adapters that need direct byte access).
Definition message.hpp:38
static MidiEvent poly_pressure(uint8_t channel, uint8_t note, uint8_t pressure)
Create a Polyphonic Key Pressure (poly aftertouch) event.
Definition message.hpp:87
bool is_cc() const
Definition message.hpp:103
bool is_note_on() const
Definition message.hpp:101
uint32_t size() const
Number of bytes in the MIDI message (1-3).
Definition message.hpp:40
uint8_t channel() const
MIDI channel (0-15).
Definition message.hpp:111
choc::midi::ShortMessage message
Definition message.hpp:33
double timestamp
Absolute time in seconds (for device I/O).
Definition message.hpp:35
static MidiEvent note_on(uint8_t channel, uint8_t note, uint8_t velocity)
Create a Note On event.
Definition message.hpp:46
static MidiEvent note_off(uint8_t channel, uint8_t note, uint8_t velocity=0)
Create a Note Off event.
Definition message.hpp:54
int32_t sample_offset
Sample position within the current buffer block.
Definition message.hpp:34
bool is_poly_pressure() const
Definition message.hpp:106
uint8_t velocity() const
Definition message.hpp:113
bool is_note_off() const
Definition message.hpp:102
static MidiEvent pitch_bend(uint8_t channel, uint16_t value)
Create a Pitch Bend event.
Definition message.hpp:73