Refactor Effect processing (#7484)
* Move common effect processing code to wrapper method
- Introduce `processImpl` and `sleepImpl` methods, and adapt each effect
plugin to use them
- Use double for RMS out sum in Compressor and LOMM
- Run `checkGate` for GranularPitchShifterEffect
- Minor changes to LadspaEffect
- Remove dynamic allocations and VLAs from VstEffect's process method
- Some minor style/formatting fixes
* Fix VstEffect regression
* GranularPitchShifterEffect should not call `checkGate`
* Apply suggestions from code review
Co-authored-by: saker <sakertooth@gmail.com>
* Follow naming convention for local variables
* Add `MAXIMUM_BUFFER_SIZE` and use it in VstEffect
* Revert "GranularPitchShifterEffect should not call `checkGate`"
This reverts commit 67526f0ffe.
* VstEffect: Simplify setting "Don't Run" state
* Rename `sleepImpl` to `processBypassedImpl`
* Use `MAXIMUM_BUFFER_SIZE` in SetupDialog
* Pass `outSum` as out parameter; Fix LadspaEffect mutex
* Move outSum calculations to wrapper method
* Fix Linux build
* Oops
* Apply suggestions from code review
Co-authored-by: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com>
* Apply suggestions from code review
Co-authored-by: saker <sakertooth@gmail.com>
---------
Co-authored-by: saker <sakertooth@gmail.com>
Co-authored-by: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
@@ -98,6 +98,7 @@ public:
|
||||
m_originalPluginData( originalPluginData )
|
||||
{
|
||||
setName();
|
||||
setDontRun(true);
|
||||
}
|
||||
|
||||
~DummyEffect() override = default;
|
||||
@@ -107,9 +108,9 @@ public:
|
||||
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
|
||||
|
||||
@@ -63,9 +63,8 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
Effects should call this at the end of audio processing
|
||||
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
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 @@ protected:
|
||||
|
||||
|
||||
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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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<BasicFilters<2>::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<BasicFilters<2>::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()
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -42,8 +42,9 @@ public:
|
||||
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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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<SampleFrame> sBuf(_frames);
|
||||
auto outFrames = frames;
|
||||
SampleFrame* outBuf = nullptr;
|
||||
QVarLengthArray<SampleFrame> 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -47,9 +47,8 @@ public:
|
||||
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
|
||||
|
||||
@@ -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<fpp_t>(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<double>(buf[f][0]);
|
||||
auto r = static_cast<double>(buf[f][1]);
|
||||
outSum += l*l + r*r;
|
||||
}
|
||||
checkGate(outSum / frames);
|
||||
|
||||
return isRunning();
|
||||
return ProcessStatus::ContinueIfNotQuiet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ public:
|
||||
*/
|
||||
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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ public:
|
||||
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
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ public:
|
||||
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;}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@ public:
|
||||
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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ public:
|
||||
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<SampleFrame> *getBuffer() {return &m_inputBuffer;}
|
||||
|
||||
|
||||
@@ -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<SampleFrame, MAXIMUM_BUFFER_SIZE>();
|
||||
|
||||
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<VstPlugin>(new VstPlugin( _plugin ));
|
||||
m_plugin = QSharedPointer<VstPlugin>(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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
void openPlugin( const QString & _plugin );
|
||||
//! Returns true if plugin was loaded (m_plugin != nullptr)
|
||||
bool openPlugin(const QString& plugin);
|
||||
void closePlugin();
|
||||
|
||||
QSharedPointer<VstPlugin> m_plugin;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@ public:
|
||||
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
|
||||
{
|
||||
|
||||
@@ -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() )
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user