diff --git a/modules/dsp/chowdsp_compressor/Compressor/chowdsp_LevelDetectorImpls.h b/modules/dsp/chowdsp_compressor/Compressor/chowdsp_LevelDetectorImpls.h index 44c903a94..4c5feb000 100644 --- a/modules/dsp/chowdsp_compressor/Compressor/chowdsp_LevelDetectorImpls.h +++ b/modules/dsp/chowdsp_compressor/Compressor/chowdsp_LevelDetectorImpls.h @@ -24,67 +24,113 @@ BallisticCoeffs computeBallisticCoeffs (T timeMs, T fs) struct PeakDetector { template - static void process (const BufferView& buffer, const BallisticCoeffs& attackCoeffs, const BallisticCoeffs& releaseCoeffs, T* z, T /* thresholdGain */) noexcept + static void process (const BufferView& inBuffer, + const BufferView& outBuffer, + const BallisticCoeffs& attackCoeffs, + const BallisticCoeffs& releaseCoeffs, + T* z, + T /* thresholdGain */) noexcept { - for (auto [ch, data] : buffer_iters::channels (buffer)) + jassert (inBuffer.getNumChannels() == outBuffer.getNumSamples()); + jassert (inBuffer.getNumSamples() == outBuffer.getNumSamples()); + + for (auto [ch, inData, outData] : buffer_iters::zip_channels (inBuffer, outBuffer)) { ScopedValue _z { z[ch] }; - for (auto& x : data) + for (auto [x, y] : zip (inData, outData)) { const auto abs_x = std::abs (x); const auto b0 = abs_x > _z.get() ? attackCoeffs.b0 : releaseCoeffs.b0; _z.get() += b0 * (abs_x - _z.get()); - x = _z.get(); + y = _z.get(); } } } + + template + static void process (const BufferView& buffer, + const BallisticCoeffs& attackCoeffs, + const BallisticCoeffs& releaseCoeffs, + T* z, + T thresholdGain) noexcept + { + process (buffer, buffer, attackCoeffs, releaseCoeffs, z, thresholdGain); + } }; /** A return-to-threshold peak detector */ struct PeakRtTDetector { template - static void process (const BufferView& buffer, const BallisticCoeffs& attackCoeffs, const BallisticCoeffs& releaseCoeffs, T* z, T thresholdGain) noexcept + static void process (const BufferView& inBuffer, + const BufferView& outBuffer, + const BallisticCoeffs& attackCoeffs, + const BallisticCoeffs& releaseCoeffs, + T* z, + T thresholdGain) noexcept { - for (auto [ch, data] : buffer_iters::channels (buffer)) + jassert (inBuffer.getNumChannels() == outBuffer.getNumSamples()); + jassert (inBuffer.getNumSamples() == outBuffer.getNumSamples()); + + for (auto [ch, inData, outData] : buffer_iters::zip_channels (inBuffer, outBuffer)) { ScopedValue _z { z[ch] }; - for (auto& x : data) + for (auto [x, y] : zip (inData, outData)) { const auto abs_x = std::abs (x); const auto b0 = abs_x > _z.get() ? attackCoeffs.b0 : releaseCoeffs.b0; const auto x_eff = abs_x > _z.get() ? abs_x : thresholdGain; _z.get() += b0 * (x_eff - _z.get()); - x = _z.get(); + y = _z.get(); } } } + + template + static void process (const BufferView& buffer, const BallisticCoeffs& attackCoeffs, const BallisticCoeffs& releaseCoeffs, T* z, T thresholdGain) noexcept + { + process (buffer, buffer, attackCoeffs, releaseCoeffs, z, thresholdGain); + } }; /** An RMS level detector */ struct RMSDetector { template - static void process (const BufferView& buffer, const BallisticCoeffs& attackCoeffs, const BallisticCoeffs& releaseCoeffs, T* z, T /* thresholdGain */) noexcept + static void process (const BufferView& inBuffer, + const BufferView& outBuffer, + const BallisticCoeffs& attackCoeffs, + const BallisticCoeffs& releaseCoeffs, + T* z, + T /* thresholdGain */) noexcept { - for (auto [ch, data] : buffer_iters::channels (buffer)) + jassert (inBuffer.getNumChannels() == outBuffer.getNumSamples()); + jassert (inBuffer.getNumSamples() == outBuffer.getNumSamples()); + + for (auto [ch, inData, outData] : buffer_iters::zip_channels (inBuffer, outBuffer)) { ScopedValue _z { z[ch] }; - for (auto& x : data) + for (auto [x, y] : zip (inData, outData)) { const auto sq_x = x * x; const auto& coeffs = sq_x > _z.get() ? attackCoeffs : releaseCoeffs; _z.get() = coeffs.a1 * _z.get() + coeffs.b0 * sq_x; - x = _z.get(); + y = _z.get(); } } - BufferMath::applyFunction (buffer, + BufferMath::applyFunction (outBuffer, [] (auto x) { CHOWDSP_USING_XSIMD_STD (sqrt); return sqrt (x); }); } + + template + static void process (const BufferView& buffer, const BallisticCoeffs& attackCoeffs, const BallisticCoeffs& releaseCoeffs, T* z, T thresholdGain) noexcept + { + process (buffer, buffer, attackCoeffs, releaseCoeffs, z, thresholdGain); + } }; } // namespace chowdsp::compressor