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

controller.h (7448B)


      1 #pragma once
      2 
      3 #include "parameterdescriptions.h"
      4 #include "parameter.h"
      5 #include "parameterlocking.h"
      6 #include "softknob.h"
      7 
      8 #include "synthLib/midiTypes.h"
      9 
     10 #include <string>
     11 
     12 #include "parameterlinks.h"
     13 
     14 namespace juce
     15 {
     16 	class AudioProcessor;
     17 	class Value;
     18 }
     19 
     20 namespace pluginLib
     21 {
     22 	class Processor;
     23 	using SysEx = std::vector<uint8_t>;
     24 
     25 	class Controller : juce::Timer
     26 	{
     27 	public:
     28 		static constexpr uint32_t InvalidParameterIndex = 0xffffffff;
     29 
     30 		baseLib::Event<uint8_t> onCurrentPartChanged;
     31 
     32 		explicit Controller(Processor& _processor, const std::string& _parameterDescJsonFilename);
     33 		~Controller() override;
     34 
     35 		virtual void sendParameterChange(const Parameter& _parameter, ParamValue _value) = 0;
     36 		void sendLockedParameters(uint8_t _part);
     37 
     38         juce::Value* getParamValueObject(uint32_t _index, uint8_t _part) const;
     39         Parameter* getParameter(uint32_t _index) const;
     40         Parameter* getParameter(uint32_t _index, uint8_t _part) const;
     41         Parameter* getParameter(const std::string& _name, uint8_t _part) const;
     42 		
     43         uint32_t getParameterIndexByName(const std::string& _name) const;
     44 
     45 		bool setParameters(const std::map<std::string, ParamValue>& _values, uint8_t _part, Parameter::Origin _changedBy) const;
     46 
     47 		const MidiPacket* getMidiPacket(const std::string& _name) const;
     48 
     49 		bool createNamedParamValues(MidiPacket::NamedParamValues& _params, const std::string& _packetName, uint8_t _part) const;
     50 		bool createNamedParamValues(MidiPacket::NamedParamValues& _dest, const MidiPacket::AnyPartParamValues& _source) const;
     51 		bool createMidiDataFromPacket(SysEx& _sysex, const std::string& _packetName, const std::map<MidiDataType, uint8_t>& _data, uint8_t _part) const;
     52 		bool createMidiDataFromPacket(SysEx& _sysex, const std::string& _packetName, const std::map<MidiDataType, uint8_t>& _data, const MidiPacket::NamedParamValues& _values) const;
     53 		bool createMidiDataFromPacket(SysEx& _sysex, const std::string& _packetName, const std::map<MidiDataType, uint8_t>& _data, const MidiPacket::AnyPartParamValues& _values) const;
     54 
     55 		bool parseMidiPacket(const MidiPacket& _packet, MidiPacket::Data& _data, MidiPacket::ParamValues& _parameterValues, const SysEx& _src) const;
     56 		bool parseMidiPacket(const MidiPacket& _packet, MidiPacket::Data& _data, MidiPacket::AnyPartParamValues& _parameterValues, const SysEx& _src) const;
     57 		bool parseMidiPacket(const MidiPacket& _packet, MidiPacket::Data& _data, const std::function<void(MidiPacket::ParamIndex, ParamValue)>& _parameterValues, const SysEx& _src) const;
     58 		bool parseMidiPacket(const std::string& _name, MidiPacket::Data& _data, MidiPacket::ParamValues& _parameterValues, const SysEx& _src) const;
     59 		bool parseMidiPacket(std::string& _name, MidiPacket::Data& _data, MidiPacket::ParamValues& _parameterValues, const SysEx& _src) const;
     60 
     61 		const auto& getExposedParameters() const { return m_synthParams; }
     62 
     63 		uint8_t getCurrentPart() const { return m_currentPart; }
     64 		virtual bool setCurrentPart(uint8_t _part);
     65 		virtual uint8_t getPartCount() const { return 16; }
     66 
     67 		virtual bool parseSysexMessage(const SysEx&, synthLib::MidiEventSource) = 0;
     68 		virtual bool parseControllerMessage(const synthLib::SMidiEvent&) = 0;
     69 
     70 		virtual bool parseMidiMessage(const synthLib::SMidiEvent& _e);
     71 
     72 		virtual void onStateLoaded() = 0;
     73 
     74         // this is called by the plug-in on audio thread!
     75         void enqueueMidiMessages(const std::vector<synthLib::SMidiEvent>&);
     76 
     77 		void loadChunkData(baseLib::ChunkReader& _cr);
     78 		void saveChunkData(baseLib::BinaryStream& _s) const;
     79 
     80 		static Parameter::Origin midiEventSourceToParameterOrigin(synthLib::MidiEventSource _source);
     81 
     82 		std::vector<uint8_t> getPartsForMidiEvent(const synthLib::SMidiEvent& _e)
     83 		{
     84 			return getPartsForMidiChannel(_e.a & 0x0f);
     85 		}
     86 
     87 		virtual  std::vector<uint8_t> getPartsForMidiChannel(uint8_t _channel) { return {}; }
     88 
     89 	private:
     90 		void getMidiMessages(std::vector<synthLib::SMidiEvent>&);
     91 		void processMidiMessages();
     92 		std::string loadParameterDescriptions(const std::string& _filename) const;
     93 
     94 	public:
     95 		ParameterLocking& getParameterLocking() { return m_locking; }
     96 		ParameterLinks& getParameterLinks() { return m_parameterLinks; }
     97 
     98 		std::set<std::string> getRegionIdsForParameter(const Parameter* _param) const;
     99 		std::set<std::string> getRegionIdsForParameter(const std::string& _name) const;
    100 
    101 		const ParameterDescriptions& getParameterDescriptions() const { return m_descriptions; }
    102 
    103 		const SoftKnob* getSoftknob(const Parameter* _parameter) const
    104 		{
    105 			const auto it = m_softKnobs.find(_parameter);
    106 			return it->second.get();
    107 		}
    108 
    109 		SoftKnob* getSoftknob(const Parameter* _parameter)
    110 		{
    111 			const auto it = m_softKnobs.find(_parameter);
    112 			return it->second.get();
    113 		}
    114 
    115 		Processor& getProcessor() const { return m_processor; }
    116 
    117 	protected:
    118 		virtual Parameter* createParameter(Controller& _controller, const Description& _desc, uint8_t _part, int _uid, const Parameter::PartFormatter& _partFormatter);
    119 		void registerParams(juce::AudioProcessor& _processor, Parameter::PartFormatter _partFormatter = nullptr);
    120 
    121 		void sendSysEx(const pluginLib::SysEx &) const;
    122 		bool sendSysEx(const std::string& _packetName) const;
    123 		bool sendSysEx(const std::string& _packetName, const std::map<pluginLib::MidiDataType, uint8_t>& _params) const;
    124 		void sendMidiEvent(const synthLib::SMidiEvent& _ev) const;
    125 		void sendMidiEvent(uint8_t _a, uint8_t _b, uint8_t _c, uint32_t _offset = 0, synthLib::MidiEventSource _source = synthLib::MidiEventSource::Editor) const;
    126 
    127 		bool combineParameterChange(uint8_t& _result, const std::string& _midiPacket, const Parameter& _parameter, ParamValue _value) const;
    128 
    129 		void applyPatchParameters(const MidiPacket::ParamValues& _params, uint8_t _part) const;
    130 
    131 		virtual bool isDerivedParameter(Parameter& _derived, Parameter& _base) const { return true; }
    132 
    133         struct ParamIndex
    134         {
    135             uint8_t page;
    136             uint8_t partNum;
    137             uint8_t paramNum;
    138 
    139         	bool operator<(const ParamIndex& _p) const
    140             {
    141 				if (page < _p.page)         return true;
    142 				if (page > _p.page)         return false;
    143 				if (partNum < _p.partNum)   return true;
    144 				if (partNum > _p.partNum)   return false;
    145 				if (paramNum < _p.paramNum) return true;
    146 				if (paramNum > _p.paramNum) return false;
    147 				return false;
    148 			}
    149 
    150 			bool operator==(const ParamIndex& _p) const
    151             {
    152 	            return page == _p.page && partNum == _p.partNum && paramNum && _p.paramNum;
    153             }
    154         };
    155 
    156 		using ParameterList = std::vector<Parameter*>;
    157 
    158 		void timerCallback() override;
    159 
    160 	private:
    161 		Processor& m_processor;
    162         const ParameterDescriptions m_descriptions;
    163 
    164 		uint8_t m_currentPart = 0;
    165 
    166 		std::mutex m_midiMessagesLock;
    167         std::vector<synthLib::SMidiEvent> m_midiMessages;
    168 
    169 		std::map<const Parameter*, std::unique_ptr<SoftKnob>> m_softKnobs;
    170 
    171 	protected:
    172 		// tries to find synth param in both internal and host
    173 		const ParameterList& findSynthParam(uint8_t _part, uint8_t _page, uint8_t _paramIndex) const;
    174 		const ParameterList& findSynthParam(const ParamIndex& _paramIndex) const;
    175 
    176     	std::map<ParamIndex, ParameterList> m_synthInternalParams;
    177 		std::map<ParamIndex, ParameterList> m_synthParams; // exposed and managed by audio processor
    178 		std::array<ParameterList, 16> m_paramsByParamType;
    179 		std::vector<std::unique_ptr<Parameter>> m_synthInternalParamList;
    180 		ParameterLocking m_locking;
    181 		ParameterLinks m_parameterLinks;
    182 	};
    183 }