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

xtState.h (8736B)


      1 #pragma once
      2 
      3 #include <array>
      4 #include <vector>
      5 #include <cstddef>
      6 #include <cstdint>
      7 #include <functional>
      8 #include <string>
      9 
     10 #include "xtMidiTypes.h"
     11 #include "xtTypes.h"
     12 
     13 #include "synthLib/deviceTypes.h"
     14 #include "synthLib/midiTypes.h"
     15 
     16 #include "wLib/wState.h"
     17 
     18 namespace synthLib
     19 {
     20 	struct SMidiEvent;
     21 }
     22 
     23 namespace xt
     24 {
     25 	class WavePreview;
     26 	class Xt;
     27 
     28 	using SysEx = wLib::SysEx;
     29 	using Responses = wLib::Responses;
     30 
     31 	class State : public wLib::State
     32 	{
     33 	public:
     34 		enum class Origin
     35 		{
     36 			Device,
     37 			External
     38 		};
     39 
     40 		enum class DumpType
     41 		{
     42 			Single,
     43 			Multi,
     44 			Global,
     45 			Mode,
     46 			Wave,
     47 			Table,
     48 
     49 			Count
     50 		};
     51 
     52 		struct Dump
     53 		{
     54 			DumpType type;
     55 			SysexCommand cmdRequest;
     56 			SysexCommand cmdDump;
     57 			SysexCommand cmdParamChange;
     58 			uint32_t firstParamIndex;
     59 			uint32_t idxParamIndexH;
     60 			uint32_t idxParamIndexL;
     61 			uint32_t idxParamValue;
     62 			uint32_t dumpSize;
     63 		};
     64 
     65 		static constexpr Dump Dumps[] = 
     66 		{
     67 			{DumpType::Single, SysexCommand::SingleRequest , SysexCommand::SingleDump , SysexCommand::SingleParameterChange , IdxSingleParamFirst, IdxSingleParamIndexH, IdxSingleParamIndexL, IdxSingleParamValue, 265},
     68 			{DumpType::Multi , SysexCommand::MultiRequest  , SysexCommand::MultiDump  , SysexCommand::MultiParameterChange  , IdxMultiParamFirst , IdxMultiParamIndexH , IdxMultiParamIndexL , IdxMultiParamValue , 265},
     69 			{DumpType::Global, SysexCommand::GlobalRequest , SysexCommand::GlobalDump , SysexCommand::GlobalParameterChange , IdxGlobalParamFirst, IdxGlobalParamIndexH, IdxGlobalParamIndexL, IdxGlobalParamValue, 39},
     70 			{DumpType::Mode  , SysexCommand::ModeRequest   , SysexCommand::ModeDump   , SysexCommand::ModeParameterChange   , IdxModeParamFirst  , IdxModeParamIndexH  , IdxModeParamIndexL  , IdxModeParamValue  , 7},
     71 			{DumpType::Wave  , SysexCommand::WaveRequest   , SysexCommand::WaveDump   , SysexCommand::WaveParameterChange   , wLib::IdxBuffer    , IdxWaveIndexH       , IdxWaveIndexL       , wLib::IdxBuffer    , 137},
     72 			{DumpType::Table , SysexCommand::WaveCtlRequest, SysexCommand::WaveCtlDump, SysexCommand::WaveCtlParameterChange, wLib::IdxBuffer    , IdxWaveIndexH       , IdxWaveIndexL       , wLib::IdxBuffer    , 265},
     73 		};
     74 
     75 		using Single = std::array<uint8_t, Dumps[static_cast<uint32_t>(DumpType::Single)].dumpSize>;
     76 		using Multi = std::array<uint8_t , Dumps[static_cast<uint32_t>(DumpType::Multi) ].dumpSize>;
     77 		using Global = std::array<uint8_t, Dumps[static_cast<uint32_t>(DumpType::Global)].dumpSize>;
     78 		using Mode = std::array<uint8_t  , Dumps[static_cast<uint32_t>(DumpType::Mode)  ].dumpSize>;
     79 		using Wave = std::array<uint8_t  , Dumps[static_cast<uint32_t>(DumpType::Wave)  ].dumpSize>;
     80 		using Table = std::array<uint8_t , Dumps[static_cast<uint32_t>(DumpType::Table) ].dumpSize>;
     81 
     82 		State(Xt& _xt, WavePreview& _wavePreview);
     83 
     84 		bool loadState(const SysEx& _sysex);
     85 
     86 		bool receive(Responses& _responses, const synthLib::SMidiEvent& _data, Origin _sender);
     87 		bool receive(Responses& _responses, const SysEx& _data, Origin _sender);
     88 		void createInitState();
     89 
     90 		bool getState(std::vector<uint8_t>& _state, synthLib::StateType _type) const;
     91 		bool setState(const std::vector<uint8_t>& _state, synthLib::StateType _type);
     92 
     93 		void process(uint32_t _numSamples);
     94 
     95 		static bool setSingleName(std::vector<uint8_t>& _sysex, const std::string& _name);
     96 
     97 		static TableId getWavetableFromSingleDump(const SysEx& _single);
     98 
     99 		static void createSequencerMultiData(std::vector<uint8_t>& _data);
    100 
    101 		static bool parseWaveData(WaveData& _wave, const SysEx& _sysex);
    102 		static bool parseMw1WaveData(WaveData& _wave, const SysEx& _sysex);
    103 
    104 		static SysEx createWaveData(const WaveData& _wave, uint16_t _waveIndex, bool _preview);
    105 		static WaveData createinterpolatedTable(const WaveData& _a, const WaveData& _b, uint16_t _indexA, uint16_t _indexB, uint16_t _indexTarget);
    106 
    107 		static bool parseTableData(TableData& _table, const SysEx& _sysex);
    108 		static bool parseMw1TableData(TableData& _table, const SysEx& _sysex);
    109 
    110 		static std::vector<WaveId> getWavesForTable(const TableData& _table);
    111 
    112 		static SysEx createTableData(const TableData& _table, uint32_t _tableIndex, bool _preview);
    113 
    114 		static SysEx createCombinedPatch(const std::vector<SysEx>& _dumps);
    115 		static bool splitCombinedPatch(std::vector<SysEx>& _dumps, const SysEx& _combinedSingle);
    116 
    117 		static SysexCommand getCommand(const SysEx& _data);
    118 
    119 		static TableId getTableId(const SysEx& _data);
    120 		static WaveId getWaveId(const SysEx& _data);
    121 
    122 		static bool isSpeech(const TableData& _table);
    123 		static bool isUpaw(const TableData& _table);
    124 
    125 		template<size_t Size> static bool append(SysEx& _dst, const std::array<uint8_t, Size>& _src, uint32_t _checksumStartIndex)
    126 		{
    127 			if(!isValid(_src))
    128 				return false;
    129 			auto src = _src;
    130 			if(_checksumStartIndex != ~0u)
    131 				wLib::State::updateChecksum(src, _checksumStartIndex);
    132 			_dst.insert(_dst.end(), src.begin(), src.end());
    133 			return true;
    134 		}
    135 
    136 		static bool updateChecksum(SysEx& _src, const uint32_t _startIndex)
    137 		{
    138 			if(_src.size() < 3)
    139 				return false;
    140 			uint8_t& c = _src[_src.size() - 2];
    141 			c = 0;
    142 			for(size_t i = _startIndex; i<_src.size()-2; ++i)
    143 				c += _src[i];
    144 			c &= 0x7f;
    145 			return true;
    146 		}
    147 
    148 	private:
    149 
    150 		bool parseSingleDump(const SysEx& _data);
    151 		bool parseMultiDump(const SysEx& _data);
    152 		bool parseGlobalDump(const SysEx& _data);
    153 		bool parseModeDump(const SysEx& _data);
    154 		bool parseWaveDump(const SysEx& _data);
    155 		bool parseTableDump(const SysEx& _data);
    156 
    157 		bool modifySingle(const SysEx& _data);
    158 		bool modifyMulti(const SysEx& _data);
    159 		bool modifyGlobal(const SysEx& _data);
    160 		bool modifyMode(const SysEx& _data);
    161 
    162 		uint8_t* getSingleParameter(const SysEx& _data);
    163 		uint8_t* getMultiParameter(const SysEx& _data);
    164 		uint8_t* getGlobalParameter(const SysEx& _data);
    165 		uint8_t* getModeParameter(const SysEx& _data);
    166 
    167 		bool getSingle(Responses& _responses, const SysEx& _data);
    168 		Single* getSingle(LocationH _buf, uint8_t _loc);
    169 
    170 		bool getMulti(Responses& _responses, const SysEx& _data);
    171 		Multi* getMulti(LocationH _buf, uint8_t _loc);
    172 
    173 		bool getGlobal(Responses& _responses);
    174 		Global* getGlobal();
    175 
    176 		bool getMode(Responses& _responses);
    177 		Mode* getMode();
    178 
    179 		bool getWave(Responses& _responses, const SysEx& _data);
    180 		Wave* getWave(WaveId _id);
    181 
    182 		bool getTable(Responses& _responses, const SysEx& _data);
    183 		Table* getTable(TableId _id);
    184 
    185 		bool getDump(DumpType _type, Responses& _responses, const SysEx& _data);
    186 		bool parseDump(DumpType _type, const SysEx& _data);
    187 		bool modifyDump(DumpType _type, const SysEx& _data);
    188 
    189 		uint8_t getGlobalParameter(GlobalParameter _parameter) const;
    190 		void setGlobalParameter(GlobalParameter _parameter, uint8_t _value);
    191 
    192 		uint8_t getModeParameter(ModeParameter _parameter) const;
    193 
    194 		bool isMultiMode() const
    195 		{
    196 			return getModeParameter(ModeParameter::Mode) != 0;
    197 		}
    198 
    199 		static bool isValid(const Single& _single)
    200 		{
    201 			return _single.front() == 0xf0;
    202 		}
    203 
    204 		static bool isValid(const Wave& _single)
    205 		{
    206 			return _single.front() == 0xf0;
    207 		}
    208 
    209 		static bool isValid(const Global& _global)
    210 		{
    211 			return _global.back() == 0xf7;
    212 		}
    213 
    214 		static bool isValid(const Mode& _mode)
    215 		{
    216 			return _mode.front() == 0xf0;
    217 		}
    218 
    219 		void forwardToDevice(const SysEx& _data);
    220 
    221 		void requestGlobal() const;
    222 		void requestMode() const;
    223 		void requestSingle(LocationH _buf, uint8_t _location) const;
    224 		void requestMulti(LocationH _buf, uint8_t _location) const;
    225 		void sendMulti(const std::vector<uint8_t>& _multiData) const;
    226 		void sendGlobalParameter(GlobalParameter _param, uint8_t _value);
    227 		void sendMultiParameter(uint8_t _instrument, MultiParameter _param, uint8_t _value);
    228 		void sendSysex(const std::initializer_list<uint8_t>& _data) const;
    229 		void sendSysex(const SysEx& _data) const;
    230 		void sendSysex(SysEx&& _data) const;
    231 
    232 		void onPlayModeChanged();
    233 
    234 		Xt& m_xt;
    235 
    236 		// ROM
    237 		std::array<Single, 256> m_romSingles{Single{}};
    238 		std::array<Multi, 128> m_romMultis{Multi{}};
    239 
    240 		// User Waves and Tables
    241 		std::array<Wave, xt::wave::g_firstRamWaveIndex + xt::wave::g_ramWaveCount> m_waves{Wave{}};
    242 		std::array<Table, xt::wave::g_tableCount> m_tables{Table{}};
    243 
    244 		// Edit Buffers
    245 		std::array<Single, 8> m_currentMultiSingles{Single{}};
    246 		std::array<Single, 1> m_currentInstrumentSingles{Single{}};
    247 		Multi m_currentMulti{};
    248 
    249 		// Global settings, only available once
    250 		Global m_global{};
    251 		Mode m_mode{};
    252 
    253 		// current state, valid while receiving data
    254 		Origin m_sender = Origin::External;
    255 		bool m_isEditBuffer = false;
    256 
    257 		// Emulator specific: preview wave editing
    258 		WavePreview& m_wavePreview;
    259 
    260 		synthLib::SMidiEvent m_lastBankSelectMSB;
    261 		synthLib::SMidiEvent m_lastBankSelectLSB;
    262 
    263 		std::vector<std::pair<int32_t, std::function<void()>>> m_delayedCalls;	// number of samples, function to call
    264 	};
    265 }