Control Surface new-input
MIDI Control Surface library for Arduino
MIDIAddress.hpp
Go to the documentation of this file.
1 /* ✔ */
2 
3 #pragma once
4 
5 #include <Def/Def.hpp>
6 
8 
13 struct __attribute__((packed)) RawMIDIAddress {
14  bool valid : 1;
15  uint8_t address : 7;
16  uint8_t channel : 4;
17  uint8_t cableNumber : 4;
18 };
19 
25  friend class MIDIAddress;
26 
27  public:
30 
31  constexpr MIDIChannelCable() : addresses{0, 0, 0, 0} {}
32  constexpr MIDIChannelCable(Channel channel, Cable cableNumber = CABLE_1)
33  : addresses{1, 0, channel.getRaw(), cableNumber.getRaw()} {}
34 
35  constexpr static MIDIChannelCable invalid() { return {}; }
36 
38 
39  public:
42 
44  constexpr Channel getChannel() const { return Channel{addresses.channel}; }
46  constexpr uint8_t getRawChannel() const { return addresses.channel; }
47 
49  constexpr Cable getCableNumber() const {
50  return Cable(addresses.cableNumber);
51  }
53  constexpr uint8_t getRawCableNumber() const {
54  return addresses.cableNumber;
55  }
56 
58 
59  public:
62 
67  constexpr bool operator==(MIDIChannelCable rhs) const {
68  return this->addresses.valid && rhs.addresses.valid &&
69  this->addresses.channel == rhs.addresses.channel &&
70  this->addresses.cableNumber == rhs.addresses.cableNumber;
71  }
72 
77  constexpr bool operator!=(MIDIChannelCable rhs) const {
78  return this->addresses.valid && rhs.addresses.valid &&
79  !(this->addresses.channel == rhs.addresses.channel &&
80  this->addresses.cableNumber == rhs.addresses.cableNumber);
81  }
82 
84  constexpr bool isValid() const { return addresses.valid; }
85 
88  constexpr explicit operator bool() const { return isValid(); }
89 
91 
92  public:
95 
97  static bool matchSingle(MIDIChannelCable toMatch, MIDIChannelCable base) {
98  return base == toMatch;
99  }
100 
102 
103  private:
104  RawMIDIAddress addresses;
105 };
106 
110  friend class MIDIAddress;
111 
112  public:
113  constexpr RelativeMIDIAddress() : addresses{0, 0, 0, 0} {}
114  constexpr RelativeMIDIAddress(int deltaAddress, int deltaChannel = 0,
115  int deltaCableNumber = 0)
116  : addresses{
117  1,
118  (uint8_t)deltaAddress,
119  (uint8_t)deltaChannel,
120  (uint8_t)deltaCableNumber,
121  } {}
122  constexpr bool isValid() const { return addresses.valid; }
123 
127 
128  private:
129  RawMIDIAddress addresses;
130  static_assert(((-1) & 0x7F) == 0x7F,
131  "Negative numbers must be two's complement");
132 };
133 
141 class MIDIAddress {
142  public:
145 
147  constexpr MIDIAddress()
148  : addresses{
149  0,
150  0,
151  0,
152  0,
153  } {}
154 
166  constexpr MIDIAddress(int address, MIDIChannelCable channelCN)
167  : addresses{
168  1,
169  (uint8_t)address,
170  channelCN.getRawChannel(),
171  channelCN.getRawCableNumber(),
172  } {} // Deliberate overflow for negative numbers
173 
189  constexpr MIDIAddress(int address, Channel channel = CHANNEL_1,
190  Cable cableNumber = CABLE_1)
191  : addresses{
192  1,
193  (uint8_t)address,
194  channel.getRaw(),
195  cableNumber.getRaw(),
196  } {} // Deliberate overflow for negative numbers
197 
210  constexpr MIDIAddress(int address, Cable cableNumber)
211  : addresses{
212  1,
213  (uint8_t)address,
214  0,
215  cableNumber.getRaw(),
216  } {} // Deliberate overflow for negative numbers
217 
228  constexpr MIDIAddress(Channel channel, Cable cableNumber = CABLE_1)
229  : addresses{
230  1,
231  0,
232  channel.getRaw(),
233  cableNumber.getRaw(),
234  } {}
235 
242  constexpr MIDIAddress(MIDIChannelCable address)
243  : addresses(address.addresses) {}
244 
246  constexpr static MIDIAddress invalid() { return {}; }
247 
249 
250  public:
253 
256 
259 
262 
265 
267 
268  public:
271 
273  constexpr uint8_t getAddress() const { return addresses.address; }
274 
276  constexpr Channel getChannel() const { return Channel{addresses.channel}; }
278  constexpr uint8_t getRawChannel() const { return addresses.channel; }
279 
281  constexpr Cable getCableNumber() const {
282  return Cable(addresses.cableNumber);
283  }
285  constexpr uint8_t getRawCableNumber() const {
286  return addresses.cableNumber;
287  }
288 
290 
291  public:
294 
299  constexpr bool operator==(MIDIAddress rhs) const {
300  return this->addresses.valid && rhs.addresses.valid &&
301  this->addresses.address == rhs.addresses.address &&
302  this->addresses.channel == rhs.addresses.channel &&
303  this->addresses.cableNumber == rhs.addresses.cableNumber;
304  }
305 
310  constexpr bool operator!=(MIDIAddress rhs) const {
311  return this->addresses.valid && rhs.addresses.valid &&
312  !(this->addresses.address == rhs.addresses.address &&
313  this->addresses.channel == rhs.addresses.channel &&
314  this->addresses.cableNumber == rhs.addresses.cableNumber);
315  }
316 
318  constexpr bool isValid() const { return addresses.valid; }
319 
322  constexpr explicit operator bool() const { return isValid(); }
323 
325 
326  public:
329 
331  static bool matchSingle(MIDIAddress toMatch, MIDIAddress base) {
332  return base == toMatch;
333  }
334 
343  static bool matchAddressInRange(MIDIAddress toMatch, MIDIAddress base,
344  uint8_t length);
345 
347 
348  private:
349  RawMIDIAddress addresses;
350 };
351 
constexpr Cable CABLE_1
Definition: Cable.hpp:118
constexpr Channel CHANNEL_1
Definition: Channel.hpp:118
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
A type-safe class for MIDI USB Cable numbers.
Definition: Cable.hpp:13
A type-safe class for MIDI channels.
Definition: Channel.hpp:13
A type-safe utility class for saving a MIDI address consisting of a 7-bit address,...
constexpr bool isValid() const
Check if the MIDI address is valid.
MIDIAddress operator-(RelativeMIDIAddress rhs) const
Subtract a relative offset.
Definition: MIDIAddress.cpp:35
constexpr MIDIAddress(int address, Cable cableNumber)
Constructor.
RawMIDIAddress addresses
constexpr uint8_t getRawChannel() const
Get the channel as an integer [0, 15].
static bool matchSingle(MIDIAddress toMatch, MIDIAddress base)
Check if two addresses match (are equal).
constexpr uint8_t getAddress() const
Get the address [0, 127].
MIDIAddress & operator-=(RelativeMIDIAddress rhs)
Subtract a relative offset from this address.
Definition: MIDIAddress.cpp:21
MIDIAddress operator+(RelativeMIDIAddress rhs) const
Add a relative offset.
Definition: MIDIAddress.cpp:29
constexpr uint8_t getRawCableNumber() const
Get the cable number as an integer [0, 15].
constexpr MIDIAddress(int address, MIDIChannelCable channelCN)
Constructor.
constexpr Channel getChannel() const
Get the channel [CHANNEL_1, CHANNEL_16].
constexpr MIDIAddress(int address, Channel channel=CHANNEL_1, Cable cableNumber=CABLE_1)
Constructor.
constexpr static MIDIAddress invalid()
Return an invalid address.
static bool matchAddressInRange(MIDIAddress toMatch, MIDIAddress base, uint8_t length)
Check if an address falls within a range of MIDI addresses, starting with address base,...
Definition: MIDIAddress.cpp:41
constexpr MIDIAddress(MIDIChannelCable address)
Constructor.
MIDIAddress & operator+=(RelativeMIDIAddress rhs)
Add a relative offset to this address.
Definition: MIDIAddress.cpp:13
constexpr bool operator!=(MIDIAddress rhs) const
Check for inequality: two addresses are not equal if and only if they are both valid addresses and ha...
constexpr Cable getCableNumber() const
Get the cable number [CABLE_1, CABLE_16].
constexpr MIDIAddress()
Default constructor, creates an invalid address.
constexpr bool operator==(MIDIAddress rhs) const
Check for equality: two addresses are equal if and only if they are both valid addresses and the MIDI...
constexpr MIDIAddress(Channel channel, Cable cableNumber=CABLE_1)
Constructor.
A class for saving a MIDI channel and cable number.
Definition: MIDIAddress.hpp:24
constexpr bool isValid() const
Check if the MIDI address is valid.
Definition: MIDIAddress.hpp:84
RawMIDIAddress addresses
constexpr static MIDIChannelCable invalid()
Definition: MIDIAddress.hpp:35
constexpr uint8_t getRawChannel() const
Get the channel as an integer [0, 15].
Definition: MIDIAddress.hpp:46
constexpr MIDIChannelCable(Channel channel, Cable cableNumber=CABLE_1)
Definition: MIDIAddress.hpp:32
constexpr uint8_t getRawCableNumber() const
Get the cable number as an integer [0, 15].
Definition: MIDIAddress.hpp:53
constexpr bool operator==(MIDIChannelCable rhs) const
Check for equality: two addresses are equal if and only if they are both valid addresses and the MIDI...
Definition: MIDIAddress.hpp:67
constexpr Channel getChannel() const
Get the channel [1, 16].
Definition: MIDIAddress.hpp:44
constexpr MIDIChannelCable()
Definition: MIDIAddress.hpp:31
constexpr bool operator!=(MIDIChannelCable rhs) const
Check for inequality: two addresses are not equal if and only if they are both valid addresses and ha...
Definition: MIDIAddress.hpp:77
constexpr Cable getCableNumber() const
Get the cable number [CABLE_1, CABLE_16].
Definition: MIDIAddress.hpp:49
static bool matchSingle(MIDIChannelCable toMatch, MIDIChannelCable base)
Check if two addresses match (are equal).
Definition: MIDIAddress.hpp:97
A class for saving an offset to a MIDI address.
constexpr bool isValid() const
constexpr RelativeMIDIAddress(int deltaAddress, int deltaChannel=0, int deltaCableNumber=0)
RawMIDIAddress addresses
constexpr RelativeMIDIAddress()
RelativeMIDIAddress & operator+=(RelativeMIDIAddress that)
Compound addition.
Definition: MIDIAddress.cpp:5