Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wet/dry panning knob to all LMMS effects #4635

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions include/Effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,27 @@ class LMMS_EXPORT Effect : public Plugin
return 1.0f - m_wetDryModel.value();
}

inline float panAmount() const
{
return m_panModel.value();
}
inline float wetLevelL() const
{
return ( m_panModel.value() < 0 ) ? m_wetDryModel.value() : ( m_wetDryModel.value() * ( ( -m_panModel.value() + 100 ) / 100 ) );
}
inline float wetLevelR() const
{
return ( m_panModel.value() > 0 ) ? m_wetDryModel.value() : ( m_wetDryModel.value() * ( ( m_panModel.value() + 100 ) / 100 ) );
}
inline float dryLevelL() const
{
return 1.0f - ( ( m_panModel.value() < 0 ) ? m_wetDryModel.value() : ( m_wetDryModel.value() * ( ( -m_panModel.value() + 100 ) / 100 ) ) );
}
inline float dryLevelR() const
{
return 1.0f - ( ( m_panModel.value() > 0 ) ? m_wetDryModel.value() : ( m_wetDryModel.value() * ( ( m_panModel.value() + 100 ) / 100 ) ) );
}

inline float gate() const
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functions above are using a linear panning law, there is already a panning law function in panning.h called panningToVolumeVector https://github.com/LMMS/lmms/blob/master/include/panning.h#L34. This existing function should be used in your calculations, as this aids with a consistent user experience, and keeps the code base more maintainable.

{
const float level = m_gateModel.value();
Expand Down Expand Up @@ -212,6 +233,7 @@ class LMMS_EXPORT Effect : public Plugin

BoolModel m_enabledModel;
FloatModel m_wetDryModel;
FloatModel m_panModel;
FloatModel m_gateModel;
TempoSyncKnobModel m_autoQuitModel;

Expand Down
1 change: 1 addition & 0 deletions include/EffectView.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public slots:
QPixmap m_bg;
LedCheckBox * m_bypass;
Knob * m_wetDry;
Knob * m_pan;
TempoSyncKnob * m_autoQuit;
Knob * m_gate;
QMdiSubWindow * m_subWindow;
Expand Down
8 changes: 4 additions & 4 deletions plugins/Amplifier/Amplifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
}

double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};

const ValueBuffer * volBuf = m_ampControls.m_volumeModel.valueBuffer();
const ValueBuffer * panBuf = m_ampControls.m_panModel.valueBuffer();
Expand Down Expand Up @@ -121,8 +121,8 @@ bool AmplifierEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
s[0] *= left1 * left2 * 0.01;
s[1] *= right1 * right2 * 0.01;

buf[f][0] = d * buf[f][0] + w * s[0];
buf[f][1] = d * buf[f][1] + w * s[1];
buf[f][0] = d[0] * buf[f][0] + w[0] * s[0];
buf[f][1] = d[1] * buf[f][1] + w[1] * s[1];
}

checkGate( outSum / frames );
Expand Down
8 changes: 4 additions & 4 deletions plugins/BassBooster/BassBooster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
const ValueBuffer *gainBuffer = m_bbControls.m_gainModel.valueBuffer();

double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};

for( fpp_t f = 0; f < frames; ++f )
{
Expand All @@ -105,8 +105,8 @@ bool BassBoosterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
sample_t s[2] = { buf[f][0], buf[f][1] };
m_bbFX.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];
buf[f][0] = d[0] * buf[f][0] + w[0] * s[0];
buf[f][1] = d[1] * buf[f][1] + w[1] * s[1];
}

checkGate( outSum / frames );
Expand Down
8 changes: 4 additions & 4 deletions plugins/Bitcrush/Bitcrush.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ 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();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};
for( int f = 0; f < frames; ++f )
{
float lsum = 0.0f;
Expand All @@ -230,8 +230,8 @@ bool BitcrushEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
lsum += m_buffer[f * OS_RATE + o][0] * OS_RESAMPLE[o];
rsum += m_buffer[f * OS_RATE + o][1] * OS_RESAMPLE[o];
}
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;
buf[f][0] = d[0] * buf[f][0] + w[0] * qBound( -m_outClip, lsum, m_outClip ) * m_outGain;
buf[f][1] = d[1] * buf[f][1] + w[1] * qBound( -m_outClip, rsum, m_outClip ) * m_outGain;
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}

Expand Down
8 changes: 4 additions & 4 deletions plugins/CrossoverEQ/CrossoverEQ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,14 @@ bool CrossoverEQEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
}
}

const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};
double outSum = 0.0;
for( int f = 0; f < frames; ++f )
{
outSum = buf[f][0] * buf[f][0] + buf[f][1] * buf[f][1];
buf[f][0] = d * buf[f][0] + w * m_work[f][0];
buf[f][1] = d * buf[f][1] + w * m_work[f][1];
buf[f][0] = d[0] * buf[f][0] + w[0] * m_work[f][0];
buf[f][1] = d[1] * buf[f][1] + w[1] * m_work[f][1];
}

checkGate( outSum );
Expand Down
8 changes: 4 additions & 4 deletions plugins/Delay/DelayEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
}
double outSum = 0.0;
const float sr = Engine::mixer()->processingSampleRate();
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};
sample_t dryS[2];
float lPeak = 0.0;
float rPeak = 0.0;
Expand Down Expand Up @@ -128,8 +128,8 @@ bool DelayEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
lPeak = buf[f][0] > lPeak ? buf[f][0] : lPeak;
rPeak = buf[f][1] > rPeak ? buf[f][1] : rPeak;

buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] );
buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] );
buf[f][0] = ( d[0] * dryS[0] ) + ( w[0] * buf[f][0] );
buf[f][1] = ( d[1] * dryS[1] ) + ( w[1] * buf[f][1] );
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];

lengthPtr += lengthInc;
Expand Down
8 changes: 4 additions & 4 deletions plugins/DualFilter/DualFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
}

double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};

if( m_dfControls.m_filter1Model.isValueChanged() || m_filter1changed )
{
Expand Down Expand Up @@ -196,8 +196,8 @@ bool DualFilterEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];

// 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];
buf[f][0] = d[0] * buf[f][0] + w[0] * s[0];
buf[f][1] = d[1] * buf[f][1] + w[1] * s[1];

//increment pointers
cut1Ptr += cut1Inc;
Expand Down
8 changes: 4 additions & 4 deletions plugins/Eq/EqEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
const int sampleRate = Engine::mixer()->processingSampleRate();

//wet/dry controls
const float dry = dryLevel();
const float wet = wetLevel();
const float dry [2] = {dryLevelL(),dryLevelR()};
const float wet [2] = {wetLevelL(),wetLevelR()};
sample_t dryS[2];
// setup sample exact controls
float hpRes = m_eqControls.m_hpResModel.value();
Expand Down Expand Up @@ -262,8 +262,8 @@ bool EqEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
}

//apply wet / dry levels
buf[f][1] = ( dry * dryS[1] ) + ( wet * buf[f][1] );
buf[f][0] = ( dry * dryS[0] ) + ( wet * buf[f][0] );
buf[f][1] = ( dry[1] * dryS[1] ) + ( wet[1] * buf[f][1] );
buf[f][0] = ( dry[0] * dryS[0] ) + ( wet[0] * buf[f][0] );


}
Expand Down
8 changes: 4 additions & 4 deletions plugins/Flanger/FlangerEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
return( false );
}
double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};
const float length = m_flangerControls.m_delayTimeModel.value() * Engine::mixer()->processingSampleRate();
const float noise = m_flangerControls.m_whiteNoiseAmountModel.value();
float amplitude = m_flangerControls.m_lfoAmountModel.value() * Engine::mixer()->processingSampleRate();
Expand Down Expand Up @@ -121,8 +121,8 @@ bool FlangerEffect::processAudioBuffer( sampleFrame *buf, const fpp_t frames )
m_rDelay->tick( &buf[f][1] );
}

buf[f][0] = ( d * dryS[0] ) + ( w * buf[f][0] );
buf[f][1] = ( d * dryS[1] ) + ( w * buf[f][1] );
buf[f][0] = ( d[0] * dryS[0] ) + ( w[0] * buf[f][0] );
buf[f][1] = ( d[1] * dryS[1] ) + ( w[1] * buf[f][1] );
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
checkGate( outSum / frames );
Expand Down
6 changes: 3 additions & 3 deletions plugins/LadspaEffect/LadspaEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,8 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
// Copy the LADSPA output buffers to the LMMS buffer.
double out_sum = 0.0;
channel = 0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};
for( ch_cnt_t proc = 0; proc < processorCount(); ++proc )
{
for( int port = 0; port < m_portCount; ++port )
Expand All @@ -240,7 +240,7 @@ bool LadspaEffect::processAudioBuffer( sampleFrame * _buf,
for( fpp_t frame = 0;
frame < frames; ++frame )
{
_buf[frame][channel] = d * _buf[frame][channel] + w * pp->buffer[frame];
_buf[frame][channel] = d[channel] * _buf[frame][channel] + w[channel] * pp->buffer[frame];
out_sum += _buf[frame][channel] * _buf[frame][channel];
}
++channel;
Expand Down
8 changes: 4 additions & 4 deletions plugins/MultitapEcho/MultitapEcho.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t fram
}

double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};

// get processing vars
const int steps = m_controls.m_steps.value();
Expand Down Expand Up @@ -149,8 +149,8 @@ bool MultitapEchoEffect::processAudioBuffer( sampleFrame * buf, const fpp_t fram

for( int f = 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];
buf[f][0] = d[0] * buf[f][0] + w[0] * m_work[f][0];
buf[f][1] = d[1] * buf[f][1] + w[1] * m_work[f][1];
outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}

Expand Down
8 changes: 4 additions & 4 deletions plugins/ReverbSC/ReverbSC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
}

double outSum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};

SPFLOAT tmpL, tmpR;
SPFLOAT dcblkL, dcblkR;
Expand Down Expand Up @@ -115,8 +115,8 @@ bool ReverbSCEffect::processAudioBuffer( sampleFrame* buf, const fpp_t frames )
sp_revsc_compute(sp, revsc, &s[0], &s[1], &tmpL, &tmpR);
sp_dcblock_compute(sp, dcblk[0], &tmpL, &dcblkL);
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;
buf[f][0] = d[0] * buf[f][0] + w[0] * dcblkL * outGain;
buf[f][1] = d[1] * buf[f][1] + w[1] * dcblkR * outGain;

outSum += buf[f][0]*buf[f][0] + buf[f][1]*buf[f][1];
}
Expand Down
8 changes: 4 additions & 4 deletions plugins/VstEffect/VstEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ bool VstEffect::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames )

if( m_plugin )
{
const float d = dryLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};
#ifdef __GNUC__
sampleFrame buf[_frames];
#else
Expand All @@ -102,11 +103,10 @@ bool VstEffect::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames )
}

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];
_buf[f][0] = w[0]*buf[f][0] + d[0]*_buf[f][0];
_buf[f][1] = w[1]*buf[f][1] + d[1]*_buf[f][1];
}
for( fpp_t f = 0; f < _frames; ++f )
{
Expand Down
8 changes: 4 additions & 4 deletions plugins/dynamics_processor/dynamics_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,
float gain;

double out_sum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};

const int stereoMode = m_dpControls.m_stereomodeModel.value();
const float inputGain = m_dpControls.m_inputModel.value();
Expand Down Expand Up @@ -217,8 +217,8 @@ bool dynProcEffect::processAudioBuffer( sampleFrame * _buf,

out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
// mix wet/dry signals
_buf[f][0] = d * _buf[f][0] + w * s[0];
_buf[f][1] = d * _buf[f][1] + w * s[1];
_buf[f][0] = d[0] * _buf[f][0] + w[0] * s[0];
_buf[f][1] = d[1] * _buf[f][1] + w[1] * s[1];
}

checkGate( out_sum / _frames );
Expand Down
8 changes: 4 additions & 4 deletions plugins/stereo_enhancer/stereo_enhancer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ bool stereoEnhancerEffect::processAudioBuffer( sampleFrame * _buf,
return( false );
}

const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};

for( fpp_t f = 0; f < _frames; ++f )
{
Expand All @@ -122,8 +122,8 @@ bool stereoEnhancerEffect::processAudioBuffer( sampleFrame * _buf,

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];
_buf[f][0] = d[0] * _buf[f][0] + w[0] * s[0];
_buf[f][1] = d[1] * _buf[f][1] + w[1] * s[1];
out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];

// Update currFrame
Expand Down
12 changes: 6 additions & 6 deletions plugins/stereo_matrix/stereo_matrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,22 +81,22 @@ bool stereoMatrixEffect::processAudioBuffer( sampleFrame * _buf,

for( fpp_t f = 0; f < _frames; ++f )
{
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};

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[0];
_buf[f][1] = r * d[1];

// Add it wet
_buf[f][0] += ( m_smControls.m_llModel.value( f ) * l +
m_smControls.m_rlModel.value( f ) * r ) * w;
m_smControls.m_rlModel.value( f ) * r ) * w[0];

_buf[f][1] += ( m_smControls.m_lrModel.value( f ) * l +
m_smControls.m_rrModel.value( f ) * r ) * w;
m_smControls.m_rrModel.value( f ) * r ) * w[1];
out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];

}
Expand Down
8 changes: 4 additions & 4 deletions plugins/waveshaper/waveshaper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,
int i = 0;

double out_sum = 0.0;
const float d = dryLevel();
const float w = wetLevel();
const float d [2] = {dryLevelL(),dryLevelR()};
const float w [2] = {wetLevelL(),wetLevelR()};
float input = m_wsControls.m_inputModel.value();
float output = m_wsControls.m_outputModel.value();
const float * samples = m_wsControls.m_wavegraphModel.samples();
Expand Down Expand Up @@ -142,8 +142,8 @@ bool waveShaperEffect::processAudioBuffer( sampleFrame * _buf,

out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1];
// mix wet/dry signals
_buf[f][0] = d * _buf[f][0] + w * s[0];
_buf[f][1] = d * _buf[f][1] + w * s[1];
_buf[f][0] = d[0] * _buf[f][0] + w[0] * s[0];
_buf[f][1] = d[1] * _buf[f][1] + w[1] * s[1];

outputPtr += outputInc;
inputPtr += inputInc;
Expand Down
Loading