diff --git a/lib/reverb/Reverb.cc b/lib/reverb/Reverb.cc index 07f67998396..38daba6d24f 100644 --- a/lib/reverb/Reverb.cc +++ b/lib/reverb/Reverb.cc @@ -454,7 +454,7 @@ void MixxxPlateX2::processBuffer(const sample_t* in, sample_t* out, const uint f // loop through the buffer, processing each sample for (uint i = 0; i + 1 < frames; i += 2) { - sample_t mono_sample = send.getNext() * (in[i] + in[i + 1]) / 2; + sample_t mono_sample = send.getNth(i / 2) * (in[i] + in[i + 1]) / 2; PlateStub::process(mono_sample, decay, &out[i], &out[i+1]); } } diff --git a/src/effects/builtin/echoeffect.cpp b/src/effects/builtin/echoeffect.cpp index f7ffcc4a0d0..b36124a132d 100644 --- a/src/effects/builtin/echoeffect.cpp +++ b/src/effects/builtin/echoeffect.cpp @@ -191,12 +191,14 @@ void EchoEffect::processChannel(const ChannelHandle& handle, EchoGroupState* pGr pGroupState->prev_feedback, bufferParameters.framesPerBuffer()); + int rampIndex = 0; //TODO: rewrite to remove assumption of stereo buffer for (SINT i = 0; i < bufferParameters.samplesPerBuffer(); i += bufferParameters.channelCount()) { - CSAMPLE_GAIN send_ramped = send.getNext(); - CSAMPLE_GAIN feedback_ramped = feedback.getNext(); + CSAMPLE_GAIN send_ramped = send.getNth(rampIndex); + CSAMPLE_GAIN feedback_ramped = feedback.getNth(rampIndex); + ++rampIndex; CSAMPLE bufferedSampleLeft = pGroupState->delay_buf[read_position]; CSAMPLE bufferedSampleRight = pGroupState->delay_buf[read_position + 1]; diff --git a/src/effects/builtin/flangereffect.cpp b/src/effects/builtin/flangereffect.cpp index 542bd58a1a7..4d255ab1155 100644 --- a/src/effects/builtin/flangereffect.cpp +++ b/src/effects/builtin/flangereffect.cpp @@ -195,13 +195,15 @@ void FlangerEffect::processChannel(const ChannelHandle& handle, CSAMPLE* delayLeft = pState->delayLeft; CSAMPLE* delayRight = pState->delayRight; + int rampIndex = 0; for (SINT i = 0; i < bufferParameters.samplesPerBuffer(); i += bufferParameters.channelCount()) { - CSAMPLE_GAIN mix_ramped = mixRamped.getNext(); - CSAMPLE_GAIN regen_ramped = regenRamped.getNext(); - double width_ramped = widthRamped.getNext(); - double manual_ramped = manualRamped.getNext(); + CSAMPLE_GAIN mix_ramped = mixRamped.getNth(rampIndex); + CSAMPLE_GAIN regen_ramped = regenRamped.getNth(rampIndex); + double width_ramped = widthRamped.getNth(rampIndex); + double manual_ramped = manualRamped.getNth(rampIndex); + ++rampIndex; pState->lfoFrames++; if (pState->lfoFrames >= lfoPeriodFrames) { diff --git a/src/util/rampingvalue.h b/src/util/rampingvalue.h index 367e1cd9c10..e29fe4d5215 100644 --- a/src/util/rampingvalue.h +++ b/src/util/rampingvalue.h @@ -3,16 +3,20 @@ template class RampingValue { public: - RampingValue(const T& initial, const T& final, int steps) { - m_value = initial; - m_increment = (final - initial) / steps; + constexpr RampingValue(const T& initial, const T& final, int steps) + : m_start(initial), + m_increment((final - initial) / steps) { } - - T getNext() { - return m_value += m_increment; + /// this method is supposed to be used in hot audio-processing loops + /// which benefit greatly from vectorization. For this to work, loop- + /// iterations can't have any data-dependencies on each other. If `getNth` + /// were to modify its instance in between iterations, a data-dependency + /// would be introduced, and vectorization made impossible! + [[nodiscard]] constexpr T getNth(int step) const { + return m_start + m_increment * step; } private: - T m_value; + T m_start; T m_increment; };