diff --git a/lib/reverb/Reverb.cc b/lib/reverb/Reverb.cc index e9d5ddbba661..67f4b0ec1c3a 100644 --- a/lib/reverb/Reverb.cc +++ b/lib/reverb/Reverb.cc @@ -434,7 +434,7 @@ Descriptor::setup() // (timrae) we have our left / right samples interleaved in the same array, so use slightly modified version of PlateX2::cycle void MixxxPlateX2::processBuffer(const sample_t* in, sample_t* out, const uint frames, const sample_t bandwidthParam, - const sample_t decayParam, const sample_t dampingParam, const sample_t blendParam) { + const sample_t decayParam, const sample_t dampingParam, const sample_t blendParam, double wet) { // set bandwidth input.bandwidth.set(exp(-M_PI * (1. - (.005 + .994*bandwidthParam)))); // set decay @@ -454,7 +454,8 @@ void MixxxPlateX2::processBuffer(const sample_t* in, sample_t* out, const uint f sample_t mono_sample = blend * (in[i] + in[i + 1]) / 2; sample_t xl, xr; PlateStub::process(mono_sample, decay, &xl, &xr); - out[i] = xl + in[i]; - out[i + 1] = xr + in[i + 1]; + out[i] = (xl * wet) + (in[i] * (1 - wet)); + out[i + 1] = (xr * wet) + (in[i + 1] * (1 - wet)); } } + diff --git a/lib/reverb/Reverb.h b/lib/reverb/Reverb.h index ae9591905f44..c40a108b46d3 100644 --- a/lib/reverb/Reverb.h +++ b/lib/reverb/Reverb.h @@ -224,7 +224,7 @@ class PlateX2 class MixxxPlateX2 : public PlateStub { public: void processBuffer(const sample_t* in, sample_t* out, const uint frames, const sample_t bandwidthParam, - const sample_t decayParam, const sample_t dampingParam, const sample_t blendParam); + const sample_t decayParam, const sample_t dampingParam, const sample_t blendParam, double wet); void init(float sampleRate) { fs = sampleRate; diff --git a/res/skins/Tango/fx_unit_left.xml b/res/skins/Tango/fx_unit_left.xml index 9bf816092407..e150fc8b3733 100644 --- a/res/skins/Tango/fx_unit_left.xml +++ b/res/skins/Tango/fx_unit_left.xml @@ -240,6 +240,17 @@ Variables: 1min,0me + + + 1min,0me + min,min vertical diff --git a/res/skins/Tango/fx_unit_left_mini.xml b/res/skins/Tango/fx_unit_left_mini.xml index e962a367138d..dbf95048192b 100644 --- a/res/skins/Tango/fx_unit_left_mini.xml +++ b/res/skins/Tango/fx_unit_left_mini.xml @@ -225,6 +225,15 @@ Variables: + + + + max,min vertical diff --git a/src/controllers/controlpickermenu.cpp b/src/controllers/controlpickermenu.cpp index 674a3e063928..541d6de48a98 100644 --- a/src/controllers/controlpickermenu.cpp +++ b/src/controllers/controlpickermenu.cpp @@ -500,9 +500,9 @@ ControlPickerMenu::ControlPickerMenu(QWidget* pParent) tr("Super Knob (control effects' Meta Knobs)"), descriptionPrefix, effectUnitMenu, true); - addPrefixedControl(effectUnitGroup, "insertion_type", - tr("Insert/Send Toggle"), - tr("Insert/Send Toggle"), + addPrefixedControl(effectUnitGroup, "Mix Mode", + tr("Mix Mode Toggle"), + tr("Toggle effect unit between D/W and D+W modes"), descriptionPrefix, effectUnitMenu); addPrefixedControl(effectUnitGroup, "next_chain", diff --git a/src/effects/builtin/autopaneffect.cpp b/src/effects/builtin/autopaneffect.cpp index b1b76df88c4b..e225b313cd81 100644 --- a/src/effects/builtin/autopaneffect.cpp +++ b/src/effects/builtin/autopaneffect.cpp @@ -91,8 +91,10 @@ void AutoPanEffect::processChannel( const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); + Q_UNUSED(mixMode); if (enableState == EffectEnableState::Disabled) { return; diff --git a/src/effects/builtin/autopaneffect.h b/src/effects/builtin/autopaneffect.h index c10f265d21eb..a62a6d3b2939 100644 --- a/src/effects/builtin/autopaneffect.h +++ b/src/effects/builtin/autopaneffect.h @@ -90,7 +90,8 @@ class AutoPanEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode); double computeLawCoefficient(double position); diff --git a/src/effects/builtin/balanceeffect.cpp b/src/effects/builtin/balanceeffect.cpp index b4ca00aedae9..5e05e9d37aff 100644 --- a/src/effects/builtin/balanceeffect.cpp +++ b/src/effects/builtin/balanceeffect.cpp @@ -110,9 +110,11 @@ void BalanceEffect::processChannel(const ChannelHandle& handle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); Q_UNUSED(groupFeatures); + Q_UNUSED(mixMode); CSAMPLE_GAIN balance = 0; CSAMPLE_GAIN midSide = 0; diff --git a/src/effects/builtin/balanceeffect.h b/src/effects/builtin/balanceeffect.h index 7276e5142313..882c590688f2 100644 --- a/src/effects/builtin/balanceeffect.h +++ b/src/effects/builtin/balanceeffect.h @@ -40,7 +40,8 @@ class BalanceEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode); private: diff --git a/src/effects/builtin/bessel4lvmixeqeffect.cpp b/src/effects/builtin/bessel4lvmixeqeffect.cpp index d04873ca60f1..333969bd7275 100644 --- a/src/effects/builtin/bessel4lvmixeqeffect.cpp +++ b/src/effects/builtin/bessel4lvmixeqeffect.cpp @@ -46,9 +46,11 @@ void Bessel4LVMixEQEffect::processChannel(const ChannelHandle& handle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); Q_UNUSED(groupFeatures); + Q_UNUSED(mixMode); if (enableState == EffectEnableState::Disabling) { // Ramp to dry, when disabling, this will ramp from dry when enabling as well diff --git a/src/effects/builtin/bessel4lvmixeqeffect.h b/src/effects/builtin/bessel4lvmixeqeffect.h index 87ac83bd9b2d..f3e6e4ed469c 100644 --- a/src/effects/builtin/bessel4lvmixeqeffect.h +++ b/src/effects/builtin/bessel4lvmixeqeffect.h @@ -37,7 +37,8 @@ class Bessel4LVMixEQEffect : public EffectProcessorImplm_oldSampleRate != bufferParameters.sampleRate() || (pState->m_loFreqCorner != m_pLoFreqCorner->get()) || diff --git a/src/effects/builtin/biquadfullkilleqeffect.h b/src/effects/builtin/biquadfullkilleqeffect.h index 4b016058a705..71584b97b3b2 100644 --- a/src/effects/builtin/biquadfullkilleqeffect.h +++ b/src/effects/builtin/biquadfullkilleqeffect.h @@ -72,7 +72,8 @@ class BiquadFullKillEQEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE *pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatureState); + const GroupFeatureState& groupFeatureState, + const EffectChainMixMode mixMode); private: QString debugString() const { diff --git a/src/effects/builtin/echoeffect.cpp b/src/effects/builtin/echoeffect.cpp index 1d0451d75d2f..bbd501cf0d3d 100644 --- a/src/effects/builtin/echoeffect.cpp +++ b/src/effects/builtin/echoeffect.cpp @@ -82,7 +82,8 @@ EffectManifestPointer EchoEffect::getManifest() { send->setName(QObject::tr("Send")); send->setShortName(QObject::tr("Send")); send->setDescription(QObject::tr( - "How much of the signal to send into the delay buffer")); + "How much of the signal to send into the delay buffer\n" + "When the effect unit is in D+W mode, keep this turned up all the way")); send->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); send->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); send->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); @@ -134,7 +135,8 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); EchoGroupState& gs = *pGroupState; @@ -184,6 +186,8 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr bufferParameters.framesPerBuffer(); const CSAMPLE_GAIN feedback_start = gs.prev_feedback + feedback_delta; + const bool addDry = mixMode == EffectChainMixMode::DrySlashWet; + //TODO: rewrite to remove assumption of stereo buffer for (unsigned int i = 0; i < bufferParameters.samplesPerBuffer(); @@ -221,19 +225,19 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr if (gs.ping_pong < delay_samples / 2) { // Left sample plus a fraction of the right sample, normalized // by 1 + fraction. - pOutput[i] = pInput[i] + + pOutput[i] = (addDry ? pInput[i] : 0) + ((bufferedSampleLeft + bufferedSampleRight * pingpong_frac) / (1 + pingpong_frac)); // Right sample reduced by (1 - fraction) - pOutput[i + 1] = pInput[i + 1] + + pOutput[i + 1] = (addDry ? pInput[i + 1] : 0) + (bufferedSampleRight * (1 - pingpong_frac)); } else { // Left sample reduced by (1 - fraction) - pOutput[i] = pInput[i] + + pOutput[i] = (addDry ? pInput[i] : 0) + (bufferedSampleLeft * (1 - pingpong_frac)); // Right sample plus fraction of left sample, normalized by // 1 + fraction - pOutput[i + 1] = pInput[i + 1] + + pOutput[i + 1] = (addDry ? pInput[i + 1] : 0) + ((bufferedSampleRight + bufferedSampleLeft * pingpong_frac) / (1 + pingpong_frac)); } diff --git a/src/effects/builtin/echoeffect.h b/src/effects/builtin/echoeffect.h index e49227b0dd04..3c764a427749 100644 --- a/src/effects/builtin/echoeffect.h +++ b/src/effects/builtin/echoeffect.h @@ -58,7 +58,8 @@ class EchoEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) override; + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) override; private: QString debugString() const { diff --git a/src/effects/builtin/filtereffect.cpp b/src/effects/builtin/filtereffect.cpp index aece10b9a065..2cf18985d246 100644 --- a/src/effects/builtin/filtereffect.cpp +++ b/src/effects/builtin/filtereffect.cpp @@ -100,9 +100,11 @@ void FilterEffect::processChannel(const ChannelHandle& handle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); Q_UNUSED(groupFeatures); + Q_UNUSED(mixMode); double hpf; double lpf; diff --git a/src/effects/builtin/filtereffect.h b/src/effects/builtin/filtereffect.h index 2d96226c8d16..1566c66ffd1e 100644 --- a/src/effects/builtin/filtereffect.h +++ b/src/effects/builtin/filtereffect.h @@ -41,7 +41,8 @@ class FilterEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE *pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode); private: QString debugString() const { diff --git a/src/effects/builtin/flangereffect.cpp b/src/effects/builtin/flangereffect.cpp index a4e39d709dd3..04e18df73458 100644 --- a/src/effects/builtin/flangereffect.cpp +++ b/src/effects/builtin/flangereffect.cpp @@ -134,8 +134,10 @@ void FlangerEffect::processChannel(const ChannelHandle& handle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); + Q_UNUSED(mixMode); double lfoPeriodParameter = m_pSpeedParameter->value(); double lfoPeriodFrames; diff --git a/src/effects/builtin/flangereffect.h b/src/effects/builtin/flangereffect.h index f87b2b30ef34..15b44bf9e660 100644 --- a/src/effects/builtin/flangereffect.h +++ b/src/effects/builtin/flangereffect.h @@ -61,7 +61,8 @@ class FlangerEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode); private: QString debugString() const { diff --git a/src/effects/builtin/graphiceqeffect.cpp b/src/effects/builtin/graphiceqeffect.cpp index d73ea07c71f4..4dee33de8bf6 100644 --- a/src/effects/builtin/graphiceqeffect.cpp +++ b/src/effects/builtin/graphiceqeffect.cpp @@ -150,9 +150,11 @@ void GraphicEQEffect::processChannel(const ChannelHandle& handle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); Q_UNUSED(groupFeatures); + Q_UNUSED(mixMode); // If the sample rate has changed, initialize the filters using the new // sample rate diff --git a/src/effects/builtin/graphiceqeffect.h b/src/effects/builtin/graphiceqeffect.h index 673f6efe889a..284ef681502a 100644 --- a/src/effects/builtin/graphiceqeffect.h +++ b/src/effects/builtin/graphiceqeffect.h @@ -44,7 +44,8 @@ class GraphicEQEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE *pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatureState); + const GroupFeatureState& groupFeatureState, + const EffectChainMixMode mixMode); private: QString debugString() const { diff --git a/src/effects/builtin/linkwitzriley8eqeffect.cpp b/src/effects/builtin/linkwitzriley8eqeffect.cpp index 61ee64b4018e..ea3f5b9d02b2 100644 --- a/src/effects/builtin/linkwitzriley8eqeffect.cpp +++ b/src/effects/builtin/linkwitzriley8eqeffect.cpp @@ -87,9 +87,11 @@ void LinkwitzRiley8EQEffect::processChannel(const ChannelHandle& handle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); Q_UNUSED(groupFeatures); + Q_UNUSED(mixMode); float fLow = 0.f, fMid = 0.f, fHigh = 0.f; if (!m_pKillLow->toBool()) { diff --git a/src/effects/builtin/linkwitzriley8eqeffect.h b/src/effects/builtin/linkwitzriley8eqeffect.h index 5cbd72966066..3fa6f53a13be 100644 --- a/src/effects/builtin/linkwitzriley8eqeffect.h +++ b/src/effects/builtin/linkwitzriley8eqeffect.h @@ -53,7 +53,8 @@ class LinkwitzRiley8EQEffect : public EffectProcessorImplm_oldFilterGainDb; double gain = pState->m_oldGain; diff --git a/src/effects/builtin/loudnesscontoureffect.h b/src/effects/builtin/loudnesscontoureffect.h index ccff153543f2..573d44c87a58 100644 --- a/src/effects/builtin/loudnesscontoureffect.h +++ b/src/effects/builtin/loudnesscontoureffect.h @@ -47,7 +47,8 @@ class LoudnessContourEffect const CSAMPLE* pInput, CSAMPLE *pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatureState); + const GroupFeatureState& groupFeatureState, + const EffectChainMixMode mixMode); private: LoudnessContourEffect(const LoudnessContourEffect&) = delete; diff --git a/src/effects/builtin/metronomeeffect.cpp b/src/effects/builtin/metronomeeffect.cpp index 9bcc956b8c9d..1bbed1d5076c 100644 --- a/src/effects/builtin/metronomeeffect.cpp +++ b/src/effects/builtin/metronomeeffect.cpp @@ -66,8 +66,10 @@ void MetronomeEffect::processChannel( const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); + Q_UNUSED(mixMode); Q_UNUSED(pInput); MetronomeGroupState* gs = pGroupState; diff --git a/src/effects/builtin/metronomeeffect.h b/src/effects/builtin/metronomeeffect.h index 8624cc4791fa..025d28c3459b 100644 --- a/src/effects/builtin/metronomeeffect.h +++ b/src/effects/builtin/metronomeeffect.h @@ -39,7 +39,8 @@ class MetronomeEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode); private: EngineEffectParameter* m_pBpmParameter; EngineEffectParameter* m_pSyncParameter; diff --git a/src/effects/builtin/moogladder4filtereffect.cpp b/src/effects/builtin/moogladder4filtereffect.cpp index bcb521c6ee1c..31d842c4cced 100644 --- a/src/effects/builtin/moogladder4filtereffect.cpp +++ b/src/effects/builtin/moogladder4filtereffect.cpp @@ -102,9 +102,11 @@ void MoogLadder4FilterEffect::processChannel( const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); Q_UNUSED(groupFeatures); + Q_UNUSED(mixMode); double resonance = m_pResonance->value(); diff --git a/src/effects/builtin/moogladder4filtereffect.h b/src/effects/builtin/moogladder4filtereffect.h index d540aa3868d2..7fb7b8aa3d2e 100644 --- a/src/effects/builtin/moogladder4filtereffect.h +++ b/src/effects/builtin/moogladder4filtereffect.h @@ -41,7 +41,8 @@ class MoogLadder4FilterEffect : public EffectProcessorImplclear(); diff --git a/src/effects/builtin/phasereffect.h b/src/effects/builtin/phasereffect.h index c85b59a5dc31..c70ea5b726ae 100644 --- a/src/effects/builtin/phasereffect.h +++ b/src/effects/builtin/phasereffect.h @@ -53,7 +53,8 @@ class PhaserEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode); private: QString debugString() const { diff --git a/src/effects/builtin/reverbeffect.cpp b/src/effects/builtin/reverbeffect.cpp index bd198fa5c445..68e3fbfc4f8f 100644 --- a/src/effects/builtin/reverbeffect.cpp +++ b/src/effects/builtin/reverbeffect.cpp @@ -64,7 +64,10 @@ EffectManifestPointer ReverbEffect::getManifest() { send->setName(QObject::tr("Send")); send->setShortName(QObject::tr("Send")); send->setDescription(QObject::tr( - "How much of the signal to send to the effect")); + "How much of the signal to send in to the effect\n" + "Lowering this fades out the effect smoothly\n" + "Use this to adjust the amount of the effect when the effect unit is in D/W mode\n" + "When the effect unit is in D+W mode, keep this turned up all the way")); send->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); send->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); send->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); @@ -73,6 +76,22 @@ EffectManifestPointer ReverbEffect::getManifest() { send->setMinimum(0); send->setDefault(0); send->setMaximum(1); + + EffectManifestParameterPointer dryWet = pManifest->addParameter(); + dryWet->setId("dry_wet"); + dryWet->setName(QObject::tr("Dry/Wet")); + dryWet->setShortName(QObject::tr("Dry/Wet")); + dryWet->setDescription(QObject::tr( + "Mix between the input (dry) and output (wet) of the effect\n" + "Lowering this fades out the effect abruptly\n" + "Use this to adjust the amount of the effect when the effect unit is in D+W mode")); + dryWet->setControlHint(EffectManifestParameter::ControlHint::KNOB_LINEAR); + dryWet->setSemanticHint(EffectManifestParameter::SemanticHint::UNKNOWN); + dryWet->setUnitsHint(EffectManifestParameter::UnitsHint::UNKNOWN); + dryWet->setMinimum(0); + dryWet->setDefault(1); + dryWet->setMaximum(1); + return pManifest; } @@ -80,7 +99,8 @@ ReverbEffect::ReverbEffect(EngineEffect* pEffect) : m_pDecayParameter(pEffect->getParameterById("decay")), m_pBandWidthParameter(pEffect->getParameterById("bandwidth")), m_pDampingParameter(pEffect->getParameterById("damping")), - m_pSendParameter(pEffect->getParameterById("send_amount")) { + m_pSendParameter(pEffect->getParameterById("send_amount")), + m_pDryWetParameter(pEffect->getParameterById("dry_wet")) { } ReverbEffect::~ReverbEffect() { @@ -92,9 +112,11 @@ void ReverbEffect::processChannel(const ChannelHandle& handle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); Q_UNUSED(groupFeatures); + Q_UNUSED(mixMode); if (!pState || !m_pDecayParameter || !m_pBandWidthParameter || !m_pDampingParameter || !m_pSendParameter) { qWarning() << "Could not retrieve all effect parameters"; @@ -105,6 +127,7 @@ void ReverbEffect::processChannel(const ChannelHandle& handle, const auto bandwidth = m_pBandWidthParameter->value(); const auto damping = m_pDampingParameter->value(); const auto send = m_pSendParameter->value(); + const double wet = m_pDryWetParameter->value(); // Reinitialize the effect when turning it on to prevent replaying the old buffer // from the last time the effect was enabled. @@ -116,5 +139,5 @@ void ReverbEffect::processChannel(const ChannelHandle& handle, } pState->reverb.processBuffer(pInput, pOutput, bufferParameters.samplesPerBuffer(), - bandwidth, decay, damping, send); + bandwidth, decay, damping, send, wet); } diff --git a/src/effects/builtin/reverbeffect.h b/src/effects/builtin/reverbeffect.h index 4e9abdd2025e..a938e88231ef 100644 --- a/src/effects/builtin/reverbeffect.h +++ b/src/effects/builtin/reverbeffect.h @@ -44,7 +44,8 @@ class ReverbEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode); private: QString debugString() const { @@ -55,6 +56,7 @@ class ReverbEffect : public EffectProcessorImpl { EngineEffectParameter* m_pBandWidthParameter; EngineEffectParameter* m_pDampingParameter; EngineEffectParameter* m_pSendParameter; + EngineEffectParameter* m_pDryWetParameter; DISALLOW_COPY_AND_ASSIGN(ReverbEffect); }; diff --git a/src/effects/builtin/threebandbiquadeqeffect.cpp b/src/effects/builtin/threebandbiquadeqeffect.cpp index c7c112c8bbf6..29f00a66ebb9 100644 --- a/src/effects/builtin/threebandbiquadeqeffect.cpp +++ b/src/effects/builtin/threebandbiquadeqeffect.cpp @@ -145,9 +145,11 @@ void ThreeBandBiquadEQEffect::processChannel( CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(handle); Q_UNUSED(groupFeatures); + Q_UNUSED(mixMode); if (pState->m_oldSampleRate != bufferParameters.sampleRate() || (pState->m_loFreqCorner != m_pLoFreqCorner->get()) || diff --git a/src/effects/builtin/threebandbiquadeqeffect.h b/src/effects/builtin/threebandbiquadeqeffect.h index d08d87286c15..1e141eec0c03 100644 --- a/src/effects/builtin/threebandbiquadeqeffect.h +++ b/src/effects/builtin/threebandbiquadeqeffect.h @@ -58,7 +58,8 @@ class ThreeBandBiquadEQEffect : public EffectProcessorImplvalue(); const double smooth = m_pWaveformParameter->value(); diff --git a/src/effects/builtin/tremoloeffect.h b/src/effects/builtin/tremoloeffect.h index 2704aad17368..a2e2fa402faf 100644 --- a/src/effects/builtin/tremoloeffect.h +++ b/src/effects/builtin/tremoloeffect.h @@ -33,7 +33,8 @@ class TremoloEffect : public EffectProcessorImpl { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) override; + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) override; private: QString debugString() const { diff --git a/src/effects/defs.h b/src/effects/defs.h index 1db1f3388e22..ffb9d8d6b952 100644 --- a/src/effects/defs.h +++ b/src/effects/defs.h @@ -26,11 +26,10 @@ inline uint qHash(SignalProcessingStage stage) { return static_cast(stage); }; -enum class EffectChainInsertionType { - Insert = 0, - Send, - // The number of insertion types. Also used to represent "unknown". - Num_Insertion_Types +enum class EffectChainMixMode { + DrySlashWet = 0, + DryPlusWet, + NumMixModes // The number of mix modes. Also used to represent "unknown". }; constexpr int kNumEffectsPerUnit = 4; diff --git a/src/effects/effectchain.cpp b/src/effects/effectchain.cpp index 45277970f116..9eec7a17f347 100644 --- a/src/effects/effectchain.cpp +++ b/src/effects/effectchain.cpp @@ -20,7 +20,7 @@ EffectChain::EffectChain(EffectsManager* pEffectsManager, const QString& id, m_bEnabled(true), m_id(id), m_name(""), - m_insertionType(EffectChainInsertionType::Insert), + m_mixMode(EffectChainMixMode::DrySlashWet), m_dMix(0), m_pEngineEffectChain(nullptr), m_bAddedToEngine(false) { @@ -240,14 +240,14 @@ void EffectChain::setMix(const double& dMix) { emit(mixChanged(dMix)); } -EffectChainInsertionType EffectChain::insertionType() const { - return m_insertionType; +EffectChainMixMode EffectChain::mixMode() const { + return m_mixMode; } -void EffectChain::setInsertionType(EffectChainInsertionType insertionType) { - m_insertionType = insertionType; +void EffectChain::setMixMode(EffectChainMixMode mixMode) { + m_mixMode = mixMode; sendParameterUpdate(); - emit(insertionTypeChanged(insertionType)); + emit(mixModeChanged(mixMode)); } void EffectChain::addEffect(EffectPointer pEffect) { @@ -327,7 +327,7 @@ void EffectChain::sendParameterUpdate() { pRequest->type = EffectsRequest::SET_EFFECT_CHAIN_PARAMETERS; pRequest->pTargetChain = m_pEngineEffectChain; pRequest->SetEffectChainParameters.enabled = m_bEnabled; - pRequest->SetEffectChainParameters.insertion_type = m_insertionType; + pRequest->SetEffectChainParameters.mix_mode = m_mixMode; pRequest->SetEffectChainParameters.mix = m_dMix; m_pEffectsManager->writeRequest(pRequest); } @@ -346,15 +346,15 @@ EffectChainPointer EffectChain::createFromXml(EffectsManager* pEffectsManager, EffectXml::ChainName); QString description = XmlParse::selectNodeQString(element, EffectXml::ChainDescription); - QString insertionTypeStr = XmlParse::selectNodeQString(element, - EffectXml::ChainInsertionType); + QString mixModeStr = XmlParse::selectNodeQString(element, + EffectXml::ChainMixMode); EffectChainPointer pChain(new EffectChain(pEffectsManager, id)); pChain->setName(name); pChain->setDescription(description); - EffectChainInsertionType insertionType = insertionTypeFromString(insertionTypeStr); - if (insertionType != EffectChainInsertionType::Num_Insertion_Types) { - pChain->setInsertionType(insertionType); + EffectChainMixMode mixMode = mixModeFromString(mixModeStr); + if (mixMode != EffectChainMixMode::NumMixModes) { + pChain->setMixMode(mixMode); } QDomElement effects = XmlParse::selectElement(element, EffectXml::EffectsRoot); diff --git a/src/effects/effectchain.h b/src/effects/effectchain.h index ad5243f69b4d..6b074ffa2a48 100644 --- a/src/effects/effectchain.h +++ b/src/effects/effectchain.h @@ -57,28 +57,28 @@ class EffectChain : public QObject { double mix() const; void setMix(const double& dMix); - static QString insertionTypeToString(EffectChainInsertionType type) { + static QString mixModeToString(EffectChainMixMode type) { switch (type) { - case EffectChainInsertionType::Insert: - return "INSERT"; - case EffectChainInsertionType::Send: - return "SEND"; + case EffectChainMixMode::DrySlashWet: + return "DRY/WET"; + case EffectChainMixMode::DryPlusWet: + return "DRY+WET"; default: return "UNKNOWN"; } } - static EffectChainInsertionType insertionTypeFromString(const QString& typeStr) { - if (typeStr == "INSERT") { - return EffectChainInsertionType::Insert; - } else if (typeStr == "SEND") { - return EffectChainInsertionType::Send; + static EffectChainMixMode mixModeFromString(const QString& typeStr) { + if (typeStr == "DRY/WET") { + return EffectChainMixMode::DrySlashWet; + } else if (typeStr == "DRY+WET") { + return EffectChainMixMode::DryPlusWet; } else { - return EffectChainInsertionType::Num_Insertion_Types; + return EffectChainMixMode::NumMixModes; } } - EffectChainInsertionType insertionType() const; - void setInsertionType(EffectChainInsertionType type); + EffectChainMixMode mixMode() const; + void setMixMode(EffectChainMixMode type); void addEffect(EffectPointer pEffect); void replaceEffect(unsigned int effectSlotNumber, EffectPointer pEffect); @@ -101,7 +101,7 @@ class EffectChain : public QObject { void descriptionChanged(const QString& name); void enabledChanged(bool enabled); void mixChanged(double v); - void insertionTypeChanged(EffectChainInsertionType type); + void mixModeChanged(EffectChainMixMode type); void channelStatusChanged(const QString& group, bool enabled); private: @@ -118,7 +118,7 @@ class EffectChain : public QObject { QString m_id; QString m_name; QString m_description; - EffectChainInsertionType m_insertionType; + EffectChainMixMode m_mixMode; double m_dMix; QSet m_enabledInputChannels; diff --git a/src/effects/effectchainslot.cpp b/src/effects/effectchainslot.cpp index b908e3b918f4..a9205d955514 100644 --- a/src/effects/effectchainslot.cpp +++ b/src/effects/effectchainslot.cpp @@ -49,11 +49,11 @@ EffectChainSlot::EffectChainSlot(EffectRack* pRack, const QString& group, m_pControlChainSuperParameter->set(0.0); m_pControlChainSuperParameter->setDefaultValue(0.0); - m_pControlChainInsertionType = new ControlPushButton(ConfigKey(m_group, "insertion_type")); - m_pControlChainInsertionType->setButtonMode(ControlPushButton::TOGGLE); - m_pControlChainInsertionType->setStates(static_cast(EffectChainInsertionType::Num_Insertion_Types)); - connect(m_pControlChainInsertionType, SIGNAL(valueChanged(double)), - this, SLOT(slotControlChainInsertionType(double))); + m_pControlChainMixMode = new ControlPushButton(ConfigKey(m_group, "mix_mode")); + m_pControlChainMixMode->setButtonMode(ControlPushButton::TOGGLE); + m_pControlChainMixMode->setStates(static_cast(EffectChainMixMode::NumMixModes)); + connect(m_pControlChainMixMode, SIGNAL(valueChanged(double)), + this, SLOT(slotControlChainMixMode(double))); m_pControlChainNextPreset = new ControlPushButton(ConfigKey(m_group, "next_chain")); connect(m_pControlChainNextPreset, SIGNAL(valueChanged(double)), @@ -98,7 +98,7 @@ EffectChainSlot::~EffectChainSlot() { delete m_pControlChainEnabled; delete m_pControlChainMix; delete m_pControlChainSuperParameter; - delete m_pControlChainInsertionType; + delete m_pControlChainMixMode; delete m_pControlChainPrevPreset; delete m_pControlChainNextPreset; delete m_pControlChainSelector; @@ -149,8 +149,8 @@ void EffectChainSlot::slotChainMixChanged(double mix) { emit(updated()); } -void EffectChainSlot::slotChainInsertionTypeChanged(EffectChainInsertionType type) { - m_pControlChainInsertionType->set(static_cast(type)); +void EffectChainSlot::slotChainMixModeChanged(EffectChainMixMode mixMode) { + m_pControlChainMixMode->set(static_cast(mixMode)); emit(updated()); } @@ -210,14 +210,14 @@ void EffectChainSlot::loadEffectChainToSlot(EffectChainPointer pEffectChain) { this, SLOT(slotChainEnabledChanged(bool))); connect(m_pEffectChain.data(), SIGNAL(mixChanged(double)), this, SLOT(slotChainMixChanged(double))); - connect(m_pEffectChain.data(), SIGNAL(insertionTypeChanged(EffectChainInsertionType)), - this, SLOT(slotChainInsertionTypeChanged(EffectChainInsertionType))); + connect(m_pEffectChain.data(), SIGNAL(mixModeChanged(EffectChainMixMode)), + this, SLOT(slotChainMixModeChanged(EffectChainMixMode))); connect(m_pEffectChain.data(), SIGNAL(channelStatusChanged(const QString&, bool)), this, SLOT(slotChainChannelStatusChanged(const QString&, bool))); m_pControlChainLoaded->forceSet(true); - m_pControlChainInsertionType->set( - static_cast(m_pEffectChain->insertionType())); + m_pControlChainMixMode->set( + static_cast(m_pEffectChain->mixMode())); // Mix and enabled channels are persistent properties of the chain slot, // not of the chain. Propagate the current settings to the chain. @@ -279,8 +279,8 @@ void EffectChainSlot::clear() { } m_pControlNumEffects->forceSet(0.0); m_pControlChainLoaded->forceSet(0.0); - m_pControlChainInsertionType->set( - static_cast(EffectChainInsertionType::Insert)); + m_pControlChainMixMode->set( + static_cast(EffectChainMixMode::DrySlashWet)); emit(updated()); } @@ -396,12 +396,12 @@ void EffectChainSlot::slotControlChainSuperParameter(double v, bool force) { } } -void EffectChainSlot::slotControlChainInsertionType(double v) { +void EffectChainSlot::slotControlChainMixMode(double v) { // Intermediate cast to integer is needed for VC++. - EffectChainInsertionType type = static_cast(int(v)); + EffectChainMixMode type = static_cast(int(v)); (void)v; // this avoids a false warning with g++ 4.8.1 - if (m_pEffectChain && type < EffectChainInsertionType::Num_Insertion_Types) { - m_pEffectChain->setInsertionType(type); + if (m_pEffectChain && type < EffectChainMixMode::NumMixModes) { + m_pEffectChain->setMixMode(type); } } @@ -459,10 +459,10 @@ QDomElement EffectChainSlot::toXml(QDomDocument* doc) const { m_pEffectChain->name()); XmlParse::addElement(*doc, chainElement, EffectXml::ChainDescription, m_pEffectChain->description()); - XmlParse::addElement(*doc, chainElement, EffectXml::ChainInsertionType, - EffectChain::insertionTypeToString( - static_cast( - static_cast(m_pControlChainInsertionType->get())))); + XmlParse::addElement(*doc, chainElement, EffectXml::ChainMixMode, + EffectChain::mixModeToString( + static_cast( + static_cast(m_pControlChainMixMode->get())))); XmlParse::addElement(*doc, chainElement, EffectXml::ChainSuperParameter, QString::number(m_pControlChainSuperParameter->get())); @@ -488,7 +488,7 @@ void EffectChainSlot::loadChainSlotFromXml(const QDomElement& effectChainElement return; } - // FIXME: insertion type is set in EffectChain::createFromXml + // FIXME: mix mode is set in EffectChain::createFromXml m_pControlChainSuperParameter->set(XmlParse::selectNodeDouble( effectChainElement, diff --git a/src/effects/effectchainslot.h b/src/effects/effectchainslot.h index 10103fa42faf..cc869830fc01 100644 --- a/src/effects/effectchainslot.h +++ b/src/effects/effectchainslot.h @@ -99,7 +99,7 @@ class EffectChainSlot : public QObject { void slotChainNameChanged(const QString& name); void slotChainEnabledChanged(bool enabled); void slotChainMixChanged(double mix); - void slotChainInsertionTypeChanged(EffectChainInsertionType type); + void slotChainMixModeChanged(EffectChainMixMode mixMode); void slotChainChannelStatusChanged(const QString& group, bool enabled); void slotEffectLoaded(EffectPointer pEffect, unsigned int slotNumber); @@ -110,7 +110,7 @@ class EffectChainSlot : public QObject { void slotControlChainEnabled(double v); void slotControlChainMix(double v); void slotControlChainSuperParameter(double v, bool force = false); - void slotControlChainInsertionType(double v); + void slotControlChainMixMode(double v); void slotControlChainSelector(double v); void slotControlChainNextPreset(double v); void slotControlChainPrevPreset(double v); @@ -134,7 +134,7 @@ class EffectChainSlot : public QObject { ControlPushButton* m_pControlChainEnabled; ControlObject* m_pControlChainMix; ControlObject* m_pControlChainSuperParameter; - ControlPushButton* m_pControlChainInsertionType; + ControlPushButton* m_pControlChainMixMode; ControlEncoder* m_pControlChainSelector; ControlPushButton* m_pControlChainNextPreset; ControlPushButton* m_pControlChainPrevPreset; diff --git a/src/effects/effectprocessor.h b/src/effects/effectprocessor.h index b493511aa28b..7e7f768fbdbc 100644 --- a/src/effects/effectprocessor.h +++ b/src/effects/effectprocessor.h @@ -81,7 +81,8 @@ class EffectProcessor { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) = 0; + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) = 0; }; // EffectProcessorImpl manages a separate EffectState for every routing of @@ -135,13 +136,15 @@ class EffectProcessorImpl : public EffectProcessor { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) = 0; + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) = 0; void process(const ChannelHandle& inputHandle, const ChannelHandle& outputHandle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) final { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) final { EffectSpecificState* pState = m_channelStateMatrix[inputHandle][outputHandle]; VERIFY_OR_DEBUG_ASSERT(pState != nullptr) { if (kEffectDebugOutput) { @@ -155,7 +158,7 @@ class EffectProcessorImpl : public EffectProcessor { m_channelStateMatrix[inputHandle][outputHandle] = pState; } processChannel(inputHandle, pState, pInput, pOutput, bufferParameters, - enableState, groupFeatures); + enableState, groupFeatures, mixMode); } void initialize(const QSet& activeInputChannels, diff --git a/src/effects/effectsmanager.cpp b/src/effects/effectsmanager.cpp index 533c7c046b73..506573c150a1 100644 --- a/src/effects/effectsmanager.cpp +++ b/src/effects/effectsmanager.cpp @@ -30,7 +30,7 @@ EffectsManager::EffectsManager(QObject* pParent, UserSettingsPointer pConfig, m_pLoEqFreq(NULL), m_pHiEqFreq(NULL), m_underDestruction(false) { - qRegisterMetaType("EffectChainInsertionType"); + qRegisterMetaType("EffectChainMixMode"); QPair requestPipes = TwoWayMessagePipe::makeTwoWayMessagePipe( kEffectMessagPipeFifoSize, kEffectMessagPipeFifoSize, false, false); diff --git a/src/effects/effectxmlelements.h b/src/effects/effectxmlelements.h index 68b90ad42bf5..03c373efc6ec 100644 --- a/src/effects/effectxmlelements.h +++ b/src/effects/effectxmlelements.h @@ -15,7 +15,7 @@ const QString ChainSuperParameter("SuperParameterValue"); const QString ChainId("Id"); const QString ChainName("Name"); const QString ChainDescription("Description"); -const QString ChainInsertionType("InsertionType"); +const QString ChainMixMode("MixMode"); const QString EffectsRoot("Effects"); const QString Effect("Effect"); diff --git a/src/effects/lv2/lv2effectprocessor.cpp b/src/effects/lv2/lv2effectprocessor.cpp index 16fb6336b8cb..4e1d1c89d073 100644 --- a/src/effects/lv2/lv2effectprocessor.cpp +++ b/src/effects/lv2/lv2effectprocessor.cpp @@ -94,9 +94,11 @@ void LV2EffectProcessor::process(const ChannelHandle& inputHandle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { Q_UNUSED(groupFeatures); Q_UNUSED(enableState); + Q_UNUSED(mixMode); LV2EffectGroupState* pState = m_channelStateMatrix[inputHandle][outputHandle]; VERIFY_OR_DEBUG_ASSERT(pState != nullptr) { diff --git a/src/effects/lv2/lv2effectprocessor.h b/src/effects/lv2/lv2effectprocessor.h index 3cebc56d12e4..ecff775bb874 100644 --- a/src/effects/lv2/lv2effectprocessor.h +++ b/src/effects/lv2/lv2effectprocessor.h @@ -51,7 +51,8 @@ class LV2EffectProcessor : public EffectProcessor { const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures) override; + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) override; private: LV2EffectGroupState* createGroupState(const mixxx::EngineParameters& bufferParameters); diff --git a/src/engine/effects/engineeffect.cpp b/src/engine/effects/engineeffect.cpp index 8fccbb7740e1..2937427deae4 100644 --- a/src/engine/effects/engineeffect.cpp +++ b/src/engine/effects/engineeffect.cpp @@ -142,7 +142,8 @@ bool EngineEffect::process(const ChannelHandle& inputHandle, const unsigned int numSamples, const unsigned int sampleRate, const EffectEnableState chainEnableState, - const GroupFeatureState& groupFeatures) { + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode) { // Compute the effective enable state from the combination of the effect's state // for the channel and the state passed from the EngineEffectChain. @@ -196,7 +197,7 @@ bool EngineEffect::process(const ChannelHandle& inputHandle, m_pProcessor->process(inputHandle, outputHandle, pInput, pOutput, bufferParameters, - effectiveEffectEnableState, groupFeatures); + effectiveEffectEnableState, groupFeatures, mixMode); processingOccured = true; diff --git a/src/engine/effects/engineeffect.h b/src/engine/effects/engineeffect.h index 06736f81e60d..87c6d4314814 100644 --- a/src/engine/effects/engineeffect.h +++ b/src/engine/effects/engineeffect.h @@ -48,7 +48,8 @@ class EngineEffect : public EffectsRequestHandler { const unsigned int numSamples, const unsigned int sampleRate, const EffectEnableState chainEnableState, - const GroupFeatureState& groupFeatures); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode); private: QString debugString() const { diff --git a/src/engine/effects/engineeffectchain.cpp b/src/engine/effects/engineeffectchain.cpp index 55a626bee0e7..8482e2fcc62e 100644 --- a/src/engine/effects/engineeffectchain.cpp +++ b/src/engine/effects/engineeffectchain.cpp @@ -9,7 +9,7 @@ EngineEffectChain::EngineEffectChain(const QString& id, const QSet& registeredOutputChannels) : m_id(id), m_enableState(EffectEnableState::Enabled), - m_insertionType(EffectChainInsertionType::Insert), + m_mixMode(EffectChainMixMode::DrySlashWet), m_dMix(0), m_buffer1(MAX_BUFFER_LEN), m_buffer2(MAX_BUFFER_LEN) { @@ -76,7 +76,7 @@ bool EngineEffectChain::removeEffect(EngineEffect* pEffect, int iIndex) { // this is called from the engine thread onCallbackStart() bool EngineEffectChain::updateParameters(const EffectsRequest& message) { // TODO(rryan): Parameter interpolation. - m_insertionType = message.SetEffectChainParameters.insertion_type; + m_mixMode = message.SetEffectChainParameters.mix_mode; m_dMix = message.SetEffectChainParameters.mix; if (m_enableState != EffectEnableState::Disabled && !message.SetEffectParameters.enabled) { @@ -252,8 +252,8 @@ bool EngineEffectChain::process(const ChannelHandle& inputHandle, } } - CSAMPLE currentWetGain = m_dMix; - CSAMPLE lastCallbackWetGain = channelStatus.old_gain; + CSAMPLE currentMixKnob = m_dMix; + CSAMPLE lastCallbackMixKnob = channelStatus.old_gain; bool processingOccured = false; if (effectiveChainEnableState != EffectEnableState::Disabled) { @@ -276,7 +276,8 @@ bool EngineEffectChain::process(const ChannelHandle& inputHandle, if (pEffect->process(inputHandle, outputHandle, pIntermediateInput, pIntermediateOutput, numSamples, sampleRate, - effectiveChainEnableState, groupFeatures)) { + effectiveChainEnableState, groupFeatures, + m_mixMode)) { processingOccured = true; // Output of this effect becomes the input of the next effect pIntermediateInput = pIntermediateOutput; @@ -287,25 +288,25 @@ bool EngineEffectChain::process(const ChannelHandle& inputHandle, if (processingOccured) { // pIntermediateInput is the output of the last processed effect. It would be the // intermediate input of the next effect if there was one. - if (m_insertionType == EffectChainInsertionType::Insert) { - // INSERT mode: output = input * (1-wet) + effect(input) * wet + if (m_mixMode == EffectChainMixMode::DrySlashWet) { + // Dry/Wet mode: output = (input * (1-mix knob)) + (wet * mix knob) SampleUtil::copy2WithRampingGain( pOut, - pIn, 1.0 - lastCallbackWetGain, 1.0 - currentWetGain, - pIntermediateInput, lastCallbackWetGain, currentWetGain, + pIn, 1.0 - lastCallbackMixKnob, 1.0 - currentMixKnob, + pIntermediateInput, lastCallbackMixKnob, currentMixKnob, numSamples); } else { - // SEND mode: output = input + effect(input) * wet + // Dry+Wet mode: output = input + (wet * mix knob) SampleUtil::copy2WithRampingGain( pOut, pIn, 1.0, 1.0, - pIntermediateInput, lastCallbackWetGain, currentWetGain, + pIntermediateInput, lastCallbackMixKnob, currentMixKnob, numSamples); } } } - channelStatus.old_gain = currentWetGain; + channelStatus.old_gain = currentMixKnob; // If the EffectProcessors have been sent a signal for the intermediate // enabling/disabling state, set the channel state or chain state diff --git a/src/engine/effects/engineeffectchain.h b/src/engine/effects/engineeffectchain.h index 079b6b96b2aa..8c984281fcdb 100644 --- a/src/engine/effects/engineeffectchain.h +++ b/src/engine/effects/engineeffectchain.h @@ -70,7 +70,7 @@ class EngineEffectChain : public EffectsRequestHandler { QString m_id; EffectEnableState m_enableState; - EffectChainInsertionType m_insertionType; + EffectChainMixMode m_mixMode; CSAMPLE m_dMix; QList m_effects; mixxx::SampleBuffer m_buffer1; diff --git a/src/engine/effects/message.h b/src/engine/effects/message.h index 54b4102e0bf2..08a974ebe5d3 100644 --- a/src/engine/effects/message.h +++ b/src/engine/effects/message.h @@ -136,7 +136,7 @@ struct EffectsRequest { } RemoveEffectFromChain; struct { bool enabled; - EffectChainInsertionType insertion_type; + EffectChainMixMode mix_mode; double mix; } SetEffectChainParameters; struct { diff --git a/src/skin/tooltips.cpp b/src/skin/tooltips.cpp index 785ff46cb11c..0874a64454e7 100644 --- a/src/skin/tooltips.cpp +++ b/src/skin/tooltips.cpp @@ -727,19 +727,25 @@ void Tooltips::addStandardTooltips() { << tr("Toggle Unit") << tr("Enable or disable this whole effect unit."); add("EffectUnit_mix") - << tr("Dry/Wet") - << tr("Adjust the balance between the original (dry) and processed (wet) signal for the whole effect unit.") + << tr("Mix") + << tr("Adjust the mixing of the dry (input) signal with the wet (output) signal of the effect unit") + << tr("D/W mode: Crossfade between dry and wet") + << tr("D+W mode: Add wet to dry") << QString("%1: %2").arg(rightClick, resetToDefault); + add("EffectUnit_mix_mode") + << tr("Mix Mode") + << tr("Adjust how the dry (input) signal is mixed with the wet (output) signal of the effect unit") + "\n" + << tr("D/W mode: Mix knob crossfades between dry and wet\n" + "Use this to change the sound of the track with EQ and filter effects.") + "\n" + << tr("D+W mode: Mix knob adds wet to dry\n" + "Use this to change only the effected (wet) signal with EQ and filter effects."); + add("EffectUnit_super1") << tr("Super Knob") << tr("Controls the Meta Knob of all effects in this unit together.") << QString("%1: %2").arg(rightClick, resetToDefault); - add("EffectUnit_insertion_type") - << tr("Insert/Send Toggle") - << tr("Insert/Send Toggle"); - add("EffectUnit_next_chain") << tr("Next Chain") << tr("Load next effect chain preset into this effect unit."); diff --git a/src/test/baseeffecttest.h b/src/test/baseeffecttest.h index 0102f5fc8dd6..d84c114bc128 100644 --- a/src/test/baseeffecttest.h +++ b/src/test/baseeffecttest.h @@ -41,13 +41,14 @@ class MockEffectProcessor : public EffectProcessor { MOCK_METHOD2(loadStatesForInputChannel, bool(const ChannelHandle* inputChannel, const EffectStatesMap* pStatesMap)); MOCK_METHOD1(deleteStatesForInputChannel, void(const ChannelHandle* inputChannel)); - MOCK_METHOD7(process, void(const ChannelHandle& inputHandle, + MOCK_METHOD8(process, void(const ChannelHandle& inputHandle, const ChannelHandle& outputHandle, const CSAMPLE* pInput, CSAMPLE* pOutput, const mixxx::EngineParameters& bufferParameters, const EffectEnableState enableState, - const GroupFeatureState& groupFeatures)); + const GroupFeatureState& groupFeatures, + const EffectChainMixMode mixMode)); }; diff --git a/src/test/effectchainslottest.cpp b/src/test/effectchainslottest.cpp index 47fd7c6de22b..9169e8943fed 100644 --- a/src/test/effectchainslottest.cpp +++ b/src/test/effectchainslottest.cpp @@ -64,13 +64,13 @@ TEST_F(EffectChainSlotTest, ChainSlotMirrorsLoadedChain) { ControlObject::set(ConfigKey(group, "mix"), 0.5); EXPECT_DOUBLE_EQ(0.5, pChain->mix()); - pChain->setInsertionType(EffectChainInsertionType::Send); - EXPECT_DOUBLE_EQ(static_cast(pChain->insertionType()), - ControlObject::get(ConfigKey(group, "insertion_type"))); + pChain->setMixMode(EffectChainMixMode::DryPlusWet); + EXPECT_DOUBLE_EQ(static_cast(pChain->mixMode()), + ControlObject::get(ConfigKey(group, "mix_mode"))); - ControlObject::set(ConfigKey(group, "insertion_type"), - static_cast(EffectChainInsertionType::Insert)); - EXPECT_EQ(EffectChainInsertionType::Insert, pChain->insertionType()); + ControlObject::set(ConfigKey(group, "mix_mode"), + static_cast(EffectChainMixMode::DrySlashWet)); + EXPECT_EQ(EffectChainMixMode::DrySlashWet, pChain->mixMode()); EXPECT_FALSE(pChain->enabledForChannel(m_master)); EXPECT_DOUBLE_EQ(0.0, ControlObject::get(ConfigKey(group, "group_[Master]_enable")));