|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2015 - ROLI Ltd.
-
- Permission is granted to use this software under the terms of either:
- a) the GPL v2 (or any later version)
- b) the Affero GPL v3
-
- Details of these licenses can be found at: www.gnu.org/licenses
-
- JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- ------------------------------------------------------------------------------
-
- To release a closed-source product which uses JUCE, commercial licenses are
- available: visit www.juce.com for more information.
-
- ==============================================================================
- */
-
- namespace LagrangeHelpers
- {
- template <int k>
- struct ResampleHelper
- {
- static forcedinline void calc (float& a, float b) { a *= b * (1.0f / k); }
- };
-
- template<>
- struct ResampleHelper <0>
- {
- static forcedinline void calc (float&, float) {}
- };
-
- template <int k>
- static forcedinline float calcCoefficient (float input, const float offset) noexcept
- {
- ResampleHelper <0 - k>::calc (input, -2.0f - offset);
- ResampleHelper <1 - k>::calc (input, -1.0f - offset);
- ResampleHelper <2 - k>::calc (input, 0.0f - offset);
- ResampleHelper <3 - k>::calc (input, 1.0f - offset);
- ResampleHelper <4 - k>::calc (input, 2.0f - offset);
- return input;
- }
-
- static forcedinline float valueAtOffset (const float* const inputs, const float offset) noexcept
- {
- return calcCoefficient<0> (inputs[4], offset)
- + calcCoefficient<1> (inputs[3], offset)
- + calcCoefficient<2> (inputs[2], offset)
- + calcCoefficient<3> (inputs[1], offset)
- + calcCoefficient<4> (inputs[0], offset);
- }
-
- static forcedinline void push (float* inputs, const float newValue) noexcept
- {
- inputs[4] = inputs[3];
- inputs[3] = inputs[2];
- inputs[2] = inputs[1];
- inputs[1] = inputs[0];
- inputs[0] = newValue;
- }
- }
-
- //==============================================================================
- LagrangeInterpolator::LagrangeInterpolator() { reset(); }
- LagrangeInterpolator::~LagrangeInterpolator() {}
-
- void LagrangeInterpolator::reset() noexcept
- {
- subSamplePos = 1.0;
-
- for (int i = 0; i < numElementsInArray (lastInputSamples); ++i)
- lastInputSamples[i] = 0;
- }
-
- int LagrangeInterpolator::process (const double actualRatio, const float* in,
- float* out, const int numOut) noexcept
- {
- if (actualRatio == 1.0)
- {
- memcpy (out, in, (size_t) numOut * sizeof (float));
-
- if (numOut >= 4)
- {
- const float* end = in + numOut;
-
- for (int i = 0; i < 4; ++i)
- lastInputSamples[i] = *--end;
- }
- else
- {
- for (int i = 0; i < numOut; ++i)
- LagrangeHelpers::push (lastInputSamples, in[i]);
- }
-
- return numOut;
- }
-
- const float* const originalIn = in;
- double pos = subSamplePos;
-
- if (actualRatio < 1.0)
- {
- for (int i = numOut; --i >= 0;)
- {
- if (pos >= 1.0)
- {
- LagrangeHelpers::push (lastInputSamples, *in++);
- pos -= 1.0;
- }
-
- *out++ = LagrangeHelpers::valueAtOffset (lastInputSamples, (float) pos);
- pos += actualRatio;
- }
- }
- else
- {
- for (int i = numOut; --i >= 0;)
- {
- while (pos < actualRatio)
- {
- LagrangeHelpers::push (lastInputSamples, *in++);
- pos += 1.0;
- }
-
- pos -= actualRatio;
- *out++ = LagrangeHelpers::valueAtOffset (lastInputSamples, 1.0f - (float) pos);
- }
- }
-
- subSamplePos = pos;
- return (int) (in - originalIn);
- }
-
- int LagrangeInterpolator::processAdding (const double actualRatio, const float* in,
- float* out, const int numOut, const float gain) noexcept
- {
- if (actualRatio == 1.0)
- {
- if (gain != 1.0f)
- {
- for (int i = 0; i < numOut; ++i)
- out[i] += in[i] * gain;
- }
- else
- {
- for (int i = 0; i < numOut; ++i)
- out[i] += in[i];
- }
-
- if (numOut >= 4)
- {
- const float* end = in + numOut;
-
- for (int i = 0; i < 4; ++i)
- lastInputSamples[i] = *--end;
- }
- else
- {
- for (int i = 0; i < numOut; ++i)
- LagrangeHelpers::push (lastInputSamples, in[i]);
- }
-
- return numOut;
- }
-
- const float* const originalIn = in;
- double pos = subSamplePos;
-
- if (actualRatio < 1.0)
- {
- for (int i = numOut; --i >= 0;)
- {
- if (pos >= 1.0)
- {
- LagrangeHelpers::push (lastInputSamples, *in++);
- pos -= 1.0;
- }
-
- *out++ += gain * LagrangeHelpers::valueAtOffset (lastInputSamples, (float) pos);
- pos += actualRatio;
- }
- }
- else
- {
- for (int i = numOut; --i >= 0;)
- {
- while (pos < actualRatio)
- {
- LagrangeHelpers::push (lastInputSamples, *in++);
- pos += 1.0;
- }
-
- pos -= actualRatio;
- *out++ += gain * LagrangeHelpers::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos));
- }
- }
-
- subSamplePos = pos;
- return (int) (in - originalIn);
- }
|