diff --git a/include/AudioEngine.h b/include/AudioEngine.h index c01b2ea1a5e..f6d8692b52d 100644 --- a/include/AudioEngine.h +++ b/include/AudioEngine.h @@ -50,14 +50,15 @@ class AudioPort; class AudioEngineWorkerThread; -const fpp_t MINIMUM_BUFFER_SIZE = 32; -const fpp_t DEFAULT_BUFFER_SIZE = 256; +constexpr fpp_t MINIMUM_BUFFER_SIZE = 32; +constexpr fpp_t DEFAULT_BUFFER_SIZE = 256; +constexpr fpp_t MAXIMUM_BUFFER_SIZE = 4096; -const int BYTES_PER_SAMPLE = sizeof( sample_t ); -const int BYTES_PER_INT_SAMPLE = sizeof( int_sample_t ); -const int BYTES_PER_FRAME = sizeof( SampleFrame ); +constexpr int BYTES_PER_SAMPLE = sizeof(sample_t); +constexpr int BYTES_PER_INT_SAMPLE = sizeof(int_sample_t); +constexpr int BYTES_PER_FRAME = sizeof(SampleFrame); -const float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f; +constexpr float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f; class LMMS_EXPORT AudioEngine : public QObject { diff --git a/include/DummyEffect.h b/include/DummyEffect.h index e2e649ab54d..3a1061eaddf 100644 --- a/include/DummyEffect.h +++ b/include/DummyEffect.h @@ -98,6 +98,7 @@ class DummyEffect : public Effect m_originalPluginData( originalPluginData ) { setName(); + setDontRun(true); } ~DummyEffect() override = default; @@ -107,9 +108,9 @@ class DummyEffect : public Effect return &m_controls; } - bool processAudioBuffer( SampleFrame*, const fpp_t ) override + ProcessStatus processImpl(SampleFrame*, const fpp_t) override { - return false; + return ProcessStatus::Sleep; } const QDomElement& originalPluginData() const diff --git a/include/Effect.h b/include/Effect.h index 34f8be00a07..7eb911701a0 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -63,9 +63,8 @@ class LMMS_EXPORT Effect : public Plugin return "effect"; } - - virtual bool processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) = 0; + //! Returns true if audio was processed and should continue being processed + bool processAudioBuffer(SampleFrame* buf, const fpp_t frames); inline ch_cnt_t processorCount() const { @@ -174,14 +173,29 @@ class LMMS_EXPORT Effect : public Plugin protected: + enum class ProcessStatus + { + //! Unconditionally continue processing + Continue, + + //! Calculate the RMS out sum and call `checkGate` to determine whether to stop processing + ContinueIfNotQuiet, + + //! Do not continue processing + Sleep + }; + /** - Effects should call this at the end of audio processing + * The main audio processing method that runs when plugin is not asleep + */ + virtual ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) = 0; + + /** + * Optional method that runs when plugin is sleeping (not enabled, + * not running, not in the Okay state, or in the Don't Run state) + */ + virtual void processBypassedImpl() {} - If the setting "Keep effects running even without input" is disabled, - after "decay" ms of a signal below "gate", the effect is turned off - and won't be processed again until it receives new audio input - */ - void checkGate( double _out_sum ); gui::PluginView* instantiateView( QWidget * ) override; @@ -212,6 +226,14 @@ class LMMS_EXPORT Effect : public Plugin private: + /** + If the setting "Keep effects running even without input" is disabled, + after "decay" ms of a signal below "gate", the effect is turned off + and won't be processed again until it receives new audio input + */ + void checkGate(double outSum); + + EffectChain * m_parent; void resample( int _i, const SampleFrame* _src_buf, sample_rate_t _src_sr, diff --git a/plugins/Amplifier/Amplifier.cpp b/plugins/Amplifier/Amplifier.cpp index 2f4e57f77d0..04fd98682bd 100644 --- a/plugins/Amplifier/Amplifier.cpp +++ b/plugins/Amplifier/Amplifier.cpp @@ -57,11 +57,8 @@ AmplifierEffect::AmplifierEffect(Model* parent, const Descriptor::SubPluginFeatu } -bool AmplifierEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) +Effect::ProcessStatus AmplifierEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if (!isEnabled() || !isRunning()) { return false ; } - - double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); @@ -86,13 +83,9 @@ bool AmplifierEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) // Dry/wet mix currentFrame = currentFrame * d + s * w; - - outSum += currentFrame.sumOfSquaredAmplitudes(); } - checkGate(outSum / frames); - - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/Amplifier/Amplifier.h b/plugins/Amplifier/Amplifier.h index 8be93800180..8c0667316a4 100644 --- a/plugins/Amplifier/Amplifier.h +++ b/plugins/Amplifier/Amplifier.h @@ -37,7 +37,8 @@ class AmplifierEffect : public Effect public: AmplifierEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key); ~AmplifierEffect() override = default; - bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/BassBooster/BassBooster.cpp b/plugins/BassBooster/BassBooster.cpp index f12fd6ace8f..ae914c85d52 100644 --- a/plugins/BassBooster/BassBooster.cpp +++ b/plugins/BassBooster/BassBooster.cpp @@ -69,12 +69,8 @@ BassBoosterEffect::BassBoosterEffect( Model* parent, const Descriptor::SubPlugin -bool BassBoosterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus BassBoosterEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } // check out changed controls if( m_frequencyChangeNeeded || m_bbControls.m_freqModel.isValueChanged() ) { @@ -87,7 +83,6 @@ bool BassBoosterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames const float const_gain = m_bbControls.m_gainModel.value(); const ValueBuffer *gainBuffer = m_bbControls.m_gainModel.valueBuffer(); - double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); @@ -102,13 +97,9 @@ bool BassBoosterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames // Dry/wet mix currentFrame = currentFrame * d + s * w; - - outSum += currentFrame.sumOfSquaredAmplitudes(); } - checkGate( outSum / frames ); - - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/BassBooster/BassBooster.h b/plugins/BassBooster/BassBooster.h index 64c4e354d6b..f46c910a304 100644 --- a/plugins/BassBooster/BassBooster.h +++ b/plugins/BassBooster/BassBooster.h @@ -38,7 +38,8 @@ class BassBoosterEffect : public Effect public: BassBoosterEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); ~BassBoosterEffect() override = default; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/Bitcrush/Bitcrush.cpp b/plugins/Bitcrush/Bitcrush.cpp index ea1c43acba1..7b9e8f8ef07 100644 --- a/plugins/Bitcrush/Bitcrush.cpp +++ b/plugins/Bitcrush/Bitcrush.cpp @@ -100,13 +100,8 @@ inline float BitcrushEffect::noise( float amt ) return fastRandf( amt * 2.0f ) - amt; } -bool BitcrushEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus BitcrushEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - // update values if( m_needsUpdate || m_controls.m_rateEnabled.isValueChanged() ) { @@ -222,7 +217,6 @@ bool BitcrushEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) // now downsample and write it back to main buffer - double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); for (auto f = std::size_t{0}; f < frames; ++f) @@ -236,12 +230,9 @@ bool BitcrushEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) } buf[f][0] = d * buf[f][0] + w * qBound( -m_outClip, lsum, m_outClip ) * m_outGain; buf[f][1] = d * buf[f][1] + w * qBound( -m_outClip, rsum, m_outClip ) * m_outGain; - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; } - checkGate( outSum / frames ); - - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/Bitcrush/Bitcrush.h b/plugins/Bitcrush/Bitcrush.h index 009c7c02dd0..4957ea9ec83 100644 --- a/plugins/Bitcrush/Bitcrush.h +++ b/plugins/Bitcrush/Bitcrush.h @@ -41,13 +41,14 @@ class BitcrushEffect : public Effect public: BitcrushEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); ~BitcrushEffect() override; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { return &m_controls; } - + private: void sampleRateChanged(); float depthCrush( float in ); diff --git a/plugins/Compressor/Compressor.cpp b/plugins/Compressor/Compressor.cpp index c04893361b1..1e4c0d0f608 100755 --- a/plugins/Compressor/Compressor.cpp +++ b/plugins/Compressor/Compressor.cpp @@ -233,31 +233,10 @@ void CompressorEffect::calcMix() -bool CompressorEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) +Effect::ProcessStatus CompressorEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if (!isEnabled() || !isRunning()) - { - // Clear lookahead buffers and other values when needed - if (!m_cleanedBuffers) - { - m_yL[0] = m_yL[1] = COMP_NOISE_FLOOR; - m_gainResult[0] = m_gainResult[1] = 1; - m_displayPeak[0] = m_displayPeak[1] = COMP_NOISE_FLOOR; - m_displayGain[0] = m_displayGain[1] = COMP_NOISE_FLOOR; - std::fill(std::begin(m_scLookBuf[0]), std::end(m_scLookBuf[0]), COMP_NOISE_FLOOR); - std::fill(std::begin(m_scLookBuf[1]), std::end(m_scLookBuf[1]), COMP_NOISE_FLOOR); - std::fill(std::begin(m_inLookBuf[0]), std::end(m_inLookBuf[0]), 0); - std::fill(std::begin(m_inLookBuf[1]), std::end(m_inLookBuf[1]), 0); - m_cleanedBuffers = true; - } - return false; - } - else - { - m_cleanedBuffers = false; - } + m_cleanedBuffers = false; - float outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); @@ -516,8 +495,6 @@ bool CompressorEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) buf[f][0] = (1 - m_mixVal) * temp1 + m_mixVal * buf[f][0]; buf[f][1] = (1 - m_mixVal) * temp2 + m_mixVal * buf[f][1]; - outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; - if (--m_lookWrite < 0) { m_lookWrite = m_lookBufLength - 1; } lInPeak = drySignal[0] > lInPeak ? drySignal[0] : lInPeak; @@ -526,15 +503,30 @@ bool CompressorEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) rOutPeak = s[1] > rOutPeak ? s[1] : rOutPeak; } - checkGate(outSum / frames); m_compressorControls.m_outPeakL = lOutPeak; m_compressorControls.m_outPeakR = rOutPeak; m_compressorControls.m_inPeakL = lInPeak; m_compressorControls.m_inPeakR = rInPeak; - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } +void CompressorEffect::processBypassedImpl() +{ + // Clear lookahead buffers and other values when needed + if (!m_cleanedBuffers) + { + m_yL[0] = m_yL[1] = COMP_NOISE_FLOOR; + m_gainResult[0] = m_gainResult[1] = 1; + m_displayPeak[0] = m_displayPeak[1] = COMP_NOISE_FLOOR; + m_displayGain[0] = m_displayGain[1] = COMP_NOISE_FLOOR; + std::fill(std::begin(m_scLookBuf[0]), std::end(m_scLookBuf[0]), COMP_NOISE_FLOOR); + std::fill(std::begin(m_scLookBuf[1]), std::end(m_scLookBuf[1]), COMP_NOISE_FLOOR); + std::fill(std::begin(m_inLookBuf[0]), std::end(m_inLookBuf[0]), 0); + std::fill(std::begin(m_inLookBuf[1]), std::end(m_inLookBuf[1]), 0); + m_cleanedBuffers = true; + } +} // Regular modulo doesn't handle negative numbers correctly. This does. inline int CompressorEffect::realmod(int k, int n) diff --git a/plugins/Compressor/Compressor.h b/plugins/Compressor/Compressor.h index af322de9735..d4c9625c9d5 100755 --- a/plugins/Compressor/Compressor.h +++ b/plugins/Compressor/Compressor.h @@ -43,7 +43,9 @@ class CompressorEffect : public Effect public: CompressorEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key); ~CompressorEffect() override = default; - bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + void processBypassedImpl() override; EffectControls* controls() override { diff --git a/plugins/CrossoverEQ/CrossoverEQ.cpp b/plugins/CrossoverEQ/CrossoverEQ.cpp index 2142d040c76..e221dc5252f 100644 --- a/plugins/CrossoverEQ/CrossoverEQ.cpp +++ b/plugins/CrossoverEQ/CrossoverEQ.cpp @@ -89,13 +89,8 @@ void CrossoverEQEffect::sampleRateChanged() } -bool CrossoverEQEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus CrossoverEQEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - // filters update if( m_needsUpdate || m_controls.m_xover12.isValueChanged() ) { @@ -192,17 +187,14 @@ bool CrossoverEQEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames const float d = dryLevel(); const float w = wetLevel(); - double outSum = 0.0; + for (auto f = std::size_t{0}; f < frames; ++f) { buf[f][0] = d * buf[f][0] + w * m_work[f][0]; buf[f][1] = d * buf[f][1] + w * m_work[f][1]; - outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } - - checkGate( outSum / frames ); - - return isRunning(); + + return ProcessStatus::ContinueIfNotQuiet; } void CrossoverEQEffect::clearFilterHistories() diff --git a/plugins/CrossoverEQ/CrossoverEQ.h b/plugins/CrossoverEQ/CrossoverEQ.h index 078e51c2189..276e2c13198 100644 --- a/plugins/CrossoverEQ/CrossoverEQ.h +++ b/plugins/CrossoverEQ/CrossoverEQ.h @@ -40,7 +40,8 @@ class CrossoverEQEffect : public Effect public: CrossoverEQEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); ~CrossoverEQEffect() override; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/Delay/DelayEffect.cpp b/plugins/Delay/DelayEffect.cpp index 4e90c0fa899..baf01591640 100644 --- a/plugins/Delay/DelayEffect.cpp +++ b/plugins/Delay/DelayEffect.cpp @@ -81,13 +81,8 @@ DelayEffect::~DelayEffect() -bool DelayEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus DelayEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - double outSum = 0.0; const float sr = Engine::audioEngine()->outputSampleRate(); const float d = dryLevel(); const float w = wetLevel(); @@ -135,19 +130,17 @@ bool DelayEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) // Dry/wet mix currentFrame = dryS * d + currentFrame * w; - - outSum += currentFrame.sumOfSquaredAmplitudes(); lengthPtr += lengthInc; amplitudePtr += amplitudeInc; lfoTimePtr += lfoTimeInc; feedbackPtr += feedbackInc; } - checkGate( outSum / frames ); + m_delayControls.m_outPeakL = peak.left(); m_delayControls.m_outPeakR = peak.right(); - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } void DelayEffect::changeSampleRate() diff --git a/plugins/Delay/DelayEffect.h b/plugins/Delay/DelayEffect.h index b7e2cfef032..fc6a21fd610 100644 --- a/plugins/Delay/DelayEffect.h +++ b/plugins/Delay/DelayEffect.h @@ -39,7 +39,9 @@ class DelayEffect : public Effect public: DelayEffect(Model* parent , const Descriptor::SubPluginFeatures::Key* key ); ~DelayEffect() override; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + EffectControls* controls() override { return &m_delayControls; diff --git a/plugins/Dispersion/Dispersion.cpp b/plugins/Dispersion/Dispersion.cpp index a2fada615bb..4d8dd40b016 100644 --- a/plugins/Dispersion/Dispersion.cpp +++ b/plugins/Dispersion/Dispersion.cpp @@ -58,14 +58,8 @@ DispersionEffect::DispersionEffect(Model* parent, const Descriptor::SubPluginFea } -bool DispersionEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) +Effect::ProcessStatus DispersionEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if (!isEnabled() || !isRunning()) - { - return false; - } - - double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); @@ -122,11 +116,9 @@ bool DispersionEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; - outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } - checkGate(outSum / frames); - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/Dispersion/Dispersion.h b/plugins/Dispersion/Dispersion.h index e3d5d4b5ca0..27365950d87 100644 --- a/plugins/Dispersion/Dispersion.h +++ b/plugins/Dispersion/Dispersion.h @@ -41,7 +41,8 @@ class DispersionEffect : public Effect public: DispersionEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key); ~DispersionEffect() override = default; - bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/DualFilter/DualFilter.cpp b/plugins/DualFilter/DualFilter.cpp index b337e100301..397180b8e5a 100644 --- a/plugins/DualFilter/DualFilter.cpp +++ b/plugins/DualFilter/DualFilter.cpp @@ -77,23 +77,17 @@ DualFilterEffect::~DualFilterEffect() -bool DualFilterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus DualFilterEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - - double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); - if( m_dfControls.m_filter1Model.isValueChanged() || m_filter1changed ) + if (m_dfControls.m_filter1Model.isValueChanged() || m_filter1changed) { m_filter1->setFilterType( static_cast::FilterType>(m_dfControls.m_filter1Model.value()) ); m_filter1changed = true; } - if( m_dfControls.m_filter2Model.isValueChanged() || m_filter2changed ) + if (m_dfControls.m_filter2Model.isValueChanged() || m_filter2changed) { m_filter2->setFilterType( static_cast::FilterType>(m_dfControls.m_filter2Model.value()) ); m_filter2changed = true; @@ -201,7 +195,6 @@ bool DualFilterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames // do another mix with dry signal buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; - outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; //increment pointers cut1Ptr += cut1Inc; @@ -213,9 +206,7 @@ bool DualFilterEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames mixPtr += mixInc; } - checkGate( outSum / frames ); - - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } void DualFilterEffect::onEnabledChanged() diff --git a/plugins/DualFilter/DualFilter.h b/plugins/DualFilter/DualFilter.h index 6c53f61ef27..dc573a8d64c 100644 --- a/plugins/DualFilter/DualFilter.h +++ b/plugins/DualFilter/DualFilter.h @@ -40,7 +40,8 @@ class DualFilterEffect : public Effect public: DualFilterEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); ~DualFilterEffect() override; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/DynamicsProcessor/DynamicsProcessor.cpp b/plugins/DynamicsProcessor/DynamicsProcessor.cpp index 5b251a6f0ad..752e63e2357 100644 --- a/plugins/DynamicsProcessor/DynamicsProcessor.cpp +++ b/plugins/DynamicsProcessor/DynamicsProcessor.cpp @@ -91,15 +91,8 @@ inline void DynProcEffect::calcRelease() } -bool DynProcEffect::processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) +Effect::ProcessStatus DynProcEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { -//apparently we can't keep running after the decay value runs out so we'll just set the peaks to zero - m_currentPeak[0] = m_currentPeak[1] = DYN_NOISE_FLOOR; - return( false ); - } //qDebug( "%f %f", m_currentPeak[0], m_currentPeak[1] ); // variables for effect @@ -107,7 +100,6 @@ bool DynProcEffect::processAudioBuffer( SampleFrame* _buf, auto sm_peak = std::array{0.0f, 0.0f}; - double out_sum = 0.0; const float d = dryLevel(); const float w = wetLevel(); @@ -140,9 +132,9 @@ bool DynProcEffect::processAudioBuffer( SampleFrame* _buf, } } - for( fpp_t f = 0; f < _frames; ++f ) + for (fpp_t f = 0; f < frames; ++f) { - auto s = std::array{_buf[f][0], _buf[f][1]}; + auto s = std::array{buf[f][0], buf[f][1]}; // apply input gain s[0] *= inputGain; @@ -210,17 +202,18 @@ bool DynProcEffect::processAudioBuffer( SampleFrame* _buf, s[1] *= outputGain; // mix wet/dry signals - _buf[f][0] = d * _buf[f][0] + w * s[0]; - _buf[f][1] = d * _buf[f][1] + w * s[1]; - out_sum += _buf[f][0] * _buf[f][0] + _buf[f][1] * _buf[f][1]; + buf[f][0] = d * buf[f][0] + w * s[0]; + buf[f][1] = d * buf[f][1] + w * s[1]; } - checkGate( out_sum / _frames ); - - return( isRunning() ); + return ProcessStatus::ContinueIfNotQuiet; } - +void DynProcEffect::processBypassedImpl() +{ + // Apparently we can't keep running after the decay value runs out so we'll just set the peaks to zero + m_currentPeak[0] = m_currentPeak[1] = DYN_NOISE_FLOOR; +} diff --git a/plugins/DynamicsProcessor/DynamicsProcessor.h b/plugins/DynamicsProcessor/DynamicsProcessor.h index 970690d8d3d..fbf5d930ac9 100644 --- a/plugins/DynamicsProcessor/DynamicsProcessor.h +++ b/plugins/DynamicsProcessor/DynamicsProcessor.h @@ -42,8 +42,9 @@ class DynProcEffect : public Effect DynProcEffect( Model * _parent, const Descriptor::SubPluginFeatures::Key * _key ); ~DynProcEffect() override; - bool processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + void processBypassedImpl() override; EffectControls * controls() override { diff --git a/plugins/Eq/EqEffect.cpp b/plugins/Eq/EqEffect.cpp index 662b85a8ea5..6859529f40e 100644 --- a/plugins/Eq/EqEffect.cpp +++ b/plugins/Eq/EqEffect.cpp @@ -64,7 +64,7 @@ EqEffect::EqEffect( Model *parent, const Plugin::Descriptor::SubPluginFeatures:: -bool EqEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus EqEffect::processImpl(SampleFrame* buf, const fpp_t frames) { const int sampleRate = Engine::audioEngine()->outputSampleRate(); @@ -131,13 +131,6 @@ bool EqEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) m_lp481.setParameters( sampleRate, lpFreq, lpRes, 1 ); - - - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - if( m_eqControls.m_outGainModel.isValueChanged() ) { m_outGain = dbfsToAmp(m_eqControls.m_outGainModel.value()); @@ -151,9 +144,9 @@ bool EqEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) m_eqControls.m_inProgress = true; double outSum = 0.0; - for( fpp_t f = 0; f < frames; ++f ) + for (fpp_t f = 0; f < frames; ++f) { - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; + outSum += buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1]; } const float outGain = m_outGain; @@ -268,8 +261,6 @@ bool EqEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) m_eqControls.m_outPeakL = m_eqControls.m_outPeakL < outPeak[0] ? outPeak[0] : m_eqControls.m_outPeakL; m_eqControls.m_outPeakR = m_eqControls.m_outPeakR < outPeak[1] ? outPeak[1] : m_eqControls.m_outPeakR; - checkGate( outSum / frames ); - if(m_eqControls.m_analyseOutModel.value( true ) && outSum > 0 && m_eqControls.isViewVisible() ) { m_eqControls.m_outFftBands.analyze( buf, frames ); @@ -281,7 +272,8 @@ bool EqEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) } m_eqControls.m_inProgress = false; - return isRunning(); + + return Effect::ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/Eq/EqEffect.h b/plugins/Eq/EqEffect.h index ca0ebb1b9ad..35e1b12b532 100644 --- a/plugins/Eq/EqEffect.h +++ b/plugins/Eq/EqEffect.h @@ -40,7 +40,9 @@ class EqEffect : public Effect public: EqEffect( Model * parent , const Descriptor::SubPluginFeatures::Key * key ); ~EqEffect() override = default; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + EffectControls * controls() override { return &m_eqControls; diff --git a/plugins/Flanger/FlangerEffect.cpp b/plugins/Flanger/FlangerEffect.cpp index 184df161e3b..c13de47cd09 100644 --- a/plugins/Flanger/FlangerEffect.cpp +++ b/plugins/Flanger/FlangerEffect.cpp @@ -85,13 +85,8 @@ FlangerEffect::~FlangerEffect() -bool FlangerEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus FlangerEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); const float length = m_flangerControls.m_delayTimeModel.value() * Engine::audioEngine()->outputSampleRate(); @@ -127,10 +122,9 @@ bool FlangerEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] ); buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] ); - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; } - checkGate( outSum / frames ); - return isRunning(); + + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/Flanger/FlangerEffect.h b/plugins/Flanger/FlangerEffect.h index 4b0246e7e17..ec43d31993e 100644 --- a/plugins/Flanger/FlangerEffect.h +++ b/plugins/Flanger/FlangerEffect.h @@ -41,7 +41,9 @@ class FlangerEffect : public Effect public: FlangerEffect( Model* parent , const Descriptor::SubPluginFeatures::Key* key ); ~FlangerEffect() override; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + EffectControls* controls() override { return &m_flangerControls; diff --git a/plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp b/plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp index 2b182991f3b..27c935ab9ab 100755 --- a/plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp +++ b/plugins/GranularPitchShifter/GranularPitchShifterEffect.cpp @@ -60,10 +60,8 @@ GranularPitchShifterEffect::GranularPitchShifterEffect(Model* parent, const Desc } -bool GranularPitchShifterEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) +Effect::ProcessStatus GranularPitchShifterEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if (!isEnabled() || !isRunning()) { return false; } - const float d = dryLevel(); const float w = wetLevel(); @@ -245,7 +243,7 @@ bool GranularPitchShifterEffect::processAudioBuffer(SampleFrame* buf, const fpp_ changeSampleRate(); } - return isRunning(); + return Effect::ProcessStatus::ContinueIfNotQuiet; } void GranularPitchShifterEffect::changeSampleRate() diff --git a/plugins/GranularPitchShifter/GranularPitchShifterEffect.h b/plugins/GranularPitchShifter/GranularPitchShifterEffect.h index 0f94168b7b6..09b8025cdc5 100755 --- a/plugins/GranularPitchShifter/GranularPitchShifterEffect.h +++ b/plugins/GranularPitchShifter/GranularPitchShifterEffect.h @@ -48,7 +48,8 @@ class GranularPitchShifterEffect : public Effect public: GranularPitchShifterEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key); ~GranularPitchShifterEffect() override = default; - bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/LOMM/LOMM.cpp b/plugins/LOMM/LOMM.cpp index 7c4574cd1b8..14f254eab65 100644 --- a/plugins/LOMM/LOMM.cpp +++ b/plugins/LOMM/LOMM.cpp @@ -101,13 +101,8 @@ void LOMMEffect::changeSampleRate() } -bool LOMMEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) +Effect::ProcessStatus LOMMEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if (!isEnabled() || !isRunning()) - { - return false; - } - if (m_needsUpdate || m_lommControls.m_split1Model.isValueChanged()) { m_lp1.setLowpass(m_lommControls.m_split1Model.value()); @@ -121,7 +116,6 @@ bool LOMMEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) } m_needsUpdate = false; - float outSum = 0.f; const float d = dryLevel(); const float w = wetLevel(); @@ -423,11 +417,9 @@ bool LOMMEffect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) buf[f][0] = d * buf[f][0] + w * s[0]; buf[f][1] = d * buf[f][1] + w * s[1]; - outSum += buf[f][0] + buf[f][1]; } - checkGate(outSum / frames); - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } extern "C" diff --git a/plugins/LOMM/LOMM.h b/plugins/LOMM/LOMM.h index 783233c5f47..0dd209e0711 100644 --- a/plugins/LOMM/LOMM.h +++ b/plugins/LOMM/LOMM.h @@ -45,7 +45,8 @@ class LOMMEffect : public Effect public: LOMMEffect(Model* parent, const Descriptor::SubPluginFeatures::Key* key); ~LOMMEffect() override = default; - bool processAudioBuffer(SampleFrame* buf, const fpp_t frames) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/LadspaEffect/LadspaEffect.cpp b/plugins/LadspaEffect/LadspaEffect.cpp index 75c79ad214b..5baa3834c2e 100644 --- a/plugins/LadspaEffect/LadspaEffect.cpp +++ b/plugins/LadspaEffect/LadspaEffect.cpp @@ -129,26 +129,25 @@ void LadspaEffect::changeSampleRate() -bool LadspaEffect::processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) +Effect::ProcessStatus LadspaEffect::processImpl(SampleFrame* buf, const fpp_t frames) { m_pluginMutex.lock(); - if( !isOkay() || dontRun() || !isRunning() || !isEnabled() ) + if (!isOkay() || dontRun() || !isEnabled() || !isRunning()) { m_pluginMutex.unlock(); - return( false ); + return ProcessStatus::Sleep; } - auto frames = _frames; - SampleFrame* o_buf = nullptr; - QVarLengthArray sBuf(_frames); + auto outFrames = frames; + SampleFrame* outBuf = nullptr; + QVarLengthArray sBuf(frames); if( m_maxSampleRate < Engine::audioEngine()->outputSampleRate() ) { - o_buf = _buf; - _buf = sBuf.data(); - sampleDown( o_buf, _buf, m_maxSampleRate ); - frames = _frames * m_maxSampleRate / + outBuf = buf; + buf = sBuf.data(); + sampleDown(outBuf, buf, m_maxSampleRate); + outFrames = frames * m_maxSampleRate / Engine::audioEngine()->outputSampleRate(); } @@ -163,11 +162,9 @@ bool LadspaEffect::processAudioBuffer( SampleFrame* _buf, switch( pp->rate ) { case BufferRate::ChannelIn: - for( fpp_t frame = 0; - frame < frames; ++frame ) + for (fpp_t frame = 0; frame < outFrames; ++frame) { - pp->buffer[frame] = - _buf[frame][channel]; + pp->buffer[frame] = buf[frame][channel]; } ++channel; break; @@ -176,7 +173,7 @@ bool LadspaEffect::processAudioBuffer( SampleFrame* _buf, ValueBuffer * vb = pp->control->valueBuffer(); if( vb ) { - memcpy( pp->buffer, vb->values(), frames * sizeof(float) ); + memcpy(pp->buffer, vb->values(), outFrames * sizeof(float)); } else { @@ -185,11 +182,9 @@ bool LadspaEffect::processAudioBuffer( SampleFrame* _buf, // This only supports control rate ports, so the audio rates are // treated as though they were control rate by setting the // port buffer to all the same value. - for( fpp_t frame = 0; - frame < frames; ++frame ) + for (fpp_t frame = 0; frame < outFrames; ++frame) { - pp->buffer[frame] = - pp->value; + pp->buffer[frame] = pp->value; } } break; @@ -218,11 +213,10 @@ bool LadspaEffect::processAudioBuffer( SampleFrame* _buf, // Process the buffers. for( ch_cnt_t proc = 0; proc < processorCount(); ++proc ) { - (m_descriptor->run)( m_handles[proc], frames ); + (m_descriptor->run)(m_handles[proc], outFrames); } // Copy the LADSPA output buffers to the LMMS buffer. - double out_sum = 0.0; channel = 0; const float d = dryLevel(); const float w = wetLevel(); @@ -238,11 +232,9 @@ bool LadspaEffect::processAudioBuffer( SampleFrame* _buf, case BufferRate::ControlRateInput: break; case BufferRate::ChannelOut: - for( fpp_t frame = 0; - frame < frames; ++frame ) + for (fpp_t frame = 0; frame < outFrames; ++frame) { - _buf[frame][channel] = d * _buf[frame][channel] + w * pp->buffer[frame]; - out_sum += _buf[frame][channel] * _buf[frame][channel]; + buf[frame][channel] = d * buf[frame][channel] + w * pp->buffer[frame]; } ++channel; break; @@ -255,17 +247,14 @@ bool LadspaEffect::processAudioBuffer( SampleFrame* _buf, } } - if( o_buf != nullptr ) + if (outBuf != nullptr) { - sampleBack( _buf, o_buf, m_maxSampleRate ); + sampleBack(buf, outBuf, m_maxSampleRate); } - checkGate( out_sum / frames ); - - - bool is_running = isRunning(); m_pluginMutex.unlock(); - return( is_running ); + + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/LadspaEffect/LadspaEffect.h b/plugins/LadspaEffect/LadspaEffect.h index d5b93d4e24b..0cfa186821f 100644 --- a/plugins/LadspaEffect/LadspaEffect.h +++ b/plugins/LadspaEffect/LadspaEffect.h @@ -47,9 +47,8 @@ class LadspaEffect : public Effect const Descriptor::SubPluginFeatures::Key * _key ); ~LadspaEffect() override; - bool processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) override; - + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + void setControl( int _control, LADSPA_Data _data ); EffectControls * controls() override diff --git a/plugins/Lv2Effect/Lv2Effect.cpp b/plugins/Lv2Effect/Lv2Effect.cpp index d6b89a2291b..afa69fe1373 100644 --- a/plugins/Lv2Effect/Lv2Effect.cpp +++ b/plugins/Lv2Effect/Lv2Effect.cpp @@ -68,9 +68,8 @@ Lv2Effect::Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key *ke -bool Lv2Effect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) +Effect::ProcessStatus Lv2Effect::processImpl(SampleFrame* buf, const fpp_t frames) { - if (!isEnabled() || !isRunning()) { return false; } Q_ASSERT(frames <= static_cast(m_tmpOutputSmps.size())); m_controls.copyBuffersFromLmms(buf, frames); @@ -83,7 +82,6 @@ bool Lv2Effect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) m_controls.copyModelsToLmms(); m_controls.copyBuffersToLmms(m_tmpOutputSmps.data(), frames); - double outSum = .0; bool corrupt = wetLevel() < 0; // #3261 - if w < 0, bash w := 0, d := 1 const float d = corrupt ? 1 : dryLevel(); const float w = corrupt ? 0 : wetLevel(); @@ -91,13 +89,9 @@ bool Lv2Effect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) { buf[f][0] = d * buf[f][0] + w * m_tmpOutputSmps[f][0]; buf[f][1] = d * buf[f][1] + w * m_tmpOutputSmps[f][1]; - auto l = static_cast(buf[f][0]); - auto r = static_cast(buf[f][1]); - outSum += l*l + r*r; } - checkGate(outSum / frames); - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/Lv2Effect/Lv2Effect.h b/plugins/Lv2Effect/Lv2Effect.h index bc81eb59098..dbede0d4353 100644 --- a/plugins/Lv2Effect/Lv2Effect.h +++ b/plugins/Lv2Effect/Lv2Effect.h @@ -42,7 +42,8 @@ class Lv2Effect : public Effect */ Lv2Effect(Model* parent, const Descriptor::SubPluginFeatures::Key* _key); - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + EffectControls* controls() override { return &m_controls; } Lv2FxControls* lv2Controls() { return &m_controls; } diff --git a/plugins/MultitapEcho/MultitapEcho.cpp b/plugins/MultitapEcho/MultitapEcho.cpp index ecc1d8f304e..96a828dcc23 100644 --- a/plugins/MultitapEcho/MultitapEcho.cpp +++ b/plugins/MultitapEcho/MultitapEcho.cpp @@ -94,14 +94,8 @@ void MultitapEchoEffect::runFilter( SampleFrame* dst, SampleFrame* src, StereoOn } -bool MultitapEchoEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus MultitapEchoEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - - double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); @@ -156,12 +150,9 @@ bool MultitapEchoEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frame { buf[f][0] = d * buf[f][0] + w * m_work[f][0]; buf[f][1] = d * buf[f][1] + w * m_work[f][1]; - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; } - - checkGate( outSum / frames ); - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/MultitapEcho/MultitapEcho.h b/plugins/MultitapEcho/MultitapEcho.h index d6e981fbd58..8c8a007aaaa 100644 --- a/plugins/MultitapEcho/MultitapEcho.h +++ b/plugins/MultitapEcho/MultitapEcho.h @@ -40,7 +40,8 @@ class MultitapEchoEffect : public Effect public: MultitapEchoEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); ~MultitapEchoEffect() override; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/PeakControllerEffect/PeakControllerEffect.cpp b/plugins/PeakControllerEffect/PeakControllerEffect.cpp index 886036095f8..394a80efd4b 100644 --- a/plugins/PeakControllerEffect/PeakControllerEffect.cpp +++ b/plugins/PeakControllerEffect/PeakControllerEffect.cpp @@ -93,37 +93,29 @@ PeakControllerEffect::~PeakControllerEffect() } -bool PeakControllerEffect::processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) +Effect::ProcessStatus PeakControllerEffect::processImpl(SampleFrame* buf, const fpp_t frames) { PeakControllerEffectControls & c = m_peakControls; - // This appears to be used for determining whether or not to continue processing - // audio with this effect - if( !isEnabled() || !isRunning() ) - { - return false; - } - // RMS: double sum = 0; if( c.m_absModel.value() ) { - for (auto i = std::size_t{0}; i < _frames; ++i) + for (auto i = std::size_t{0}; i < frames; ++i) { // absolute value is achieved because the squares are > 0 - sum += _buf[i][0]*_buf[i][0] + _buf[i][1]*_buf[i][1]; + sum += buf[i][0] * buf[i][0] + buf[i][1] * buf[i][1]; } } else { - for (auto i = std::size_t{0}; i < _frames; ++i) + for (auto i = std::size_t{0}; i < frames; ++i) { // the value is absolute because of squaring, // so we need to correct it - sum += _buf[i][0] * _buf[i][0] * sign( _buf[i][0] ) - + _buf[i][1] * _buf[i][1] * sign( _buf[i][1] ); + sum += buf[i][0] * buf[i][0] * sign(buf[i][0]) + + buf[i][1] * buf[i][1] * sign(buf[i][1]); } } @@ -131,19 +123,19 @@ bool PeakControllerEffect::processAudioBuffer( SampleFrame* _buf, // this will mute the output after the values were measured if( c.m_muteModel.value() ) { - for (auto i = std::size_t{0}; i < _frames; ++i) + for (auto i = std::size_t{0}; i < frames; ++i) { - _buf[i][0] = _buf[i][1] = 0.0f; + buf[i][0] = buf[i][1] = 0.0f; } } - float curRMS = sqrt_neg( sum / _frames ); + float curRMS = sqrt_neg(sum / frames); const float tres = c.m_tresholdModel.value(); const float amount = c.m_amountModel.value() * c.m_amountMultModel.value(); curRMS = qAbs( curRMS ) < tres ? 0.0f : curRMS; m_lastSample = qBound( 0.0f, c.m_baseModel.value() + amount * curRMS, 1.0f ); - return isRunning(); + return ProcessStatus::Continue; } diff --git a/plugins/PeakControllerEffect/PeakControllerEffect.h b/plugins/PeakControllerEffect/PeakControllerEffect.h index dc6e507f351..bac8db92948 100644 --- a/plugins/PeakControllerEffect/PeakControllerEffect.h +++ b/plugins/PeakControllerEffect/PeakControllerEffect.h @@ -41,8 +41,8 @@ class PeakControllerEffect : public Effect PeakControllerEffect( Model * parent, const Descriptor::SubPluginFeatures::Key * _key ); ~PeakControllerEffect() override; - bool processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls * controls() override { diff --git a/plugins/ReverbSC/ReverbSC.cpp b/plugins/ReverbSC/ReverbSC.cpp index 2def88d1db9..1383d526637 100644 --- a/plugins/ReverbSC/ReverbSC.cpp +++ b/plugins/ReverbSC/ReverbSC.cpp @@ -75,14 +75,8 @@ ReverbSCEffect::~ReverbSCEffect() sp_destroy(&sp); } -bool ReverbSCEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) +Effect::ProcessStatus ReverbSCEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - - double outSum = 0.0; const float d = dryLevel(); const float w = wetLevel(); @@ -119,14 +113,9 @@ bool ReverbSCEffect::processAudioBuffer( SampleFrame* buf, const fpp_t frames ) sp_dcblock_compute(sp, dcblk[1], &tmpR, &dcblkR); buf[f][0] = d * buf[f][0] + w * dcblkL * outGain; buf[f][1] = d * buf[f][1] + w * dcblkR * outGain; - - outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1]; } - - checkGate( outSum / frames ); - - return isRunning(); + return ProcessStatus::ContinueIfNotQuiet; } void ReverbSCEffect::changeSampleRate() diff --git a/plugins/ReverbSC/ReverbSC.h b/plugins/ReverbSC/ReverbSC.h index f3c196f5bf8..2d02662bfdf 100644 --- a/plugins/ReverbSC/ReverbSC.h +++ b/plugins/ReverbSC/ReverbSC.h @@ -45,7 +45,8 @@ class ReverbSCEffect : public Effect public: ReverbSCEffect( Model* parent, const Descriptor::SubPluginFeatures::Key* key ); ~ReverbSCEffect() override; - bool processAudioBuffer( SampleFrame* buf, const fpp_t frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/SpectrumAnalyzer/Analyzer.cpp b/plugins/SpectrumAnalyzer/Analyzer.cpp index dc2108eb9e4..7b6086ed2bb 100644 --- a/plugins/SpectrumAnalyzer/Analyzer.cpp +++ b/plugins/SpectrumAnalyzer/Analyzer.cpp @@ -77,7 +77,7 @@ Analyzer::~Analyzer() } // Take audio data and pass them to the spectrum processor. -bool Analyzer::processAudioBuffer(SampleFrame* buffer, const fpp_t frame_count) +Effect::ProcessStatus Analyzer::processImpl(SampleFrame* buf, const fpp_t frames) { // Measure time spent in audio thread; both average and peak should be well under 1 ms. #ifdef SA_DEBUG @@ -91,14 +91,12 @@ bool Analyzer::processAudioBuffer(SampleFrame* buffer, const fpp_t frame_count) } #endif - if (!isEnabled() || !isRunning ()) {return false;} - // Skip processing if the controls dialog isn't visible, it would only waste CPU cycles. if (m_controls.isViewVisible()) { // To avoid processing spikes on audio thread, data are stored in // a lockless ringbuffer and processed in a separate thread. - m_inputBuffer.write(buffer, frame_count, true); + m_inputBuffer.write(buf, frames, true); } #ifdef SA_DEBUG audio_time = std::chrono::high_resolution_clock::now().time_since_epoch().count() - audio_time; @@ -107,7 +105,7 @@ bool Analyzer::processAudioBuffer(SampleFrame* buffer, const fpp_t frame_count) if (audio_time / 1000000.0 > m_max_execution) {m_max_execution = audio_time / 1000000.0;} #endif - return isRunning(); + return ProcessStatus::Continue; } diff --git a/plugins/SpectrumAnalyzer/Analyzer.h b/plugins/SpectrumAnalyzer/Analyzer.h index da87ffd3527..d898b13335d 100644 --- a/plugins/SpectrumAnalyzer/Analyzer.h +++ b/plugins/SpectrumAnalyzer/Analyzer.h @@ -45,7 +45,8 @@ class Analyzer : public Effect Analyzer(Model *parent, const Descriptor::SubPluginFeatures::Key *key); ~Analyzer() override; - bool processAudioBuffer(SampleFrame* buffer, const fpp_t frame_count) override; + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + EffectControls *controls() override {return &m_controls;} SaProcessor *getProcessor() {return &m_processor;} diff --git a/plugins/StereoEnhancer/StereoEnhancer.cpp b/plugins/StereoEnhancer/StereoEnhancer.cpp index 261c897df2f..f0cf830c52e 100644 --- a/plugins/StereoEnhancer/StereoEnhancer.cpp +++ b/plugins/StereoEnhancer/StereoEnhancer.cpp @@ -82,28 +82,17 @@ StereoEnhancerEffect::~StereoEnhancerEffect() -bool StereoEnhancerEffect::processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) +Effect::ProcessStatus StereoEnhancerEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - - // This appears to be used for determining whether or not to continue processing - // audio with this effect - double out_sum = 0.0; - - if( !isEnabled() || !isRunning() ) - { - return( false ); - } - const float d = dryLevel(); const float w = wetLevel(); - for( fpp_t f = 0; f < _frames; ++f ) + for (fpp_t f = 0; f < frames; ++f) { // copy samples into the delay buffer - m_delayBuffer[m_currFrame][0] = _buf[f][0]; - m_delayBuffer[m_currFrame][1] = _buf[f][1]; + m_delayBuffer[m_currFrame][0] = buf[f][0]; + m_delayBuffer[m_currFrame][1] = buf[f][1]; // Get the width knob value from the Stereo Enhancer effect float width = m_seFX.wideCoeff(); @@ -117,27 +106,25 @@ bool StereoEnhancerEffect::processAudioBuffer( SampleFrame* _buf, frameIndex += DEFAULT_BUFFER_SIZE; } - //sample_t s[2] = { _buf[f][0], _buf[f][1] }; //Vanilla - auto s = std::array{_buf[f][0], m_delayBuffer[frameIndex][1]}; //Chocolate + //sample_t s[2] = { buf[f][0], buf[f][1] }; //Vanilla + auto s = std::array{buf[f][0], m_delayBuffer[frameIndex][1]}; //Chocolate m_seFX.nextSample( s[0], s[1] ); - _buf[f][0] = d * _buf[f][0] + w * s[0]; - _buf[f][1] = d * _buf[f][1] + w * s[1]; - out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; + buf[f][0] = d * buf[f][0] + w * s[0]; + buf[f][1] = d * buf[f][1] + w * s[1]; // Update currFrame m_currFrame += 1; m_currFrame %= DEFAULT_BUFFER_SIZE; } - checkGate( out_sum / _frames ); if( !isRunning() ) { clearMyBuffer(); } - return( isRunning() ); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/StereoEnhancer/StereoEnhancer.h b/plugins/StereoEnhancer/StereoEnhancer.h index 861187f8f7e..3e27330add1 100644 --- a/plugins/StereoEnhancer/StereoEnhancer.h +++ b/plugins/StereoEnhancer/StereoEnhancer.h @@ -40,8 +40,8 @@ class StereoEnhancerEffect : public Effect StereoEnhancerEffect( Model * parent, const Descriptor::SubPluginFeatures::Key * _key ); ~StereoEnhancerEffect() override; - bool processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls * controls() override { diff --git a/plugins/StereoMatrix/StereoMatrix.cpp b/plugins/StereoMatrix/StereoMatrix.cpp index c4384fddd60..038b560594b 100644 --- a/plugins/StereoMatrix/StereoMatrix.cpp +++ b/plugins/StereoMatrix/StereoMatrix.cpp @@ -64,44 +64,29 @@ StereoMatrixEffect::StereoMatrixEffect( -bool StereoMatrixEffect::processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) +Effect::ProcessStatus StereoMatrixEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - - // This appears to be used for determining whether or not to continue processing - // audio with this effect - if( !isEnabled() || !isRunning() ) - { - return( false ); - } - - double out_sum = 0.0; - - for( fpp_t f = 0; f < _frames; ++f ) + for (fpp_t f = 0; f < frames; ++f) { const float d = dryLevel(); const float w = wetLevel(); - sample_t l = _buf[f][0]; - sample_t r = _buf[f][1]; + sample_t l = buf[f][0]; + sample_t r = buf[f][1]; // Init with dry-mix - _buf[f][0] = l * d; - _buf[f][1] = r * d; + buf[f][0] = l * d; + buf[f][1] = r * d; // Add it wet - _buf[f][0] += ( m_smControls.m_llModel.value( f ) * l + + buf[f][0] += ( m_smControls.m_llModel.value( f ) * l + m_smControls.m_rlModel.value( f ) * r ) * w; - _buf[f][1] += ( m_smControls.m_lrModel.value( f ) * l + + buf[f][1] += ( m_smControls.m_lrModel.value( f ) * l + m_smControls.m_rrModel.value( f ) * r ) * w; - out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; - } - checkGate( out_sum / _frames ); - - return( isRunning() ); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/StereoMatrix/StereoMatrix.h b/plugins/StereoMatrix/StereoMatrix.h index a254264f838..2b2b22f1aec 100644 --- a/plugins/StereoMatrix/StereoMatrix.h +++ b/plugins/StereoMatrix/StereoMatrix.h @@ -39,8 +39,8 @@ class StereoMatrixEffect : public Effect StereoMatrixEffect( Model * parent, const Descriptor::SubPluginFeatures::Key * _key ); ~StereoMatrixEffect() override = default; - bool processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls* controls() override { diff --git a/plugins/Vectorscope/Vectorscope.cpp b/plugins/Vectorscope/Vectorscope.cpp index c94eb5d2834..106116c8469 100644 --- a/plugins/Vectorscope/Vectorscope.cpp +++ b/plugins/Vectorscope/Vectorscope.cpp @@ -58,18 +58,17 @@ Vectorscope::Vectorscope(Model *parent, const Plugin::Descriptor::SubPluginFeatu // Take audio data and store them for processing and display in the GUI thread. -bool Vectorscope::processAudioBuffer(SampleFrame* buffer, const fpp_t frame_count) +Effect::ProcessStatus Vectorscope::processImpl(SampleFrame* buf, const fpp_t frames) { - if (!isEnabled() || !isRunning ()) {return false;} - // Skip processing if the controls dialog isn't visible, it would only waste CPU cycles. if (m_controls.isViewVisible()) { // To avoid processing spikes on audio thread, data are stored in // a lockless ringbuffer and processed in a separate thread. - m_inputBuffer.write(buffer, frame_count); + m_inputBuffer.write(buf, frames); } - return isRunning(); + + return ProcessStatus::Continue; } diff --git a/plugins/Vectorscope/Vectorscope.h b/plugins/Vectorscope/Vectorscope.h index 66d20e63903..528b236905a 100644 --- a/plugins/Vectorscope/Vectorscope.h +++ b/plugins/Vectorscope/Vectorscope.h @@ -39,7 +39,8 @@ class Vectorscope : public Effect Vectorscope(Model *parent, const Descriptor::SubPluginFeatures::Key *key); ~Vectorscope() override = default; - bool processAudioBuffer(SampleFrame* buffer, const fpp_t frame_count) override; + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; + EffectControls *controls() override {return &m_controls;} LocklessRingBuffer *getBuffer() {return &m_inputBuffer;} diff --git a/plugins/VstEffect/VstEffect.cpp b/plugins/VstEffect/VstEffect.cpp index ecb8240c867..53de4f4cc59 100644 --- a/plugins/VstEffect/VstEffect.cpp +++ b/plugins/VstEffect/VstEffect.cpp @@ -65,63 +65,47 @@ VstEffect::VstEffect( Model * _parent, m_key( *_key ), m_vstControls( this ) { + bool loaded = false; if( !m_key.attributes["file"].isEmpty() ) { - openPlugin( m_key.attributes["file"] ); + loaded = openPlugin(m_key.attributes["file"]); } setDisplayName( m_key.attributes["file"].section( ".dll", 0, 0 ).isEmpty() ? m_key.name : m_key.attributes["file"].section( ".dll", 0, 0 ) ); + + setDontRun(!loaded); } -bool VstEffect::processAudioBuffer( SampleFrame* _buf, const fpp_t _frames ) +Effect::ProcessStatus VstEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) + assert(m_plugin != nullptr); + static thread_local auto tempBuf = std::array(); + + std::memcpy(tempBuf.data(), buf, sizeof(SampleFrame) * frames); + if (m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) { - return false; + m_plugin->process(tempBuf.data(), tempBuf.data()); + m_pluginMutex.unlock(); } - if( m_plugin ) + const float w = wetLevel(); + const float d = dryLevel(); + for (fpp_t f = 0; f < frames; ++f) { - const float d = dryLevel(); -#ifdef __GNUC__ - SampleFrame buf[_frames]; -#else - SampleFrame* buf = new SampleFrame[_frames]; -#endif - memcpy( buf, _buf, sizeof( SampleFrame ) * _frames ); - if (m_pluginMutex.tryLock(Engine::getSong()->isExporting() ? -1 : 0)) - { - m_plugin->process( buf, buf ); - m_pluginMutex.unlock(); - } - - double out_sum = 0.0; - const float w = wetLevel(); - for( fpp_t f = 0; f < _frames; ++f ) - { - _buf[f][0] = w*buf[f][0] + d*_buf[f][0]; - _buf[f][1] = w*buf[f][1] + d*_buf[f][1]; - } - for( fpp_t f = 0; f < _frames; ++f ) - { - out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; - } -#ifndef __GNUC__ - delete[] buf; -#endif - - checkGate( out_sum / _frames ); + buf[f][0] = w * tempBuf[f][0] + d * buf[f][0]; + buf[f][1] = w * tempBuf[f][1] + d * buf[f][1]; } - return isRunning(); + + return ProcessStatus::ContinueIfNotQuiet; } -void VstEffect::openPlugin( const QString & _plugin ) +bool VstEffect::openPlugin(const QString& plugin) { gui::TextFloat* tf = nullptr; if( gui::getGUI() != nullptr ) @@ -133,18 +117,19 @@ void VstEffect::openPlugin( const QString & _plugin ) } QMutexLocker ml( &m_pluginMutex ); Q_UNUSED( ml ); - m_plugin = QSharedPointer(new VstPlugin( _plugin )); + m_plugin = QSharedPointer(new VstPlugin(plugin)); if( m_plugin->failed() ) { m_plugin.clear(); delete tf; - collectErrorForUI( VstPlugin::tr( "The VST plugin %1 could not be loaded." ).arg( _plugin ) ); - return; + collectErrorForUI(VstPlugin::tr("The VST plugin %1 could not be loaded.").arg(plugin)); + return false; } delete tf; - m_key.attributes["file"] = _plugin; + m_key.attributes["file"] = plugin; + return true; } diff --git a/plugins/VstEffect/VstEffect.h b/plugins/VstEffect/VstEffect.h index c3f6e8091ce..a8fbd410b78 100644 --- a/plugins/VstEffect/VstEffect.h +++ b/plugins/VstEffect/VstEffect.h @@ -45,8 +45,7 @@ class VstEffect : public Effect const Descriptor::SubPluginFeatures::Key * _key ); ~VstEffect() override = default; - bool processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) override; + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls * controls() override { @@ -55,7 +54,8 @@ class VstEffect : public Effect private: - void openPlugin( const QString & _plugin ); + //! Returns true if plugin was loaded (m_plugin != nullptr) + bool openPlugin(const QString& plugin); void closePlugin(); QSharedPointer m_plugin; diff --git a/plugins/WaveShaper/WaveShaper.cpp b/plugins/WaveShaper/WaveShaper.cpp index 37378540867..f21a2dff77f 100644 --- a/plugins/WaveShaper/WaveShaper.cpp +++ b/plugins/WaveShaper/WaveShaper.cpp @@ -66,18 +66,11 @@ WaveShaperEffect::WaveShaperEffect( Model * _parent, -bool WaveShaperEffect::processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) +Effect::ProcessStatus WaveShaperEffect::processImpl(SampleFrame* buf, const fpp_t frames) { - if( !isEnabled() || !isRunning () ) - { - return( false ); - } - // variables for effect int i = 0; - double out_sum = 0.0; const float d = dryLevel(); const float w = wetLevel(); float input = m_wsControls.m_inputModel.value(); @@ -94,9 +87,9 @@ bool WaveShaperEffect::processAudioBuffer( SampleFrame* _buf, const float *inputPtr = inputBuffer ? &( inputBuffer->values()[ 0 ] ) : &input; const float *outputPtr = outputBufer ? &( outputBufer->values()[ 0 ] ) : &output; - for( fpp_t f = 0; f < _frames; ++f ) + for (fpp_t f = 0; f < frames; ++f) { - auto s = std::array{_buf[f][0], _buf[f][1]}; + auto s = std::array{buf[f][0], buf[f][1]}; // apply input gain s[0] *= *inputPtr; @@ -138,17 +131,14 @@ bool WaveShaperEffect::processAudioBuffer( SampleFrame* _buf, s[1] *= *outputPtr; // mix wet/dry signals - _buf[f][0] = d * _buf[f][0] + w * s[0]; - _buf[f][1] = d * _buf[f][1] + w * s[1]; - out_sum += _buf[f][0] * _buf[f][0] + _buf[f][1] * _buf[f][1]; + buf[f][0] = d * buf[f][0] + w * s[0]; + buf[f][1] = d * buf[f][1] + w * s[1]; outputPtr += outputInc; inputPtr += inputInc; } - checkGate( out_sum / _frames ); - - return( isRunning() ); + return ProcessStatus::ContinueIfNotQuiet; } diff --git a/plugins/WaveShaper/WaveShaper.h b/plugins/WaveShaper/WaveShaper.h index 4c9d6e96222..773419de8c8 100644 --- a/plugins/WaveShaper/WaveShaper.h +++ b/plugins/WaveShaper/WaveShaper.h @@ -40,8 +40,8 @@ class WaveShaperEffect : public Effect WaveShaperEffect( Model * _parent, const Descriptor::SubPluginFeatures::Key * _key ); ~WaveShaperEffect() override = default; - bool processAudioBuffer( SampleFrame* _buf, - const fpp_t _frames ) override; + + ProcessStatus processImpl(SampleFrame* buf, const fpp_t frames) override; EffectControls * controls() override { diff --git a/src/core/Effect.cpp b/src/core/Effect.cpp index b6b2840515a..1fb0b71b5c1 100644 --- a/src/core/Effect.cpp +++ b/src/core/Effect.cpp @@ -122,6 +122,41 @@ void Effect::loadSettings( const QDomElement & _this ) +bool Effect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) +{ + if (!isOkay() || dontRun() || !isEnabled() || !isRunning()) + { + processBypassedImpl(); + return false; + } + + const auto status = processImpl(buf, frames); + switch (status) + { + case ProcessStatus::Continue: + break; + case ProcessStatus::ContinueIfNotQuiet: + { + double outSum = 0.0; + for (std::size_t idx = 0; idx < frames; ++idx) + { + outSum += buf[idx].sumOfSquaredAmplitudes(); + } + + checkGate(outSum / frames); + break; + } + case ProcessStatus::Sleep: + return false; + default: + break; + } + + return isRunning(); +} + + + Effect * Effect::instantiate( const QString& pluginName, Model * _parent, @@ -146,7 +181,7 @@ Effect * Effect::instantiate( const QString& pluginName, -void Effect::checkGate( double _out_sum ) +void Effect::checkGate(double outSum) { if( m_autoQuitDisabled ) { @@ -155,7 +190,7 @@ void Effect::checkGate( double _out_sum ) // Check whether we need to continue processing input. Restart the // counter if the threshold has been exceeded. - if (_out_sum - gate() <= F_EPSILON) + if (outSum - gate() <= F_EPSILON) { incrementBufferCount(); if( bufferCount() > timeout() ) diff --git a/src/gui/modals/SetupDialog.cpp b/src/gui/modals/SetupDialog.cpp index 6f05433b782..d71ede03f53 100644 --- a/src/gui/modals/SetupDialog.cpp +++ b/src/gui/modals/SetupDialog.cpp @@ -564,7 +564,7 @@ SetupDialog::SetupDialog(ConfigTab tab_to_open) : QHBoxLayout * bufferSizeSubLayout = new QHBoxLayout(); m_bufferSizeSlider = new QSlider(Qt::Horizontal, bufferSizeBox); - m_bufferSizeSlider->setRange(1, 128); + m_bufferSizeSlider->setRange(1, MAXIMUM_BUFFER_SIZE / BUFFERSIZE_RESOLUTION); m_bufferSizeSlider->setTickInterval(8); m_bufferSizeSlider->setPageStep(8); m_bufferSizeSlider->setValue(m_bufferSize / BUFFERSIZE_RESOLUTION);