MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
MIDINode.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "InputNode.hpp"
4
6
7/**
8 * @brief MIDI input node configuration
9 */
11 std::optional<uint8_t> channel; ///< MIDI channel filter (0-15)
12 std::optional<uint8_t> note_number; ///< Note number filter (0-127)
13 std::optional<uint8_t> cc_number; ///< CC number filter (0-127)
14 std::optional<uint8_t> message_type; ///< Message type filter (0x80-0xF0)
15
16 bool note_on_only {}; ///< Only respond to Note On
17 bool note_off_only {}; ///< Only respond to Note Off
18
19 std::function<double(uint8_t)> velocity_curve; ///< Custom velocity mapping
20 bool invert_cc { false }; ///< Flip CC 127→0
21
22 /**
23 * @brief Note velocity node (responds to any note)
24 */
25 static MIDIConfig note() { return {}; }
26
27 /**
28 * @brief Specific note velocity
29 */
30 static MIDIConfig note(uint8_t note_num)
31 {
32 MIDIConfig cfg;
33 cfg.note_number = note_num;
34 return cfg;
35 }
36
37 /**
38 * @brief Control Change node
39 */
40 static MIDIConfig cc(uint8_t cc_num)
41 {
42 MIDIConfig cfg;
43 cfg.cc_number = cc_num;
44 cfg.message_type = 0xB0;
45 return cfg;
46 }
47
48 /**
49 * @brief Pitch bend node
50 */
52 {
53 MIDIConfig cfg;
54 cfg.message_type = 0xE0;
55 return cfg;
56 }
57
58 /**
59 * @brief Aftertouch node
60 */
62 {
63 MIDIConfig cfg;
64 cfg.message_type = 0xD0;
65 return cfg;
66 }
67
68 /**
69 * @brief Program change node
70 */
72 {
73 MIDIConfig cfg;
74 cfg.message_type = 0xC0;
75 return cfg;
76 }
77
78 /**
79 * @brief Apply velocity curve transformation
80 */
81 template <typename F>
83 {
84 velocity_curve = std::forward<F>(curve);
85 return *this;
86 }
87
89 {
90 channel = ch;
91 return *this;
92 }
93
95 {
96 note_on_only = true;
97 return *this;
98 }
99
101 {
102 note_off_only = true;
103 return *this;
104 }
105
107 {
108 invert_cc = true;
109 return *this;
110 }
111};
112
113/**
114 * @class MIDINode
115 * @brief Specialized InputNode for MIDI messages
116 *
117 * Extracts and processes MIDI data with convenient filtering:
118 * - Note numbers and velocities
119 * - Control Change values
120 * - Pitch bend (normalized to [-1, 1])
121 * - Channel-specific filtering
122 * - Message type filtering
123 *
124 * Example usage:
125 * @code
126 * // Any note velocity
127 * auto note_vel = std::make_shared<MIDINode>(MIDIConfig::note());
128 *
129 * // Specific note on channel 1
130 * auto middle_c = std::make_shared<MIDINode>(
131 * MIDIConfig::note(60).on_channel(0));
132 *
133 * // Mod wheel (CC 1)
134 * auto mod_wheel = std::make_shared<MIDINode>(MIDIConfig::cc(1));
135 *
136 * // Pitch bend on channel 2
137 * auto pitch = std::make_shared<MIDINode>(
138 * MIDIConfig::pitch_bend().on_channel(1));
139 * @endcode
140 */
141class MAYAFLUX_API MIDINode : public InputNode {
142public:
143 using NoteCallback = std::function<void(uint8_t note, uint8_t velocity, bool is_on)>;
144 using CC_Callback = std::function<void(uint8_t cc_num, uint8_t value)>;
145 using PitchBendCallback = std::function<void(int16_t bend)>;
146
147 explicit MIDINode(MIDIConfig config = {});
148
149 void save_state() override { }
150 void restore_state() override { }
151
152 /**
153 * @brief Callback for note events with note number and velocity
154 * @param callback Function receiving (note_number, velocity, is_note_on)
155 */
156 void on_note(std::function<void(uint8_t note, uint8_t velocity, bool is_on)> callback)
157 {
158 m_note_callbacks.push_back(std::move(callback));
159 }
160
161 /**
162 * @brief Callback for CC events with controller number and value
163 */
164 void on_cc(std::function<void(uint8_t cc_num, uint8_t value)> callback)
165 {
166 m_cc_callbacks.push_back(std::move(callback));
167 }
168
169 /**
170 * @brief Callback for pitch bend with 14-bit value
171 */
172 void on_pitch_bend(std::function<void(int16_t bend)> callback)
173 {
174 m_pitch_bend_callbacks.push_back(std::move(callback));
175 }
176
177protected:
178 double extract_value(const Core::InputValue& value) override;
179
180 void notify_tick(double value) override;
181
182private:
184 std::optional<Core::InputValue::MIDIMessage> m_last_midi_message;
185
186 std::vector<NoteCallback> m_note_callbacks;
187 std::vector<CC_Callback> m_cc_callbacks;
188 std::vector<PitchBendCallback> m_pitch_bend_callbacks;
189
190 void fire_midi_callbacks(const Core::InputValue::MIDIMessage& midi);
191 [[nodiscard]] bool matches_filters(const Core::InputValue& value) const;
192};
193
194} // namespace MayaFlux::Nodes::Input
Abstract base class for nodes that receive external input.
std::function< void(uint8_t cc_num, uint8_t value)> CC_Callback
Definition MIDINode.hpp:144
std::vector< PitchBendCallback > m_pitch_bend_callbacks
Definition MIDINode.hpp:188
std::function< void(int16_t bend)> PitchBendCallback
Definition MIDINode.hpp:145
void restore_state() override
Restores the node's state from the last save Recursively cascades through all connected modulator nod...
Definition MIDINode.hpp:150
std::optional< Core::InputValue::MIDIMessage > m_last_midi_message
Definition MIDINode.hpp:184
void on_pitch_bend(std::function< void(int16_t bend)> callback)
Callback for pitch bend with 14-bit value.
Definition MIDINode.hpp:172
void on_note(std::function< void(uint8_t note, uint8_t velocity, bool is_on)> callback)
Callback for note events with note number and velocity.
Definition MIDINode.hpp:156
std::vector< CC_Callback > m_cc_callbacks
Definition MIDINode.hpp:187
std::vector< NoteCallback > m_note_callbacks
Definition MIDINode.hpp:186
void on_cc(std::function< void(uint8_t cc_num, uint8_t value)> callback)
Callback for CC events with controller number and value.
Definition MIDINode.hpp:164
std::function< void(uint8_t note, uint8_t velocity, bool is_on)> NoteCallback
Definition MIDINode.hpp:143
void save_state() override
Saves the node's current state for later restoration Recursively cascades through all connected modul...
Definition MIDINode.hpp:149
Specialized InputNode for MIDI messages.
Definition MIDINode.hpp:141
Generic input value container.
Configuration for InputNode behavior.
Definition InputNode.hpp:79
std::optional< uint8_t > channel
MIDI channel filter (0-15)
Definition MIDINode.hpp:11
std::function< double(uint8_t)> velocity_curve
Custom velocity mapping.
Definition MIDINode.hpp:19
static MIDIConfig program_change()
Program change node.
Definition MIDINode.hpp:71
bool invert_cc
Flip CC 127→0.
Definition MIDINode.hpp:20
std::optional< uint8_t > cc_number
CC number filter (0-127)
Definition MIDINode.hpp:13
std::optional< uint8_t > message_type
Message type filter (0x80-0xF0)
Definition MIDINode.hpp:14
static MIDIConfig aftertouch()
Aftertouch node.
Definition MIDINode.hpp:61
MIDIConfig & with_velocity_curve(F &&curve)
Apply velocity curve transformation.
Definition MIDINode.hpp:82
bool note_on_only
Only respond to Note On.
Definition MIDINode.hpp:16
static MIDIConfig note(uint8_t note_num)
Specific note velocity.
Definition MIDINode.hpp:30
std::optional< uint8_t > note_number
Note number filter (0-127)
Definition MIDINode.hpp:12
static MIDIConfig pitch_bend()
Pitch bend node.
Definition MIDINode.hpp:51
bool note_off_only
Only respond to Note Off.
Definition MIDINode.hpp:17
static MIDIConfig cc(uint8_t cc_num)
Control Change node.
Definition MIDINode.hpp:40
MIDIConfig & on_channel(uint8_t ch)
Definition MIDINode.hpp:88
static MIDIConfig note()
Note velocity node (responds to any note)
Definition MIDINode.hpp:25
MIDI input node configuration.
Definition MIDINode.hpp:10