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 a6ff82eea530df1b7523940d81e6705ee0abff0d
parent df42e631d9a90be598e3383cb23972ac50c2d2e8
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Thu,  6 Feb 2025 20:37:55 +0100

fix NR2x getting stuck after 12 hours

Diffstat:
Msource/nord/n2x/n2xLib/n2xhardware.cpp | 31+++++++++++++++++--------------
Msource/nord/n2x/n2xLib/n2xhardware.h | 5++---
2 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/source/nord/n2x/n2xLib/n2xhardware.cpp b/source/nord/n2x/n2xLib/n2xhardware.cpp @@ -57,7 +57,6 @@ namespace n2x m_dspB.terminate(); m_esaiFrameIndex = 0; - m_maxEsaiCallbacks = std::numeric_limits<uint32_t>::max(); m_esaiLatency = 0; while(!m_dspA.getDSPThread().runThread() || !m_dspB.getDSPThread().runThread()) @@ -69,7 +68,7 @@ namespace n2x m_dspB.getPeriph().getEsai().getAudioInputs().pop_front(); // DSP B waits for ESAI rate limiting and for DSP A to provide audio data - m_haltDSPcv.notify_all(); + m_haltDSPSem.notify(999999); if(m_dspA.getPeriph().getEsai().getAudioOutputs().empty()) m_dspA.getPeriph().getEsai().getAudioOutputs().push_back({}); } @@ -246,14 +245,7 @@ namespace n2x m_requestedFramesAvailableMutex.unlock(); } - if(m_esaiFrameIndex >= m_maxEsaiCallbacks + m_esaiLatency) - { - std::unique_lock uLock(m_haltDSPmutex); - m_haltDSPcv.wait(uLock, [&] - { - return (m_maxEsaiCallbacks + m_esaiLatency) > m_esaiFrameIndex; - }); - } + m_haltDSPSem.wait(1); } void Hardware::syncUCtoDSP() @@ -317,12 +309,23 @@ namespace n2x void Hardware::advanceSamples(const uint32_t _samples, const uint32_t _latency) { + // if the latency was higher first but now is lower, we might report < 0 samples. In this case we + // cannot notify but have to wait for another sample block until we can notify again + + const auto latencyDiff = static_cast<int>(_latency) - static_cast<int>(m_esaiLatency); + m_esaiLatency = _latency; + + const auto notifyCount = static_cast<int>(_samples) + latencyDiff + m_dspNotifyCorrection; + + if (notifyCount > 0) + { + m_haltDSPSem.notify(notifyCount); + m_dspNotifyCorrection = 0; + } + else { - std::lock_guard uLockHalt(m_haltDSPmutex); - m_maxEsaiCallbacks += _samples; - m_esaiLatency = _latency; + m_dspNotifyCorrection = notifyCount; } - m_haltDSPcv.notify_one(); } void Hardware::haltDSPs() diff --git a/source/nord/n2x/n2xLib/n2xhardware.h b/source/nord/n2x/n2xLib/n2xhardware.h @@ -91,10 +91,9 @@ namespace n2x uint32_t m_midiOffsetCounter = 0; // DSP slowdown - uint32_t m_maxEsaiCallbacks = 0; uint32_t m_esaiLatency = 0; - std::mutex m_haltDSPmutex; - dsp56k::ConditionVariable m_haltDSPcv; + int32_t m_dspNotifyCorrection = 0; + dsp56k::SpscSemaphoreWithCount m_haltDSPSem; bool m_bootFinished = false; };