gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

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 }