LCOV - code coverage report
Current view: top level - src/MIDI_Parsers - MIDI_MessageTypes.hpp (source / functions) Hit Total Coverage
Test: e224b347cd670555e44f06608ac41bd1ace9d9d8 Lines: 38 38 100.0 %
Date: 2020-09-08 17:44:46 Functions: 15 15 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <AH/Settings/Warnings.hpp>
       4             : #include <Settings/NamespaceSettings.hpp>
       5             : #include <stddef.h> // size_t
       6             : #include <stdint.h> // uint8_t
       7             : 
       8             : #ifndef ARDUINO
       9             : #include <vector>
      10             : #endif
      11             : 
      12             : AH_DIAGNOSTIC_WERROR()
      13             : 
      14             : #include <Def/Channel.hpp>
      15             : #include <Def/Cable.hpp>
      16             : 
      17             : BEGIN_CS_NAMESPACE
      18             : 
      19             : // -------------------------------------------------------------------------- //
      20             : 
      21             : enum class MIDIMessageType : uint8_t {
      22             :     NOTE_OFF = 0x80,         // 3B
      23             :     NOTE_ON = 0x90,          // 3B
      24             :     KEY_PRESSURE = 0xA0,     // 3B
      25             :     CC = 0xB0,               // 3B
      26             :     CONTROL_CHANGE = CC,     // 3B
      27             :     PROGRAM_CHANGE = 0xC0,   // 2B
      28             :     CHANNEL_PRESSURE = 0xD0, // 2B
      29             :     PITCH_BEND = 0xE0,       // 3B
      30             : 
      31             :     SYSEX_START = 0xF0,
      32             :     SYSEX_END = 0xF7,
      33             : 
      34             :     TUNE_REQUEST = 0xF6,
      35             : 
      36             :     /* System Real-Time messages */
      37             :     TIMING_CLOCK = 0xF8,
      38             :     UNDEFINED_REALTIME_1 = 0xF9,
      39             :     START = 0xFA,
      40             :     CONTINUE = 0xFB,
      41             :     STOP = 0xFC,
      42             :     UNDEFINED_REALTIME_2 = 0xFD,
      43             :     ACTIVE_SENSING = 0xFE,
      44             :     RESET = 0xFF,
      45             : };
      46             : 
      47             : /// See table 4-1 in <https://usb.org/sites/default/files/midi10.pdf>.
      48             : enum class MIDICodeIndexNumber : uint8_t {
      49             :     MISC_FUNCTION_CODES = 0x0,
      50             :     CABLE_EVENTS = 0x1,
      51             :     SYSTEM_COMMON_2B = 0x2,
      52             :     SYSTEM_COMMON_3B = 0x3,
      53             :     SYSEX_START_CONT = 0x4,
      54             :     SYSTEM_COMMON_1B = 0x5,
      55             :     SYSEX_END_1B = 0x5,
      56             :     SYSEX_END_2B = 0x6,
      57             :     SYSEX_END_3B = 0x7,
      58             : 
      59             :     NOTE_OFF = 0x8,
      60             :     NOTE_ON = 0x9,
      61             :     KEY_PRESSURE = 0xA,
      62             :     CONTROL_CHANGE = 0xB,
      63             :     PROGRAM_CHANGE = 0xC,
      64             :     CHANNEL_PRESSURE = 0xD,
      65             :     PITCH_BEND = 0xE,
      66             : 
      67             :     SINGLE_BYTE = 0xF,
      68             : };
      69             : 
      70             : // -------------------------------------------------------------------------- //
      71             : 
      72             : struct ChannelMessage {
      73             :     /// Constructor.
      74         221 :     ChannelMessage(uint8_t header, uint8_t data1, uint8_t data2, uint8_t CN)
      75         221 :         : header(header), data1(data1), data2(data2), CN(CN) {}
      76             : 
      77             :     /// Constructor.
      78             :     ChannelMessage(MIDIMessageType type, Channel channel, uint8_t data1,
      79             :                    uint8_t data2 = 0x00, Cable cable = CABLE_1)
      80             :         : ChannelMessage(uint8_t(type) | channel.getRaw(), data1, data2,
      81             :                          cable.getRaw()) {}
      82             : 
      83             :     uint8_t header; ///< MIDI status byte (message type and channel).
      84             :     uint8_t data1;  ///< First MIDI data byte
      85             :     uint8_t data2;  ///< First MIDI data byte
      86             : 
      87             :     uint8_t CN; ///< USB MIDI cable number;
      88             : 
      89             :     /// Check for equality.
      90          25 :     bool operator==(ChannelMessage other) const {
      91          50 :         return this->header == other.header && this->data1 == other.data1 &&
      92          25 :                this->data2 == other.data2 && this->CN == other.CN;
      93             :     }
      94             :     /// Check for inequality.
      95             :     bool operator!=(ChannelMessage other) const { return !(*this == other); }
      96             : 
      97             :     /// Get the MIDI channel of the message.
      98           2 :     Channel getChannel() const { return Channel(header & 0x0F); }
      99             :     /// Set the MIDI channel of the message.
     100           1 :     void setChannel(Channel channel) {
     101           1 :         header &= 0xF0;
     102           1 :         header |= channel.getRaw();
     103           1 :     }
     104             : 
     105             :     /// Get the MIDI USB cable number of the message.
     106             :     Cable getCable() const { return Cable(CN); }
     107             :     /// Set the MIDI USB cable number of the message.
     108             :     void setCable(Cable cable) { CN = cable.getRaw(); }
     109             : 
     110             :     /// Get the MIDI message type.
     111         773 :     MIDIMessageType getMessageType() const {
     112         773 :         return static_cast<MIDIMessageType>(header & 0xF0);
     113             :     }
     114             :     /// Set the MIDI message type.
     115             :     void setMessageType(MIDIMessageType type) {
     116             :         header &= 0x0F;
     117             :         header |= static_cast<uint8_t>(type) & 0xF0;
     118             :     }
     119             : 
     120             :     /// Check whether this message has one or two data bytes.
     121             :     ///
     122             :     /// - 2 data bytes: Note On/Off, Aftertouch, Control Change or Pitch Bend
     123             :     /// - 1 data byte: Program Change or Channel Pressure
     124         451 :     bool hasTwoDataBytes() const {
     125         451 :         auto type = getMessageType();
     126         451 :         return type <= MIDIMessageType::CONTROL_CHANGE ||
     127         332 :                type == MIDIMessageType::PITCH_BEND;
     128         451 :     }
     129             : 
     130             :     /// Check whether the header is a valid header for a channel message.
     131         322 :     bool hasValidHeader() const {
     132         322 :         auto type = getMessageType();
     133         644 :         return type >= MIDIMessageType::NOTE_OFF &&
     134         322 :                type <= MIDIMessageType::PITCH_BEND;
     135         322 :     }
     136             : };
     137             : 
     138             : struct SysExMessage {
     139             :     /// Constructor.
     140           3 :     SysExMessage() : data(nullptr), length(0), CN(0) {}
     141             : 
     142             :     /// Constructor.
     143          97 :     SysExMessage(const uint8_t *data, size_t length, uint8_t CN)
     144          97 :         : data(data), length(length), CN(CN) {}
     145             : 
     146             :     /// Constructor.
     147          24 :     SysExMessage(const uint8_t *data, size_t length, Cable cable = CABLE_1)
     148          24 :         : data(data), length(length), CN(cable.getRaw()) {}
     149             : 
     150             : #ifndef ARDUINO
     151             :     /// Constructor.
     152          12 :     SysExMessage(const std::vector<uint8_t> &vec, Cable cable = CABLE_1)
     153          12 :         : SysExMessage(vec.data(), vec.size(), cable) {}
     154             : #endif
     155             : 
     156             :     const uint8_t *data;
     157             :     uint8_t length;
     158             :     uint8_t CN;
     159             : 
     160           7 :     bool operator==(SysExMessage other) const {
     161          14 :         return this->length == other.length &&
     162           7 :                this->data == other.data && // TODO: compare contents or pointer?
     163           7 :                this->CN == other.CN;
     164             :     }
     165             :     bool operator!=(SysExMessage other) const { return !(*this == other); }
     166             : 
     167             :     /// Get the MIDI USB cable number of the message.
     168             :     Cable getCable() const { return Cable(CN); }
     169             :     /// Set the MIDI USB cable number of the message.
     170             :     void setCable(Cable cable) { CN = cable.getRaw(); }
     171             : };
     172             : 
     173             : struct RealTimeMessage {
     174             :     /// Constructor.
     175         105 :     RealTimeMessage(uint8_t message, uint8_t cn) : message(message), CN(cn) {}
     176             : 
     177             :     /// Constructor.
     178           8 :     RealTimeMessage(MIDIMessageType message, uint8_t cn)
     179           8 :         : message(uint8_t(message)), CN(cn) {}
     180             : 
     181             :     /// Constructor.
     182             :     RealTimeMessage(uint8_t message, Cable cable = CABLE_1)
     183             :         : message(message), CN(cable.getRaw()) {}
     184             : 
     185             :     /// Constructor.
     186             :     RealTimeMessage(MIDIMessageType message, Cable cable = CABLE_1)
     187             :         : message(uint8_t(message)), CN(cable.getRaw()) {}
     188             : 
     189             :     uint8_t message;
     190             :     uint8_t CN;
     191             : 
     192          27 :     bool operator==(RealTimeMessage other) const {
     193          27 :         return this->message == other.message && this->CN == other.CN;
     194             :     }
     195             :     bool operator!=(RealTimeMessage other) const { return !(*this == other); }
     196             : 
     197             :     /// Get the MIDI USB cable number of the message.
     198             :     Cable getCable() const { return Cable(CN); }
     199             :     /// Set the MIDI USB cable number of the message.
     200             :     void setCable(Cable cable) { CN = cable.getRaw(); }
     201             : };
     202             : 
     203             : END_CS_NAMESPACE
     204             : 
     205             : AH_DIAGNOSTIC_POP()

Generated by: LCOV version 1.14-6-g40580cd