midipacket.h (4450B)
1 #pragma once 2 3 #include <cstdint> 4 #include <functional> 5 #include <map> 6 #include <optional> 7 #include <set> 8 #include <string> 9 #include <unordered_map> 10 #include <vector> 11 12 #include "types.h" 13 14 namespace pluginLib 15 { 16 class ParameterDescriptions; 17 18 enum class MidiDataType 19 { 20 Null, 21 Byte, 22 DeviceId, 23 Checksum, 24 Bank, 25 Program, 26 Parameter, 27 ParameterIndex, 28 ParameterValue, 29 Page, 30 Part 31 }; 32 33 class MidiPacket 34 { 35 public: 36 static constexpr uint8_t AnyPart = 0xff; 37 static constexpr uint32_t InvalidIndex = 0xffffffff; 38 39 struct MidiDataDefinition 40 { 41 MidiDataType type = MidiDataType::Null; 42 43 uint8_t byte = 0; 44 45 std::string paramName; 46 uint8_t paramMask = 0xff; 47 uint8_t paramShiftRight = 0; // right shift for unpacking from midi, left for packing 48 uint8_t paramShiftLeft = 0; // left shift for unpacking from midi, right for packing 49 uint8_t paramPart = AnyPart; 50 51 uint32_t checksumFirstIndex = 0; 52 uint32_t checksumLastIndex = 0; 53 uint8_t checksumInitValue = 0; 54 55 uint8_t packValue(const ParamValue _unmasked) const 56 { 57 return static_cast<uint8_t>(((_unmasked & paramMask) << paramShiftRight) >> paramShiftLeft); 58 } 59 60 ParamValue unpackValue(const uint8_t _masked) const 61 { 62 return ((_masked << paramShiftLeft) >> paramShiftRight) & paramMask; 63 } 64 65 bool doMasksOverlap(const MidiDataDefinition& _d) const 66 { 67 return (packValue(0xff) & _d.packValue(0xff)) != 0; 68 } 69 }; 70 71 using Data = std::map<MidiDataType, uint8_t>; 72 using ParamIndex = std::pair<uint8_t,uint32_t>; 73 74 struct ParamIndexHash 75 { 76 std::size_t operator () (const ParamIndex& p) const 77 { 78 static_assert(sizeof(std::size_t) > sizeof(uint32_t) + sizeof(uint8_t), "need a 64 bit compiler"); 79 return (static_cast<std::size_t>(p.first) << 32) | p.second; 80 } 81 }; 82 83 using ParamIndices = std::set<ParamIndex>; 84 using ParamValues = std::unordered_map<ParamIndex, ParamValue, ParamIndexHash>; // part, index => value 85 using AnyPartParamValues = std::vector<std::optional<ParamValue>>; // index => value 86 using NamedParamValues = std::map<std::pair<uint8_t,std::string>, ParamValue>; // part, name => value 87 using Sysex = std::vector<uint8_t>; 88 89 MidiPacket() = default; 90 explicit MidiPacket(std::string _name, std::vector<MidiDataDefinition>&& _bytes); 91 92 const std::vector<MidiDataDefinition>& definitions() { return m_definitions; } 93 uint32_t size() const { return m_byteSize; } 94 95 bool create(std::vector<uint8_t>& _dst, const Data& _data, const NamedParamValues& _paramValues) const; 96 bool create(std::vector<uint8_t>& _dst, const Data& _data) const; 97 bool parse(Data& _data, AnyPartParamValues& _parameterValues, const ParameterDescriptions& _parameters, const Sysex& _src, bool _ignoreChecksumErrors = true) const; 98 bool parse(Data& _data, ParamValues& _parameterValues, const ParameterDescriptions& _parameters, const Sysex& _src, bool _ignoreChecksumErrors = true) const; 99 bool parse(Data& _data, const std::function<void(ParamIndex, ParamValue)>& _addParamValueCallback, const ParameterDescriptions& _parameters, const Sysex& _src, bool _ignoreChecksumErrors = true) const; 100 bool getParameterIndices(ParamIndices& _indices, const ParameterDescriptions& _parameters) const; 101 bool getDefinitionsForByteIndex(std::vector<const MidiDataDefinition*>& _result, uint32_t _byteIndex) const; 102 bool getParameterIndicesForByteIndex(std::vector<ParamIndex>& _result, const ParameterDescriptions& _parameters, uint32_t _byteIndex) const; 103 104 uint32_t getByteIndexForType(MidiDataType _type) const; 105 uint32_t getByteIndexForParameterName(const std::string& _name) const; 106 std::vector<uint32_t> getDefinitionIndicesForParameterName(const std::string& _name) const; 107 const MidiDataDefinition *getDefinitionByParameterName(const std::string& _name) const; 108 109 ParamValue getParameterValue(const Sysex& _sysex, const std::vector<uint32_t>& _definitionIndices) const; 110 111 bool updateChecksums(Sysex& _data) const; 112 113 bool hasPartDependentParameters() const { return m_numDifferentPartsUsedInParameters; } 114 115 private: 116 117 static uint8_t calcChecksum(const MidiDataDefinition& _d, const Sysex& _src); 118 119 const std::string m_name; 120 std::vector<MidiDataDefinition> m_definitions; 121 std::map<uint32_t, uint32_t> m_definitionToByteIndex; 122 std::vector<std::vector<uint32_t>> m_byteToDefinitionIndex; 123 uint32_t m_byteSize = 0; 124 bool m_hasParameters = false; 125 uint32_t m_numDifferentPartsUsedInParameters = 0; 126 }; 127 }