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

frontpanelState.cpp (3586B)


      1 #include "frontpanelState.h"
      2 
      3 #include "microcontrollerTypes.h"
      4 
      5 #include "synthLib/midiTypes.h"
      6 
      7 #include "dsp56kEmu/dsp.h"
      8 #include "dsp56kEmu/peripherals.h"
      9 
     10 namespace virusLib
     11 {
     12 	static constexpr std::initializer_list<uint8_t> g_midiDumpHeader = {0xf0, 0x00, 0x20, 0x33, 0x01, OMNI_DEVICE_ID, DUMP_EMU_SYNTHSTATE};
     13 
     14 	void FrontpanelState::updateLfoPhaseFromTimer(dsp56k::DSP& _dsp, const uint32_t _lfo, const uint32_t _timer, const float _minimumValue/* = 0.0f*/, float _maximumValue/* = 1.0f*/)
     15 	{
     16 		updatePhaseFromTimer(m_lfoPhases[_lfo], _dsp, _timer, _minimumValue, _maximumValue);
     17 	}
     18 
     19 	void FrontpanelState::updatePhaseFromTimer(float& _target, dsp56k::DSP& _dsp, const uint32_t _timer, float _minimumValue, float _maximumValue)
     20 	{
     21 		const auto* peripherals = _dsp.getPeriph(0);
     22 
     23 		if(const auto* p362 = dynamic_cast<const dsp56k::Peripherals56362*>(peripherals))
     24 		{
     25 			const auto& t = p362->getTimers();
     26 			updatePhaseFromTimer(_target, t, _timer, _minimumValue, _maximumValue);
     27 		}
     28 		else if(const auto* p303 = dynamic_cast<const dsp56k::Peripherals56303*>(peripherals))
     29 		{
     30 			const auto& t = p303->getTimers();
     31 			updatePhaseFromTimer(_target, t, _timer, _minimumValue, _maximumValue);
     32 		}
     33 	}
     34 
     35 	void FrontpanelState::updatePhaseFromTimer(float& _target, const dsp56k::Timers& _timers, uint32_t _timer, float _minimumValue, float _maximumValue)
     36 	{
     37 		const auto compare = _timers.readTCPR(static_cast<int>(_timer));
     38 		const auto load = _timers.readTLR(static_cast<int>(_timer));
     39 
     40 		const auto range = 0xffffff - load;
     41 
     42 		const auto normalized = static_cast<float>(compare - load) / static_cast<float>(range);
     43 
     44 		// the minimum PWM value is not always zero, we need to remap
     45 		const auto floatRange = _maximumValue - _minimumValue;
     46 		const auto floatRangeInv = 1.0f / floatRange;
     47 
     48 		_target = (normalized - _minimumValue) * floatRangeInv;
     49 	}
     50 
     51 	void writeFloat(std::vector<uint8_t>& _sysex, const float _v)
     52 	{
     53 		const auto* ptr = reinterpret_cast<const uint8_t*>(&_v);
     54 		for(size_t i=0; i<sizeof(_v); ++i)
     55 			_sysex.push_back(ptr[i]);
     56 	}
     57 
     58 	size_t readFloat(float& _dst, const uint8_t* _s)
     59 	{
     60 		auto* ptr = reinterpret_cast<uint8_t*>(&_dst);
     61 		for(size_t i=0; i<sizeof(_dst); ++i)
     62 			ptr[i] = _s[i];
     63 		return sizeof(_dst);
     64 	}
     65 
     66 	void FrontpanelState::toMidiEvent(synthLib::SMidiEvent& _e) const
     67 	{
     68 		_e.sysex.assign(g_midiDumpHeader.begin(), g_midiDumpHeader.end());
     69 
     70 		uint32_t midiEvents = 0;
     71 
     72 		for(size_t i=0; i<m_midiEventReceived.size(); ++i)
     73 		{
     74 			if(m_midiEventReceived[i])
     75 				midiEvents |= (1<<i);
     76 		}
     77 
     78 		_e.sysex.push_back((midiEvents >> 14) & 0x7f);
     79 		_e.sysex.push_back((midiEvents >> 7) & 0x7f);
     80 		_e.sysex.push_back((midiEvents) & 0x7f);
     81 
     82 		for (const auto lfoPhase : m_lfoPhases)
     83 			writeFloat(_e.sysex, lfoPhase);
     84 
     85 		writeFloat(_e.sysex, m_logo);
     86 		writeFloat(_e.sysex, m_bpm);
     87 
     88 		_e.sysex.push_back(0xf7);
     89 	}
     90 
     91 	bool FrontpanelState::fromMidiEvent(const synthLib::SMidiEvent& _e)
     92 	{
     93 		return fromMidiEvent(_e.sysex);
     94 	}
     95 
     96 	bool FrontpanelState::fromMidiEvent(const std::vector<uint8_t>& _sysex)
     97 	{
     98 		if(_sysex.size() < g_midiDumpHeader.size())
     99 			return false;
    100 
    101 		const auto* s = &_sysex[g_midiDumpHeader.size()];
    102 
    103 		uint32_t midiEvents = 0;
    104 		midiEvents |= static_cast<uint32_t>(*s) << 14; ++s;
    105 		midiEvents |= static_cast<uint32_t>(*s) << 7; ++s;
    106 		midiEvents |= static_cast<uint32_t>(*s); ++s;
    107 
    108 		for(size_t i=0; i<m_midiEventReceived.size(); ++i)
    109 			m_midiEventReceived[i] = (midiEvents & (1<<i)) ? true : false;
    110 
    111 		for (auto& lfoPhase : m_lfoPhases)
    112 			s += readFloat(lfoPhase, s);
    113 
    114 		s += readFloat(m_logo, s);
    115 		readFloat(m_bpm, s);
    116 
    117 		return true;
    118 	}
    119 }