Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
rpn_parser.hpp
Go to the documentation of this file.
1#pragma once
2
5
7#include <functional>
8#include <cstdint>
9
10namespace pulp::midi {
11
32class RpnParser {
33public:
38 std::function<void(uint8_t channel, uint16_t parameter, uint16_t value)> on_rpn;
39
41 std::function<void(uint8_t channel, uint16_t parameter, uint16_t value)> on_nrpn;
42
44 std::function<void(uint8_t channel, uint16_t parameter, bool is_rpn)> on_increment;
45
47 std::function<void(uint8_t channel, uint16_t parameter, bool is_rpn)> on_decrement;
48
50 void process(const MidiEvent& event) {
51 auto msg = event.message;
52 if (!msg.isController()) return;
53
54 uint8_t channel = msg.getChannel0to15();
55 uint8_t cc = msg.getControllerNumber();
56 uint8_t val = msg.getControllerValue();
57
58 auto& state = channel_state_[channel];
59
60 switch (cc) {
61 case 101: // RPN MSB
62 set_parameter_byte(state, true, true, val);
63 break;
64
65 case 100: // RPN LSB
66 set_parameter_byte(state, true, false, val);
67 break;
68
69 case 99: // NRPN MSB
70 set_parameter_byte(state, false, true, val);
71 break;
72
73 case 98: // NRPN LSB
74 set_parameter_byte(state, false, false, val);
75 break;
76
77 case 6: // Data Entry MSB
78 state.value_msb = val;
79 break;
80
81 case 38: // Data Entry LSB
82 if (state.param_set) {
83 uint16_t param = combine(state.param_msb, state.param_lsb);
84 uint16_t value = combine(state.value_msb, val);
85 if (state.is_rpn) {
86 if (on_rpn) on_rpn(channel, param, value);
87 } else {
88 if (on_nrpn) on_nrpn(channel, param, value);
89 }
90 }
91 break;
92
93 case 96: // Increment
94 if (state.param_set) {
95 uint16_t param = combine(state.param_msb, state.param_lsb);
96 if (on_increment) on_increment(channel, param, state.is_rpn);
97 }
98 break;
99
100 case 97: // Decrement
101 if (state.param_set) {
102 uint16_t param = combine(state.param_msb, state.param_lsb);
103 if (on_decrement) on_decrement(channel, param, state.is_rpn);
104 }
105 break;
106
107 default:
108 break;
109 }
110 }
111
113 void reset() {
114 for (auto& s : channel_state_) s = {};
115 }
116
117private:
118 struct ChannelState {
119 uint8_t param_msb = 0;
120 uint8_t param_lsb = 0;
121 uint8_t value_msb = 0;
122 bool is_rpn = true;
123 bool param_msb_set = false;
124 bool param_lsb_set = false;
125 bool param_set = false;
126 };
127
128 ChannelState channel_state_[16]{};
129
130 static uint16_t combine(uint8_t msb, uint8_t lsb) {
131 return static_cast<uint16_t>((msb << 7) | lsb);
132 }
133
134 static void update_parameter_state(ChannelState& state) {
135 state.param_set = state.param_msb_set && state.param_lsb_set
136 && !(state.param_msb == 0x7F && state.param_lsb == 0x7F);
137 }
138
139 static void set_parameter_byte(ChannelState& state,
140 bool is_rpn,
141 bool is_msb,
142 uint8_t value) {
143 if (state.is_rpn != is_rpn) {
144 state.param_msb = 0;
145 state.param_lsb = 0;
146 state.param_msb_set = false;
147 state.param_lsb_set = false;
148 state.param_set = false;
149 } else if (is_msb && state.param_set) {
150 state.param_lsb_set = false;
151 state.param_set = false;
152 }
153
154 state.is_rpn = is_rpn;
155 if (is_msb) {
156 state.param_msb = value;
157 state.param_msb_set = true;
158 } else {
159 state.param_lsb = value;
160 state.param_lsb_set = true;
161 }
162 update_parameter_state(state);
163 }
164};
165
166} // namespace pulp::midi
Parses RPN (Registered Parameter Number) and NRPN (Non-Registered Parameter Number) messages from a s...
Definition rpn_parser.hpp:32
std::function< void(uint8_t channel, uint16_t parameter, uint16_t value)> on_nrpn
Called when a complete NRPN message is received.
Definition rpn_parser.hpp:41
void process(const MidiEvent &event)
Process a MIDI event. Non-CC events are ignored.
Definition rpn_parser.hpp:50
std::function< void(uint8_t channel, uint16_t parameter, bool is_rpn)> on_decrement
Called when a decrement (CC 97) is received for the active parameter.
Definition rpn_parser.hpp:47
void reset()
Reset all channel state.
Definition rpn_parser.hpp:113
std::function< void(uint8_t channel, uint16_t parameter, uint16_t value)> on_rpn
Called when a complete RPN message is received.
Definition rpn_parser.hpp:38
std::function< void(uint8_t channel, uint16_t parameter, bool is_rpn)> on_increment
Called when an increment (CC 96) is received for the active parameter.
Definition rpn_parser.hpp:44
Definition custom_node_events.hpp:26
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
@ value
the widget's primary value (Knob, Fader, RangeSlider, Toggle, ProgressBar)
Definition binding_diagnostics.hpp:19
Timestamped MIDI event combining a choc::midi::ShortMessage with timing info.
Definition message.hpp:32