From 37a92aec6318c60eae1a1495b9e84db9c091642d Mon Sep 17 00:00:00 2001 From: jules Date: Fri, 29 Sep 2017 16:28:40 +0100 Subject: [PATCH] Fixed an edge-case error in the LaGrange and Catmull-Rom interpolators when the ratio changes to exactly 1.0 --- .../effects/juce_CatmullRomInterpolator.cpp | 16 ++-- .../effects/juce_LagrangeInterpolator.cpp | 94 +++++++------------ 2 files changed, 40 insertions(+), 70 deletions(-) diff --git a/modules/juce_audio_basics/effects/juce_CatmullRomInterpolator.cpp b/modules/juce_audio_basics/effects/juce_CatmullRomInterpolator.cpp index 3d210938c6..f38b66f956 100644 --- a/modules/juce_audio_basics/effects/juce_CatmullRomInterpolator.cpp +++ b/modules/juce_audio_basics/effects/juce_CatmullRomInterpolator.cpp @@ -27,13 +27,13 @@ struct CatmullRomAlgorithm { static forcedinline float valueAtOffset (const float* const inputs, const float offset) noexcept { - const float y0 = inputs[3]; - const float y1 = inputs[2]; - const float y2 = inputs[1]; - const float y3 = inputs[0]; + auto y0 = inputs[3]; + auto y1 = inputs[2]; + auto y2 = inputs[1]; + auto y3 = inputs[0]; - const float halfY0 = 0.5f * y0; - const float halfY3 = 0.5f * y3; + auto halfY0 = 0.5f * y0; + auto halfY3 = 0.5f * y3; return y1 + offset * ((0.5f * y2 - halfY0) + (offset * (((y0 + 2.0f * y2) - (halfY3 + 2.5f * y1)) @@ -48,8 +48,8 @@ void CatmullRomInterpolator::reset() noexcept { subSamplePos = 1.0; - for (int i = 0; i < numElementsInArray (lastInputSamples); ++i) - lastInputSamples[i] = 0; + for (auto& s : lastInputSamples) + s = 0; } int CatmullRomInterpolator::process (double actualRatio, const float* in, float* out, int numOut) noexcept diff --git a/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp b/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp index eca8e98e62..9488ef9b00 100644 --- a/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp +++ b/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp @@ -49,97 +49,67 @@ namespace } template - static int interpolate (float* lastInputSamples, double& subSamplePos, const double actualRatio, - const float* in, float* out, const int numOut) noexcept + static int interpolate (float* lastInputSamples, double& subSamplePos, double actualRatio, + const float* in, float* out, int numOut) noexcept { - if (actualRatio == 1.0) + auto pos = subSamplePos; + + if (actualRatio == 1.0 && pos == 1.0) { memcpy (out, in, (size_t) numOut * sizeof (float)); pushInterpolationSamples (lastInputSamples, in, numOut); return numOut; } - const float* const originalIn = in; - double pos = subSamplePos; + int numUsed = 0; - if (actualRatio < 1.0) + while (numOut > 0) { - for (int i = numOut; --i >= 0;) + while (pos >= 1.0) { - if (pos >= 1.0) - { - pushInterpolationSample (lastInputSamples, *in++); - pos -= 1.0; - } - - *out++ = InterpolatorType::valueAtOffset (lastInputSamples, (float) pos); - pos += actualRatio; - } - } - else - { - for (int i = numOut; --i >= 0;) - { - while (pos < actualRatio) - { - pushInterpolationSample (lastInputSamples, *in++); - pos += 1.0; - } - - pos -= actualRatio; - *out++ = InterpolatorType::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos)); + pushInterpolationSample (lastInputSamples, in[numUsed++]); + pos -= 1.0; } + + *out++ = InterpolatorType::valueAtOffset (lastInputSamples, (float) pos); + pos += actualRatio; + --numOut; } subSamplePos = pos; - return (int) (in - originalIn); + return numUsed; } template - static int interpolateAdding (float* lastInputSamples, double& subSamplePos, const double actualRatio, - const float* in, float* out, const int numOut, const float gain) noexcept + static int interpolateAdding (float* lastInputSamples, double& subSamplePos, double actualRatio, + const float* in, float* out, int numOut, const float gain) noexcept { - if (actualRatio == 1.0) + auto pos = subSamplePos; + + if (actualRatio == 1.0 && pos == 1.0) { FloatVectorOperations::addWithMultiply (out, in, gain, numOut); pushInterpolationSamples (lastInputSamples, in, numOut); return numOut; } - const float* const originalIn = in; - double pos = subSamplePos; + int numUsed = 0; - if (actualRatio < 1.0) + while (numOut > 0) { - for (int i = numOut; --i >= 0;) + while (pos >= 1.0) { - if (pos >= 1.0) - { - pushInterpolationSample (lastInputSamples, *in++); - pos -= 1.0; - } - - *out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, (float) pos); - pos += actualRatio; - } - } - else - { - for (int i = numOut; --i >= 0;) - { - while (pos < actualRatio) - { - pushInterpolationSample (lastInputSamples, *in++); - pos += 1.0; - } - - pos -= actualRatio; - *out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos)); + pushInterpolationSample (lastInputSamples, in[numUsed++]); + pos -= 1.0; } + + *out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, (float) pos); + pos += actualRatio; + --numOut; } subSamplePos = pos; - return (int) (in - originalIn); + return numUsed; } } @@ -186,8 +156,8 @@ void LagrangeInterpolator::reset() noexcept { subSamplePos = 1.0; - for (int i = 0; i < numElementsInArray (lastInputSamples); ++i) - lastInputSamples[i] = 0; + for (auto& s : lastInputSamples) + s = 0; } int LagrangeInterpolator::process (double actualRatio, const float* in, float* out, int numOut) noexcept