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

commit cae54d750224b623ce515c9325f5067ee2b7e0ea
parent 774c14c323c1d901a26aa7399c3bc1377079491b
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Tue, 30 Apr 2024 23:15:28 +0200

refactor xt/mq hardware classes, remove duplicated code by moving to base class

Diffstat:
Msource/mqLib/mqhardware.cpp | 158++-----------------------------------------------------------------------------
Msource/mqLib/mqhardware.h | 53+++++++++++++----------------------------------------
Msource/wLib/wHardware.cpp | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msource/wLib/wHardware.h | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msource/xtLib/xtHardware.cpp | 180++-----------------------------------------------------------------------------
Msource/xtLib/xtHardware.h | 66++++++++++++++++--------------------------------------------------
6 files changed, 269 insertions(+), 420 deletions(-)

diff --git a/source/mqLib/mqhardware.cpp b/source/mqLib/mqhardware.cpp @@ -18,15 +18,9 @@ namespace mqLib static_assert(ROM_DATA_SIZE == ROM::g_romSize); #endif - constexpr uint32_t g_syncEsaiFrameRate = 8; - constexpr uint32_t g_syncHaltDspEsaiThreshold = 16; - - static_assert((g_syncEsaiFrameRate & (g_syncEsaiFrameRate - 1)) == 0, "esai frame sync rate must be power of two"); - static_assert(g_syncHaltDspEsaiThreshold >= g_syncEsaiFrameRate * 2, "esai DSP halt threshold must be greater than two times the sync rate"); - - Hardware::Hardware(std::string _romFilename) - : m_romFileName(std::move(_romFilename)) - , m_rom(m_romFileName, ROM_DATA) + Hardware::Hardware(const std::string& _romFilename) + : wLib::Hardware(44100) + , m_rom(_romFilename, ROM_DATA) , m_uc(m_rom) #if MQ_VOICE_EXPANSION , m_dsps{MqDsp(*this, m_uc.getHdi08A().getHdi08(), 0), MqDsp(*this, m_uc.getHdi08B().getHdi08(), 1) , MqDsp(*this, m_uc.getHdi08C().getHdi08(), 2)} @@ -54,16 +48,6 @@ namespace mqLib { processUcCycle(); } - - void Hardware::sendMidi(const synthLib::SMidiEvent& _ev) - { - m_midiIn.push_back(_ev); - } - - void Hardware::receiveMidi(std::vector<uint8_t>& _data) - { - m_midi.readTransmitBuffer(_data); - } void Hardware::setBootMode(const BootMode _mode) { @@ -138,29 +122,6 @@ namespace mqLib #endif } - void Hardware::ucYieldLoop(const std::function<bool()>& _continue) - { - const auto dspHalted = m_haltDSP; - - resumeDSP(); - - while(_continue()) - { - if(m_processAudio) - { - std::this_thread::yield(); - } - else - { - std::unique_lock uLock(m_esaiFrameAddedMutex); - m_esaiFrameAddedCv.wait(uLock); - } - } - - if(dspHalted) - haltDSP(); - } - void Hardware::initVoiceExpansion() { if (m_dsps.size() < 3) @@ -221,27 +182,7 @@ namespace mqLib esaiA.setCallback([&](dsp56k::Audio*) { - ++m_esaiFrameIndex; - - processMidiInput(); - - if((m_esaiFrameIndex & (g_syncEsaiFrameRate-1)) == 0) - m_esaiFrameAddedCv.notify_one(); - - m_requestedFramesAvailableMutex.lock(); - - if(m_requestedFrames && esaiA.getAudioOutputs().size() >= m_requestedFrames) - { - m_requestedFramesAvailableMutex.unlock(); - m_requestedFramesAvailableCv.notify_one(); - } - else - { - m_requestedFramesAvailableMutex.unlock(); - } - - std::unique_lock uLock(m_haltDSPmutex); - m_haltDSPcv.wait(uLock, [&]{ return m_haltDSP == false; }); + onEsaiCallback(esaiA); }, 0); } @@ -275,27 +216,6 @@ namespace mqLib } } - void Hardware::haltDSP() - { - if(m_haltDSP) - return; - - std::lock_guard uLockHalt(m_haltDSPmutex); - m_haltDSP = true; - } - - void Hardware::resumeDSP() - { - if(!m_haltDSP) - return; - - { - std::lock_guard uLockHalt(m_haltDSPmutex); - m_haltDSP = false; - } - m_haltDSPcv.notify_one(); - } - void Hardware::setGlobalDefaultParameters() { m_midi.writeMidi({0xf0,0x3e,0x10,0x7f,0x24,0x00,0x07,0x02,0xf7}); // Control Send = SysEx @@ -303,76 +223,6 @@ namespace mqLib m_bootCompleted = true; } - void Hardware::syncUcToDSP() - { - if(m_remainingUcCycles > 0) - return; - - // we can only use ESAI to clock the uc once it has been enabled - if(m_esaiFrameIndex <= 0) - return; - - if(m_esaiFrameIndex == m_lastEsaiFrameIndex) - { - resumeDSP(); - std::unique_lock uLock(m_esaiFrameAddedMutex); - m_esaiFrameAddedCv.wait(uLock, [this]{return m_esaiFrameIndex > m_lastEsaiFrameIndex;}); - } - - const auto esaiFrameIndex = m_esaiFrameIndex; - - const auto ucClock = m_uc.getSim().getSystemClockHz(); - - constexpr double divInv = 1.0 / 44100.0; // stereo interleaved - const double ucCyclesPerFrame = static_cast<double>(ucClock) * divInv; - - const auto esaiDelta = esaiFrameIndex - m_lastEsaiFrameIndex; - - m_remainingUcCyclesD += ucCyclesPerFrame * static_cast<double>(esaiDelta); - m_remainingUcCycles = static_cast<int64_t>(m_remainingUcCyclesD); - m_remainingUcCyclesD -= static_cast<double>(m_remainingUcCycles); - - if(esaiDelta > g_syncHaltDspEsaiThreshold) - { - haltDSP(); - } - else - { - resumeDSP(); - } - - m_lastEsaiFrameIndex = esaiFrameIndex; - } - - void Hardware::processMidiInput() - { - ++m_midiOffsetCounter; - - while(!m_midiIn.empty()) - { - const auto& e = m_midiIn.front(); - - if(e.offset > m_midiOffsetCounter) - break; - - if(!e.sysex.empty()) - { - m_midi.writeMidi(e.sysex); - } - else - { - m_midi.writeMidi(e.a); - const auto len = synthLib::MidiBufferParser::lengthFromStatusByte(e.a); - if (len > 1) - m_midi.writeMidi(e.b); - if (len > 2) - m_midi.writeMidi(e.c); - } - - m_midiIn.pop_front(); - } - } - void Hardware::processAudio(uint32_t _frames, uint32_t _latency) { ensureBufferSize(_frames); diff --git a/source/mqLib/mqhardware.h b/source/mqLib/mqhardware.h @@ -22,7 +22,7 @@ namespace mqLib static constexpr uint32_t g_dspCount = g_useVoiceExpansion ? 3 : 1; public: - explicit Hardware(std::string _romFilename); + explicit Hardware(const std::string& _romFilename); ~Hardware(); void process(); @@ -34,9 +34,6 @@ namespace mqLib auto& getAudioInputs() { return m_audioInputs; } auto& getAudioOutputs() { return m_audioOutputs; } - void sendMidi(const synthLib::SMidiEvent& _ev); - void receiveMidi(std::vector<uint8_t>& _data); - dsp56k::DSPThread& getDspThread(uint32_t _index = 0) { return m_dsps[_index].thread(); } void processAudio(uint32_t _frames, uint32_t _latency = 0); @@ -55,57 +52,33 @@ namespace mqLib bool isBootCompleted() const { return m_bootCompleted; } void resetMidiCounter(); - void ucYieldLoop(const std::function<bool()>& _continue); void initVoiceExpansion(); + wLib::Midi& getMidi() override + { + return m_midi; + } + + mc68k::Mc68k& getUc() override + { + return m_uc; + } + private: void setupEsaiListener(); void hdiProcessUCtoDSPNMIIrq(); void processUcCycle(); - void haltDSP(); - void resumeDSP(); void setGlobalDefaultParameters(); - void syncUcToDSP(); - void processMidiInput(); - - const std::string m_romFileName; const ROM m_rom; bool m_requestNMI = false; - // timing - uint32_t m_esaiFrameIndex = 0; - uint32_t m_lastEsaiFrameIndex = 0; - int64_t m_remainingUcCycles = 0; - double m_remainingUcCyclesD = 0; - MqMc m_uc; - std::array<MqDsp,g_dspCount> m_dsps; - - wLib::Midi m_midi; - dsp56k::RingBuffer<synthLib::SMidiEvent, 16384, true> m_midiIn; - uint32_t m_midiOffsetCounter = 0; - - std::vector<dsp56k::TWord> m_delayedAudioIn; - - std::vector<dsp56k::TWord> m_dummyInput; - std::vector<dsp56k::TWord> m_dummyOutput; - TAudioInputs m_audioInputs; TAudioOutputs m_audioOutputs; + std::array<MqDsp,g_dspCount> m_dsps; - std::mutex m_esaiFrameAddedMutex; - std::condition_variable m_esaiFrameAddedCv; - - std::mutex m_requestedFramesAvailableMutex; - std::condition_variable m_requestedFramesAvailableCv; - size_t m_requestedFrames = 0; - - bool m_haltDSP = false; - std::condition_variable m_haltDSPcv; - std::mutex m_haltDSPmutex; - bool m_processAudio = false; - bool m_bootCompleted = false; + wLib::Midi m_midi; }; } diff --git a/source/wLib/wHardware.cpp b/source/wLib/wHardware.cpp @@ -1,5 +1,170 @@ #include "wHardware.h" +#include "wMidi.h" +#include "dsp56kEmu/audio.h" + +#include "../synthLib/midiBufferParser.h" + +#include "../mc68k/mc68k.h" + namespace wLib { + constexpr uint32_t g_syncEsaiFrameRate = 8; + constexpr uint32_t g_syncHaltDspEsaiThreshold = 16; + + static_assert((g_syncEsaiFrameRate & (g_syncEsaiFrameRate - 1)) == 0, "esai frame sync rate must be power of two"); + static_assert(g_syncHaltDspEsaiThreshold >= g_syncEsaiFrameRate * 2, "esai DSP halt threshold must be greater than two times the sync rate"); + + Hardware::Hardware(const double& _samplerate) : m_samplerateInv(1.0 / _samplerate) + { + } + + void Hardware::haltDSP() + { + if(m_haltDSP) + return; + + std::lock_guard uLockHalt(m_haltDSPmutex); + m_haltDSP = true; + } + + void Hardware::resumeDSP() + { + if(!m_haltDSP) + return; + + { + std::lock_guard uLockHalt(m_haltDSPmutex); + m_haltDSP = false; + } + m_haltDSPcv.notify_one(); + } + + void Hardware::ucYieldLoop(const std::function<bool()>& _continue) + { + const auto dspHalted = m_haltDSP; + + resumeDSP(); + + while(_continue()) + { + if(m_processAudio) + { + std::this_thread::yield(); + } + else + { + std::unique_lock uLock(m_esaiFrameAddedMutex); + m_esaiFrameAddedCv.wait(uLock); + } + } + + if(dspHalted) + haltDSP(); + } + + void Hardware::sendMidi(const synthLib::SMidiEvent& _ev) + { + m_midiIn.push_back(_ev); + } + + void Hardware::receiveMidi(std::vector<uint8_t>& _data) + { + getMidi().readTransmitBuffer(_data); + } + + void Hardware::onEsaiCallback(dsp56k::Audio& _audio) + { + ++m_esaiFrameIndex; + + processMidiInput(); + + if((m_esaiFrameIndex & (g_syncEsaiFrameRate-1)) == 0) + m_esaiFrameAddedCv.notify_one(); + + m_requestedFramesAvailableMutex.lock(); + + if(m_requestedFrames && _audio.getAudioOutputs().size() >= m_requestedFrames) + { + m_requestedFramesAvailableMutex.unlock(); + m_requestedFramesAvailableCv.notify_one(); + } + else + { + m_requestedFramesAvailableMutex.unlock(); + } + + std::unique_lock uLock(m_haltDSPmutex); + m_haltDSPcv.wait(uLock, [&]{ return m_haltDSP == false; }); + } + + void Hardware::syncUcToDSP() + { + if(m_remainingUcCycles > 0) + return; + + // we can only use ESAI to clock the uc once it has been enabled + if(m_esaiFrameIndex <= 0) + return; + + if(m_esaiFrameIndex == m_lastEsaiFrameIndex) + { + resumeDSP(); + std::unique_lock uLock(m_esaiFrameAddedMutex); + m_esaiFrameAddedCv.wait(uLock, [this]{return m_esaiFrameIndex > m_lastEsaiFrameIndex;}); + } + + const auto esaiFrameIndex = m_esaiFrameIndex; + + const auto ucClock = getUc().getSim().getSystemClockHz(); + + constexpr double divInv = 1.0 / 44100.0; // stereo interleaved + const double ucCyclesPerFrame = static_cast<double>(ucClock) * divInv; + + const auto esaiDelta = esaiFrameIndex - m_lastEsaiFrameIndex; + + m_remainingUcCyclesD += ucCyclesPerFrame * static_cast<double>(esaiDelta); + m_remainingUcCycles = static_cast<int64_t>(m_remainingUcCyclesD); + m_remainingUcCyclesD -= static_cast<double>(m_remainingUcCycles); + + if(esaiDelta > g_syncHaltDspEsaiThreshold) + { + haltDSP(); + } + else + { + resumeDSP(); + } + + m_lastEsaiFrameIndex = esaiFrameIndex; + } + + void Hardware::processMidiInput() + { + ++m_midiOffsetCounter; + + while(!m_midiIn.empty()) + { + const auto& e = m_midiIn.front(); + + if(e.offset > m_midiOffsetCounter) + break; + + if(!e.sysex.empty()) + { + getMidi().writeMidi(e.sysex); + } + else + { + getMidi().writeMidi(e.a); + const auto len = synthLib::MidiBufferParser::lengthFromStatusByte(e.a); + if (len > 1) + getMidi().writeMidi(e.b); + if (len > 2) + getMidi().writeMidi(e.c); + } + + m_midiIn.pop_front(); + } + } } diff --git a/source/wLib/wHardware.h b/source/wLib/wHardware.h @@ -1,8 +1,75 @@ #pragma once +#include <cstdint> +#include <functional> + +#include "dsp56kEmu/ringbuffer.h" +#include "dsp56kEmu/types.h" + +#include "../synthLib/midiTypes.h" + +namespace mc68k +{ + class Mc68k; +} + +namespace dsp56k +{ + class Audio; +} + namespace wLib { + class Midi; + class Hardware { + public: + Hardware(const double& _samplerate); + virtual ~Hardware() = default; + + virtual Midi& getMidi() = 0; + virtual mc68k::Mc68k& getUc() = 0; + + void haltDSP(); + void resumeDSP(); + + void ucYieldLoop(const std::function<bool()>& _continue); + + void sendMidi(const synthLib::SMidiEvent& _ev); + void receiveMidi(std::vector<uint8_t>& _data); + + protected: + void onEsaiCallback(dsp56k::Audio& _audio); + void syncUcToDSP(); + void processMidiInput(); + + // timing + const double m_samplerateInv; + uint32_t m_esaiFrameIndex = 0; + uint32_t m_lastEsaiFrameIndex = 0; + int64_t m_remainingUcCycles = 0; + double m_remainingUcCyclesD = 0; + + dsp56k::RingBuffer<synthLib::SMidiEvent, 16384, true> m_midiIn; + uint32_t m_midiOffsetCounter = 0; + + std::vector<dsp56k::TWord> m_delayedAudioIn; + + std::vector<dsp56k::TWord> m_dummyInput; + std::vector<dsp56k::TWord> m_dummyOutput; + + std::mutex m_esaiFrameAddedMutex; + std::condition_variable m_esaiFrameAddedCv; + + std::mutex m_requestedFramesAvailableMutex; + std::condition_variable m_requestedFramesAvailableCv; + size_t m_requestedFrames = 0; + + bool m_haltDSP = false; + std::condition_variable m_haltDSPcv; + std::mutex m_haltDSPmutex; + bool m_processAudio = false; + bool m_bootCompleted = false; }; } diff --git a/source/xtLib/xtHardware.cpp b/source/xtLib/xtHardware.cpp @@ -1,6 +1,5 @@ #include "xtHardware.h" -#include "../synthLib/midiTypes.h" #include "../synthLib/midiBufferParser.h" #include "../synthLib/deviceException.h" @@ -8,15 +7,9 @@ namespace xt { - constexpr uint32_t g_syncEsaiFrameRate = 8; - constexpr uint32_t g_syncHaltDspEsaiThreshold = 16; - - static_assert((g_syncEsaiFrameRate & (g_syncEsaiFrameRate - 1)) == 0, "esai frame sync rate must be power of two"); - static_assert(g_syncHaltDspEsaiThreshold >= g_syncEsaiFrameRate * 2, "esai DSP halt threshold must be greater than two times the sync rate"); - - Hardware::Hardware(std::string _romFilename) - : m_romFileName(std::move(_romFilename)) - , m_rom(m_romFileName, nullptr) + Hardware::Hardware(const std::string& _romFilename) + : wLib::Hardware(40000) + , m_rom(_romFilename, nullptr) , m_uc(m_rom) , m_dsps{DSP(*this, m_uc.getHdi08A().getHdi08(), 0)} , m_midi(m_uc.getQSM()) @@ -35,16 +28,6 @@ namespace xt processUcCycle(); } - void Hardware::sendMidi(const synthLib::SMidiEvent& _ev) - { - m_midiIn.push_back(_ev); - } - - void Hardware::receiveMidi(std::vector<uint8_t>& _data) - { - m_midi.readTransmitBuffer(_data); - } - void Hardware::resetMidiCounter() { // wait for DSP to enter blocking state @@ -60,45 +43,6 @@ namespace xt m_midiOffsetCounter = 0; } - void Hardware::hdiProcessUCtoDSPNMIIrq() - { - // QS6 is connected to DSP NMI pin but I've never seen this being triggered -#if SUPPORT_NMI_INTERRUPT - const uint8_t requestNMI = m_uc.requestDSPinjectNMI(); - - if(m_requestNMI && !requestNMI) - { -// LOG("uc request DSP NMI"); - m_dsps.front().hdiSendIrqToDSP(dsp56k::Vba_NMI); - - m_requestNMI = requestNMI; - } -#endif - } - - void Hardware::ucYieldLoop(const std::function<bool()>& _continue) - { - const auto dspHalted = m_haltDSP; - - resumeDSP(); - - while(_continue()) - { - if(m_processAudio) - { - std::this_thread::yield(); - } - else - { - std::unique_lock uLock(m_esaiFrameAddedMutex); - m_esaiFrameAddedCv.wait(uLock); - } - } - - if(dspHalted) - haltDSP(); - } - void Hardware::initVoiceExpansion() { if (m_dsps.size() < 3) @@ -114,32 +58,9 @@ namespace xt esaiA.setCallback([&](dsp56k::Audio*) { -/* auto& dsp = m_dsps.front().dsp(); - auto& mem = dsp.memory(); - mem.saveAssembly("xt_dspA.asm", 0, mem.sizeP(), true, false, dsp.getPeriph(0), dsp.getPeriph(1)); -*/ m_bootCompleted = true; - ++m_esaiFrameIndex; - - processMidiInput(); - - if((m_esaiFrameIndex & (g_syncEsaiFrameRate-1)) == 0) - m_esaiFrameAddedCv.notify_one(); - m_requestedFramesAvailableMutex.lock(); - - if(m_requestedFrames && esaiA.getAudioOutputs().size() >= m_requestedFrames) - { - m_requestedFramesAvailableMutex.unlock(); - m_requestedFramesAvailableCv.notify_one(); - } - else - { - m_requestedFramesAvailableMutex.unlock(); - } - - std::unique_lock uLock(m_haltDSPmutex); - m_haltDSPcv.wait(uLock, [&]{ return m_haltDSP == false; }); + onEsaiCallback(esaiA); }, 0); } @@ -154,8 +75,6 @@ namespace xt for (auto& dsp : m_dsps) dsp.transferHostFlagsUc2Dsdp(); - hdiProcessUCtoDSPNMIIrq(); - for (auto& dsp : m_dsps) dsp.hdiTransferDSPtoUC(); @@ -173,97 +92,6 @@ namespace xt } } - void Hardware::haltDSP() - { - if(m_haltDSP) - return; - - std::lock_guard uLockHalt(m_haltDSPmutex); - m_haltDSP = true; - } - - void Hardware::resumeDSP() - { - if(!m_haltDSP) - return; - - { - std::lock_guard uLockHalt(m_haltDSPmutex); - m_haltDSP = false; - } - m_haltDSPcv.notify_one(); - } - - void Hardware::syncUcToDSP() - { - if(m_remainingUcCycles > 0) - return; - - // we can only use ESAI to clock the uc once it has been enabled - if(m_esaiFrameIndex <= 0) - return; - - if(m_esaiFrameIndex == m_lastEsaiFrameIndex) - { - resumeDSP(); - std::unique_lock uLock(m_esaiFrameAddedMutex); - m_esaiFrameAddedCv.wait(uLock, [this]{return m_esaiFrameIndex > m_lastEsaiFrameIndex;}); - } - - const auto esaiFrameIndex = m_esaiFrameIndex; - - const auto ucClock = m_uc.getSim().getSystemClockHz(); - - constexpr double divInv = 1.0 / 40000.0; - const double ucCyclesPerFrame = static_cast<double>(ucClock) * divInv; - - const auto esaiDelta = esaiFrameIndex - m_lastEsaiFrameIndex; - - m_remainingUcCyclesD += ucCyclesPerFrame * static_cast<double>(esaiDelta); - m_remainingUcCycles += static_cast<int64_t>(m_remainingUcCyclesD); - m_remainingUcCyclesD -= static_cast<double>(m_remainingUcCycles); - - if(esaiDelta > g_syncHaltDspEsaiThreshold) - { - haltDSP(); - } - else - { - resumeDSP(); - } - - m_lastEsaiFrameIndex = esaiFrameIndex; - } - - void Hardware::processMidiInput() - { - ++m_midiOffsetCounter; - - while(!m_midiIn.empty()) - { - const auto& e = m_midiIn.front(); - - if(e.offset > m_midiOffsetCounter) - break; - - if(!e.sysex.empty()) - { - m_midi.writeMidi(e.sysex); - } - else - { - m_midi.writeMidi(e.a); - const auto len = synthLib::MidiBufferParser::lengthFromStatusByte(e.a); - if (len > 1) - m_midi.writeMidi(e.b); - if (len > 2) - m_midi.writeMidi(e.c); - } - - m_midiIn.pop_front(); - } - } - void Hardware::processAudio(uint32_t _frames, uint32_t _latency) { ensureBufferSize(_frames); diff --git a/source/xtLib/xtHardware.h b/source/xtLib/xtHardware.h @@ -8,23 +8,20 @@ #include "dsp56kEmu/dspthread.h" -#include "../synthLib/midiTypes.h" - -#include "dsp56kEmu/ringbuffer.h" - #include "../wLib/wMidi.h" +#include "../wLib/wHardware.h" namespace xt { class XtUc; - class Hardware + class Hardware : public wLib::Hardware { static constexpr uint32_t g_dspCount = 1; public: - explicit Hardware(std::string _romFilename); - ~Hardware(); + explicit Hardware(const std::string& _romFilename); + virtual ~Hardware(); void process(); @@ -35,9 +32,6 @@ namespace xt auto& getAudioInputs() { return m_audioInputs; } auto& getAudioOutputs() { return m_audioOutputs; } - void sendMidi(const synthLib::SMidiEvent& _ev); - void receiveMidi(std::vector<uint8_t>& _data); - dsp56k::DSPThread& getDspThread(uint32_t _index = 0) { return m_dsps[_index].thread(); } void processAudio(uint32_t _frames, uint32_t _latency = 0); @@ -54,56 +48,28 @@ namespace xt bool isBootCompleted() const { return m_bootCompleted; } void resetMidiCounter(); - void ucYieldLoop(const std::function<bool()>& _continue); void initVoiceExpansion(); + wLib::Midi& getMidi() override + { + return m_midi; + } + + mc68k::Mc68k& getUc() override + { + return m_uc; + } + private: void setupEsaiListener(); - void hdiProcessUCtoDSPNMIIrq(); void processUcCycle(); - void haltDSP(); - void resumeDSP(); - void syncUcToDSP(); - void processMidiInput(); - - const std::string m_romFileName; const Rom m_rom; - bool m_requestNMI = false; - - // timing - uint32_t m_esaiFrameIndex = 0; - uint32_t m_lastEsaiFrameIndex = 0; - int64_t m_remainingUcCycles = 0; - double m_remainingUcCyclesD = 0; - XtUc m_uc; - std::array<DSP,g_dspCount> m_dsps; - - wLib::Midi m_midi; - dsp56k::RingBuffer<synthLib::SMidiEvent, 1024, true> m_midiIn; - uint32_t m_midiOffsetCounter = 0; - - std::vector<dsp56k::TWord> m_delayedAudioIn; - - std::vector<dsp56k::TWord> m_dummyInput; - std::vector<dsp56k::TWord> m_dummyOutput; - TAudioInputs m_audioInputs; TAudioOutputs m_audioOutputs; - - std::mutex m_esaiFrameAddedMutex; - std::condition_variable m_esaiFrameAddedCv; - - std::mutex m_requestedFramesAvailableMutex; - std::condition_variable m_requestedFramesAvailableCv; - size_t m_requestedFrames = 0; - - bool m_haltDSP = false; - std::condition_variable m_haltDSPcv; - std::mutex m_haltDSPmutex; - bool m_processAudio = false; - bool m_bootCompleted = false; + std::array<DSP,g_dspCount> m_dsps; + wLib::Midi m_midi; }; }