device.cpp (3711B)
1 #include "device.h" 2 3 #include "synthLib/deviceTypes.h" 4 5 #include "mqbuildconfig.h" 6 #include "mqhardware.h" 7 8 namespace mqLib 9 { 10 Device::Device(const synthLib::DeviceCreateParams& _params) 11 : wLib::Device(_params) 12 , m_mq(BootMode::Default, _params.romData, _params.romName) 13 , m_state(m_mq) 14 , m_sysexRemote(m_mq) 15 { 16 // we need to hit the play button to resume boot if the used rom is an OS update. mQ will complain about an uninitialized ROM area in this case 17 m_mq.setButton(Buttons::ButtonType::Play, true); 18 while(!m_mq.isBootCompleted()) 19 m_mq.process(8); 20 m_mq.setButton(Buttons::ButtonType::Play, false); 21 22 m_state.createInitState(); 23 24 auto* hw = m_mq.getHardware(); 25 hw->resetMidiCounter(); 26 } 27 28 Device::~Device() = default; 29 30 uint32_t Device::getInternalLatencyMidiToOutput() const 31 { 32 return 0; 33 } 34 35 uint32_t Device::getInternalLatencyInputToOutput() const 36 { 37 return 0; 38 } 39 40 float Device::getSamplerate() const 41 { 42 return 44100.0f; 43 } 44 45 bool Device::isValid() const 46 { 47 return m_mq.isValid(); 48 } 49 50 bool Device::getState(std::vector<uint8_t>& _state, synthLib::StateType _type) 51 { 52 return m_state.getState(_state, _type); 53 } 54 55 bool Device::setState(const std::vector<uint8_t>& _state, synthLib::StateType _type) 56 { 57 if constexpr (g_pluginDemo) 58 return false; 59 60 return m_state.setState(_state, _type); 61 } 62 63 uint32_t Device::getChannelCountIn() 64 { 65 return 2; 66 } 67 68 uint32_t Device::getChannelCountOut() 69 { 70 return 6; 71 } 72 73 void Device::readMidiOut(std::vector<synthLib::SMidiEvent>& _midiOut) 74 { 75 m_mq.receiveMidi(m_midiOutBuffer); 76 m_midiOutParser.write(m_midiOutBuffer); 77 m_midiOutParser.getEvents(_midiOut); 78 m_midiOutBuffer.clear(); 79 80 Responses responses; 81 82 for (const auto& midiOut : _midiOut) 83 { 84 m_state.receive(responses, midiOut, State::Origin::Device); 85 86 for (auto& response : responses) 87 { 88 auto& r = _midiOut.emplace_back(); 89 std::swap(response, r.sysex); 90 } 91 } 92 93 if(!m_customSysexOut.empty()) 94 { 95 _midiOut.insert(_midiOut.begin(), m_customSysexOut.begin(), m_customSysexOut.end()); 96 m_customSysexOut.clear(); 97 } 98 } 99 100 void Device::processAudio(const synthLib::TAudioInputs& _inputs, const synthLib::TAudioOutputs& _outputs, const size_t _samples) 101 { 102 const float* inputs[2] = {_inputs[0], _inputs[1]}; 103 float* outputs[6] = {_outputs[0], _outputs[1], _outputs[2], _outputs[3], _outputs[4], _outputs[5]}; 104 105 m_mq.process(inputs, outputs, static_cast<uint32_t>(_samples), getExtraLatencySamples()); 106 107 const auto dirty = static_cast<uint32_t>(m_mq.getDirtyFlags()); 108 109 m_sysexRemote.handleDirtyFlags(m_customSysexOut, dirty); 110 } 111 112 bool Device::sendMidi(const synthLib::SMidiEvent& _ev, std::vector<synthLib::SMidiEvent>& _response) 113 { 114 const auto& sysex = _ev.sysex; 115 116 if (!sysex.empty()) 117 { 118 if (m_sysexRemote.receive(m_customSysexOut, sysex)) 119 return true; 120 } 121 122 Responses responses; 123 124 const auto res = m_state.receive(responses, _ev, State::Origin::External); 125 126 for (auto& response : responses) 127 { 128 auto& r = _response.emplace_back(); 129 std::swap(response, r.sysex); 130 } 131 132 // 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 133 if(res) 134 return true; 135 136 if(_ev.sysex.empty()) 137 { 138 auto e = _ev; 139 e.offset += m_numSamplesProcessed + getExtraLatencySamples(); 140 m_mq.sendMidiEvent(e); 141 } 142 else 143 { 144 m_mq.sendMidiEvent(_ev); 145 } 146 147 return true; 148 } 149 150 dsp56k::EsxiClock* Device::getDspEsxiClock() const 151 { 152 auto& mq = const_cast<MicroQ&>(m_mq); 153 auto* p = dynamic_cast<dsp56k::Peripherals56362*>(mq.getHardware()->getDSP().dsp().getPeriph(dsp56k::MemArea_X)); 154 if(!p) 155 return nullptr; 156 return &p->getEsaiClock(); 157 } 158 }