diff --git a/include/AudioEngine.h b/include/AudioEngine.h index f056c22e108..7a8213e97ee 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -27,6 +27,12 @@ #include +#ifdef __MINGW32__ +#include +#else +#include +#endif + #if (QT_VERSION >= QT_VERSION_CHECK(5,14,0)) #include #endif @@ -475,19 +481,10 @@ class LMMS_EXPORT AudioEngine : public QObject bool m_clearSignal; - bool m_changesSignal; - unsigned int m_changes; - QMutex m_changesMutex; -#if (QT_VERSION >= QT_VERSION_CHECK(5,14,0)) - QRecursiveMutex m_doChangesMutex; -#else - QMutex m_doChangesMutex; -#endif - QMutex m_waitChangesMutex; - QWaitCondition m_changesAudioEngineCondition; - QWaitCondition m_changesRequestCondition; - - bool m_waitingForWrite; + bool m_runChanges; + int m_numChanges; + std::condition_variable m_numChangesCond, m_runChangesCond; + std::mutex m_numChangesMutex, m_runChangesMutex; friend class Engine; friend class AudioEngineWorkerThread; diff --git a/src/core/AudioEngine.cpp b/src/core/AudioEngine.cpp index 2d077babcfd..55570181508 100644 --- a/src/core/AudioEngine.cpp +++ b/src/core/AudioEngine.cpp @@ -90,12 +90,8 @@ AudioEngine::AudioEngine( bool renderOnly ) : m_profiler(), m_metronomeActive(false), m_clearSignal( false ), - m_changesSignal( false ), - m_changes( 0 ), -#if (QT_VERSION < QT_VERSION_CHECK(5,14,0)) - m_doChangesMutex( QMutex::Recursive ), -#endif - m_waitingForWrite( false ) + m_runChanges(false), + m_numChanges(0) { for( int i = 0; i < 2; ++i ) { @@ -444,8 +440,6 @@ void AudioEngine::renderStageMix() emit nextAudioBuffer(m_outputBufferRead); - runChangesInModel(); - // and trigger LFOs EnvelopeAndLfoParameters::instances()->trigger(); Controller::triggerFrameCounter(); @@ -463,6 +457,7 @@ const surroundSampleFrame *AudioEngine::renderNextBuffer() renderStageInstruments(); // STAGE 1: run and render all play handles renderStageEffects(); // STAGE 2: process effects of all instrument- and sampletracks renderStageMix(); // STAGE 3: do master mix in mixer + runChangesInModel(); // STAGE 4: call runChangesInModel to process pending non-automated changes s_renderingThread = false; m_profiler.finishPeriod(processingSampleRate(), m_framesPerPeriod); @@ -805,57 +800,44 @@ void AudioEngine::removePlayHandlesOfTypes(Track * track, PlayHandle::Types type void AudioEngine::requestChangeInModel() { - if( s_renderingThread ) - return; - - m_changesMutex.lock(); - m_changes++; - m_changesMutex.unlock(); + if (s_renderingThread || !m_isProcessing) { return; } - m_doChangesMutex.lock(); - m_waitChangesMutex.lock(); - if (m_isProcessing && !m_waitingForWrite && !m_changesSignal) { - m_changesSignal = true; - m_changesRequestCondition.wait( &m_waitChangesMutex ); + auto lock = std::lock_guard{m_numChangesMutex}; + ++m_numChanges; } - m_waitChangesMutex.unlock(); -} - - + auto lock = std::unique_lock{m_runChangesMutex}; + m_runChangesCond.wait(lock, [this] { return m_runChanges; }); +} void AudioEngine::doneChangeInModel() { - if( s_renderingThread ) - return; - - m_changesMutex.lock(); - bool moreChanges = --m_changes; - m_changesMutex.unlock(); + if (s_renderingThread || !m_isProcessing) { return; } - if( !moreChanges ) { - m_changesSignal = false; - m_changesAudioEngineCondition.wakeOne(); + auto lock = std::lock_guard{m_numChangesMutex}; + --m_numChanges; } - m_doChangesMutex.unlock(); -} - - + m_numChangesCond.notify_one(); +} void AudioEngine::runChangesInModel() { - if( m_changesSignal ) { - m_waitChangesMutex.lock(); - // allow changes in the model from other threads ... - m_changesRequestCondition.wakeOne(); - // ... and wait until they are done - m_changesAudioEngineCondition.wait( &m_waitChangesMutex ); - m_waitChangesMutex.unlock(); + auto lock = std::lock_guard{m_runChangesMutex}; + m_runChanges = true; + } + m_runChangesCond.notify_all(); + + { + auto lock = std::unique_lock{m_numChangesMutex}; + m_numChangesCond.wait(lock, [this] { return m_numChanges == 0; }); } + + auto lock = std::lock_guard{m_runChangesMutex}; + m_runChanges = false; } bool AudioEngine::isAudioDevNameValid(QString name) @@ -1304,16 +1286,7 @@ void AudioEngine::fifoWriter::run() void AudioEngine::fifoWriter::write( surroundSampleFrame * buffer ) { - m_audioEngine->m_waitChangesMutex.lock(); - m_audioEngine->m_waitingForWrite = true; - m_audioEngine->m_waitChangesMutex.unlock(); - m_audioEngine->runChangesInModel(); - - m_fifo->write( buffer ); - - m_audioEngine->m_doChangesMutex.lock(); - m_audioEngine->m_waitingForWrite = false; - m_audioEngine->m_doChangesMutex.unlock(); + m_fifo->write(buffer); } } // namespace lmms