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 }