45namespace zrythm::utils::midi
48static constexpr uint8_t MIDI_CH1_NOTE_ON = 0x90;
49static constexpr uint8_t MIDI_CH1_NOTE_OFF = 0x80;
51static constexpr uint8_t MIDI_CH1_POLY_AFTERTOUCH = 0xA0;
52static constexpr uint8_t MIDI_CH1_CTRL_CHANGE = 0xB0;
53static constexpr uint8_t MIDI_CH1_PROG_CHANGE = 0xC0;
55static constexpr uint8_t MIDI_CH1_CHAN_AFTERTOUCH = 0xD0;
56static constexpr uint8_t MIDI_CH1_PITCH_WHEEL_RANGE = 0xE0;
57static constexpr uint8_t MIDI_ALL_NOTES_OFF = 0x7B;
58static constexpr uint8_t MIDI_ALL_SOUND_OFF = 0x78;
59static constexpr uint8_t MIDI_SYSTEM_MESSAGE = 0xF0;
60static constexpr uint8_t MIDI_SONG_POSITION = 0xF2;
61static constexpr uint8_t MIDI_CLOCK_START = 0xFA;
62static constexpr uint8_t MIDI_CLOCK_CONTINUE = 0xFB;
63static constexpr uint8_t MIDI_CLOCK_BEAT = 0xF8;
64static constexpr uint8_t MIDI_CLOCK_STOP = 0xFC;
65static constexpr uint8_t MIDI_META_EVENT = 0xFF;
70 return std::numeric_limits<std::uint16_t>::max ();
94std::optional<std::string>
119midi_note_number_to_frequency (
const uint8_t note)
121 return 440.f * powf (2.f, ((
float) note - 69.f) * (1.f / 12.f));
125midi_frequency_to_note_number (
const float freq)
127 return (uint8_t) round (
128 69.f + (12.f / logf (2.f)) * logf (freq * (1.0f / 440.f)));
138midi_get_chromatic_scale_index (
const uint8_t note)
149midi_get_octave_number (
const uint8_t note)
151 const uint8_t octave_for_middle_c = 3;
152 return note / 12 + (uint8_t) (octave_for_middle_c - 5);
160midi_is_short_message_type (
161 std::span<const midi_byte_t> short_msg,
164 return (short_msg[0] & 0xf0) == type;
168midi_get_note_number (std::span<const midi_byte_t> short_msg)
174midi_get_velocity (std::span<const midi_byte_t> short_msg)
187midi_get_note_name_with_octave (std::span<const midi_byte_t> short_msg);
190midi_is_note_on (std::span<const midi_byte_t> short_msg)
192 return midi_is_short_message_type (short_msg, MIDI_CH1_NOTE_ON)
193 && midi_get_velocity (short_msg) != 0;
197midi_is_note_off (std::span<const midi_byte_t> short_msg)
199 return midi_is_short_message_type (short_msg, MIDI_CH1_NOTE_OFF)
200 || (midi_is_short_message_type (short_msg, MIDI_CH1_NOTE_ON) && midi_get_velocity (short_msg) == 0);
204midi_is_program_change (std::span<const midi_byte_t> short_msg)
206 return midi_is_short_message_type (short_msg, MIDI_CH1_PROG_CHANGE);
210midi_get_program_change_number (std::span<const midi_byte_t> short_msg)
216midi_is_pitch_wheel (std::span<const midi_byte_t> short_msg)
218 return midi_is_short_message_type (short_msg, MIDI_CH1_PITCH_WHEEL_RANGE);
222midi_is_aftertouch (std::span<const midi_byte_t> short_msg)
224 return midi_is_short_message_type (short_msg, MIDI_CH1_POLY_AFTERTOUCH);
228midi_is_channel_pressure (std::span<const midi_byte_t> short_msg)
230 return midi_is_short_message_type (short_msg, MIDI_CH1_CHAN_AFTERTOUCH);
234midi_is_controller (std::span<const midi_byte_t> short_msg)
236 return midi_is_short_message_type (short_msg, MIDI_CH1_CTRL_CHANGE);
247static inline uint32_t
248midi_get_14_bit_value (std::span<const midi_byte_t> short_msg)
250 return short_msg[1] | ((uint32_t) short_msg[2] << 7);
254midi_get_channel_0_to_15 (std::span<const midi_byte_t> short_msg)
256 return short_msg[0] & 0x0f;
260midi_get_channel_1_to_16 (std::span<const midi_byte_t> short_msg)
262 return midi_get_channel_0_to_15 (short_msg) + 1u;
265static inline uint32_t
266midi_get_pitchwheel_value (std::span<const midi_byte_t> short_msg)
268 return midi_get_14_bit_value (short_msg);
272midi_get_aftertouch_value (std::span<const midi_byte_t> short_msg)
278midi_get_channel_pressure_value (std::span<const midi_byte_t> short_msg)
284midi_get_controller_number (std::span<const midi_byte_t> short_msg)
290midi_get_controller_value (std::span<const midi_byte_t> short_msg)
296midi_is_all_notes_off (std::span<const midi_byte_t> short_msg)
298 return midi_is_controller (short_msg)
299 && midi_get_controller_number (short_msg) == 123;
303midi_is_all_sound_off (std::span<const midi_byte_t> short_msg)
305 return midi_is_controller (short_msg)
306 && midi_get_controller_number (short_msg) == 120;
310midi_is_quarter_frame (std::span<const midi_byte_t> short_msg)
312 return short_msg[0] == 0xf1;
316midi_is_clock (std::span<const midi_byte_t> short_msg)
318 return short_msg[0] == 0xf8;
322midi_is_start (std::span<const midi_byte_t> short_msg)
324 return short_msg[0] == 0xfa;
328midi_is_continue (std::span<const midi_byte_t> short_msg)
330 return short_msg[0] == 0xfb;
334midi_is_stop (std::span<const midi_byte_t> short_msg)
336 return short_msg[0] == 0xfc;
340midi_is_active_sense (std::span<const midi_byte_t> short_msg)
342 return short_msg[0] == 0xfe;
346midi_is_song_position_pointer (std::span<const midi_byte_t> short_msg)
348 return short_msg[0] == 0xf2;
351static inline uint32_t
352midi_get_song_position_pointer_value (std::span<const midi_byte_t> short_msg)
354 return midi_get_14_bit_value (short_msg);
358midi_get_hex_str (std::span<const midi_byte_t> msg);
361midi_print_to_str (std::span<const midi_byte_t> msg);
364midi_print (std::span<const midi_byte_t> msg);
367midi_is_short_msg (std::span<const midi_byte_t> msg)
369 assert (!msg.empty ());
374 return msg[0] != MIDI_SYSTEM_MESSAGE && msg[0] != MIDI_META_EVENT;
378midi_is_sysex (std::span<const midi_byte_t> msg)
380 return msg.size () > 1 && msg[0] == MIDI_SYSTEM_MESSAGE;
384midi_is_meta_event (std::span<const midi_byte_t> msg)
386 return msg.size () > 2 && msg[0] == MIDI_META_EVENT;
390midi_is_short_msg_meta_event (std::span<const midi_byte_t> short_msg)
392 return midi_is_meta_event (short_msg);
396midi_is_meta_event_of_type (
397 std::span<const midi_byte_t> msg,
400 return msg.size () > 2 && msg[1] == type && msg[0] == MIDI_META_EVENT;
404midi_get_meta_event_type (std::span<const midi_byte_t> msg)
406 assert (midi_is_meta_event (msg));
425midi_get_meta_event_data (
430 assert (midi_is_meta_event (std::span (msg, msg_sz)));
436 size_t content_len = 0;
437 size_t len_bytes = 0;
438 for (
size_t i = 2; i < msg_sz; i++)
442 content_len = (content_len << 7) | (
byte & 0x7fu);
447 if (len_bytes == 4 || len_bytes + 2 == msg_sz)
451 size_t content_start = len_bytes + 2;
453 if (content_start + content_len > msg_sz)
456 *data = &msg[content_start];
std::optional< std::string > midi_ctrl_change_get_description(std::span< const midi_byte_t > ctrl_change)
Returns a string representation of the given control change event, if control change.
std::string_view midi_get_note_name(midi_byte_t note)
Returns the note name (eg, "C") for a value between 0 and 127.
int midi_get_msg_length(const uint8_t status_byte)
Returns the length of the MIDI message based on the status byte.
std::string_view midi_get_controller_name(midi_byte_t cc)
Return the name of the given cc (0-127).
std::optional< int > midi_ctrl_change_get_channel(std::span< const midi_byte_t > ctrl_change)
Returns the MIDI channel of the given control change event, if control change.
std::uint8_t midi_byte_t
MIDI byte.
void midi_get_bytes_from_combined(uint32_t val, midi_byte_t *lsb, midi_byte_t *msb)
Used for MIDI controls whose values are split between MSB/LSB.