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

xtDevice.cpp (3236B)


      1 #include "xtDevice.h"
      2 
      3 #include "xtHardware.h"
      4 
      5 namespace mqLib
      6 {
      7 	class MicroQ;
      8 }
      9 
     10 namespace xt
     11 {
     12 	Device::Device(const synthLib::DeviceCreateParams& _params) : wLib::Device(_params), m_xt(_params.romData, _params.romName), m_wavePreview(m_xt), m_state(m_xt, m_wavePreview), m_sysexRemote(m_xt)
     13 	{
     14 		while(!m_xt.isBootCompleted())
     15 			m_xt.process(8);
     16 
     17 		m_state.createInitState();
     18 
     19 		auto* hw = m_xt.getHardware();
     20 		hw->resetMidiCounter();
     21 	}
     22 
     23 	float Device::getSamplerate() const
     24 	{
     25 		return 40000.0f;
     26 	}
     27 
     28 	bool Device::isValid() const
     29 	{
     30 		return m_xt.isValid();
     31 	}
     32 
     33 	bool Device::getState(std::vector<uint8_t>& _state, synthLib::StateType _type)
     34 	{
     35 		return m_state.getState(_state, _type);
     36 	}
     37 
     38 	bool Device::setState(const std::vector<uint8_t>& _state, synthLib::StateType _type)
     39 	{
     40 		return m_state.setState(_state, _type);
     41 	}
     42 
     43 	uint32_t Device::getChannelCountIn()
     44 	{
     45 		return 2;
     46 	}
     47 
     48 	uint32_t Device::getChannelCountOut()
     49 	{
     50 		return 4;
     51 	}
     52 
     53 	void Device::readMidiOut(std::vector<synthLib::SMidiEvent>& _midiOut)
     54 	{
     55 		m_xt.receiveMidi(m_midiOutBuffer);
     56 		m_midiOutParser.write(m_midiOutBuffer);
     57 		m_midiOutParser.getEvents(_midiOut);
     58 		m_midiOutBuffer.clear();
     59 
     60 		wLib::Responses responses;
     61 
     62 		for (const auto& midiOut : _midiOut)
     63 		{
     64 			m_state.receive(responses, midiOut, State::Origin::Device);
     65 
     66 			for (auto& response : responses)
     67 			{
     68 				auto& r = _midiOut.emplace_back();
     69 				std::swap(response, r.sysex);
     70 			}
     71 		}
     72 
     73 		if(!m_customSysexOut.empty())
     74 		{
     75 			_midiOut.insert(_midiOut.begin(), m_customSysexOut.begin(), m_customSysexOut.end());
     76 			m_customSysexOut.clear();
     77 		}
     78 	}
     79 
     80 	void Device::processAudio(const synthLib::TAudioInputs& _inputs, const synthLib::TAudioOutputs& _outputs, size_t _samples)
     81 	{
     82 		m_state.process(static_cast<uint32_t>(_samples));
     83 
     84 		const float* inputs[2] = {_inputs[0], _inputs[1]};
     85 		float* outputs[4] = {_outputs[0], _outputs[1], _outputs[2], _outputs[3]};
     86 		m_xt.process(inputs, outputs, static_cast<uint32_t>(_samples), getExtraLatencySamples());
     87 
     88 		const auto dirty = static_cast<uint32_t>(m_xt.getDirtyFlags());
     89 
     90 		m_sysexRemote.handleDirtyFlags(m_customSysexOut, dirty);
     91 	}
     92 
     93 	bool Device::sendMidi(const synthLib::SMidiEvent& _ev, std::vector<synthLib::SMidiEvent>& _response)
     94 	{
     95 		const auto& sysex = _ev.sysex;
     96 
     97 		if (!sysex.empty())
     98 		{
     99 			if (m_sysexRemote.receive(m_customSysexOut, sysex))
    100 				return true;
    101 		}
    102 
    103 		Responses responses;
    104 
    105 		const auto res = m_state.receive(responses, _ev, State::Origin::External);
    106 
    107 		for (auto& response : responses)
    108 		{
    109 			auto& r = _response.emplace_back();
    110 			std::swap(response, r.sysex);
    111 		}
    112 
    113 		// do not forward to device if our cache was able to reply. It might have sent something to the device already on its own if a cache miss occured
    114 		if(res)
    115 			return true;
    116 
    117 		if(_ev.sysex.empty())
    118 		{
    119 			auto e = _ev;
    120 			e.offset += m_numSamplesProcessed + getExtraLatencySamples();
    121 			m_xt.sendMidiEvent(e);
    122 		}
    123 		else
    124 		{
    125 			m_xt.sendMidiEvent(_ev);
    126 		}
    127 		return true;
    128 	}
    129 
    130 	dsp56k::EsxiClock* Device::getDspEsxiClock() const
    131 	{
    132 		const auto& xt = const_cast<Xt&>(m_xt);
    133 		auto* p = dynamic_cast<dsp56k::Peripherals56303*>(xt.getHardware()->getDSP().dsp().getPeriph(dsp56k::MemArea_X));
    134 		if(!p)
    135 			return nullptr;
    136 		return &p->getEssiClock();
    137 	}
    138 }