xt.cpp (3647B)
1 #include "xt.h" 2 3 #include "synthLib/midiTypes.h" 4 5 #include "dsp56kEmu/threadtools.h" 6 7 #include "xtHardware.h" 8 #include "xtRomLoader.h" 9 10 namespace xt 11 { 12 Xt::Xt(const std::vector<uint8_t>& _romData, const std::string& _romName) 13 { 14 m_hw.reset(new Hardware(_romData, _romName)); 15 16 if(!isValid()) 17 return; 18 19 m_midiOutBuffer.reserve(1024); 20 21 m_ucThread.reset(new std::thread([&]() 22 { 23 dsp56k::ThreadTools::setCurrentThreadPriority(dsp56k::ThreadPriority::Highest); 24 dsp56k::ThreadTools::setCurrentThreadName("MC68331"); 25 while(!m_destroy) 26 processUcThread(); 27 m_destroy = false; 28 m_hw->ucThreadTerminated(); 29 })); 30 31 m_hw->initVoiceExpansion(); 32 33 m_hw->getUC().setLcdDirtyCallback([this] 34 { 35 m_dirtyFlags.fetch_or(static_cast<uint32_t>(DirtyFlags::Lcd)); 36 }); 37 m_hw->getUC().setLedsDirtyCallback([this] 38 { 39 m_dirtyFlags.fetch_or(static_cast<uint32_t>(DirtyFlags::Leds)); 40 }); 41 } 42 43 Xt::~Xt() 44 { 45 if(!isValid()) 46 return; 47 48 // we need to have passed the boot stage 49 m_hw->processAudio(1); 50 51 m_destroy = true; 52 53 // DSP needs to run to let the uc thread wake up 54 const auto& esai = m_hw->getDSP().getPeriph().getEssi0(); 55 while(m_destroy) 56 { 57 if(!esai.getAudioOutputs().empty()) 58 m_hw->processAudio(1); 59 else 60 std::this_thread::yield(); 61 } 62 63 m_ucThread->join(); 64 m_ucThread.reset(); 65 m_hw.reset(); 66 } 67 68 bool Xt::isValid() const 69 { 70 return m_hw && m_hw->isValid(); 71 } 72 73 void Xt::process(const float** _inputs, float** _outputs, uint32_t _frames, uint32_t _latency) 74 { 75 std::lock_guard lock(m_mutex); 76 77 m_hw->ensureBufferSize(_frames); 78 79 // convert inputs from float to DSP words 80 auto& dspIns = m_hw->getAudioInputs(); 81 82 for(size_t c=0; c<dspIns.size(); ++c) 83 { 84 for(uint32_t i=0; i<_frames; ++i) 85 dspIns[c][i] = dsp56k::sample2dsp(_inputs[c][i]); 86 } 87 88 internalProcess(_frames, _latency); 89 90 // convert outputs from DSP words to float 91 const auto& dspOuts = m_hw->getAudioOutputs(); 92 93 for(size_t c=0; c<dspOuts.size(); ++c) 94 { 95 for(uint32_t i=0; i<_frames; ++i) 96 _outputs[c][i] = dsp56k::dsp2sample<float>(dspOuts[c][i]); 97 } 98 } 99 100 void Xt::process(uint32_t _frames, uint32_t _latency) 101 { 102 std::lock_guard lock(m_mutex); 103 internalProcess(_frames, _latency); 104 } 105 106 void Xt::internalProcess(uint32_t _frames, uint32_t _latency) 107 { 108 // process audio 109 m_hw->processAudio(_frames, _latency); 110 111 // receive midi output 112 m_hw->receiveMidi(m_midiOutBuffer); 113 } 114 115 TAudioInputs& Xt::getAudioInputs() const 116 { 117 return m_hw->getAudioInputs(); 118 } 119 120 TAudioOutputs& Xt::getAudioOutputs() const 121 { 122 return m_hw->getAudioOutputs(); 123 } 124 125 void Xt::sendMidiEvent(const synthLib::SMidiEvent& _ev) const 126 { 127 m_hw->sendMidi(_ev); 128 } 129 130 void Xt::receiveMidi(std::vector<uint8_t>& _buffer) 131 { 132 std::lock_guard lock(m_mutex); 133 std::swap(_buffer, m_midiOutBuffer); 134 m_midiOutBuffer.clear(); 135 } 136 137 Hardware* Xt::getHardware() const 138 { 139 return m_hw.get(); 140 } 141 142 bool Xt::isBootCompleted() const 143 { 144 return m_hw && m_hw->isBootCompleted(); 145 } 146 147 Xt::DirtyFlags Xt::getDirtyFlags() 148 { 149 const auto r = m_dirtyFlags.exchange(0); 150 return static_cast<DirtyFlags>(r); 151 } 152 153 void Xt::readLCD(std::array<char, 80>& _lcdData) const 154 { 155 _lcdData = m_hw->getUC().getLcd().getData(); 156 } 157 158 bool Xt::getLedState(LedType _led) const 159 { 160 return m_hw->getUC().getLedState(_led); 161 } 162 163 bool Xt::getButton(ButtonType _button) const 164 { 165 return m_hw->getUC().getButton(_button); 166 } 167 168 void Xt::processUcThread() const 169 { 170 for(size_t i=0; i<32; ++i) 171 { 172 m_hw->process(); 173 m_hw->process(); 174 m_hw->process(); 175 m_hw->process(); 176 m_hw->process(); 177 m_hw->process(); 178 m_hw->process(); 179 m_hw->process(); 180 } 181 } 182 }