|
|
|
@@ -22,185 +22,179 @@ |
|
|
|
==============================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace LagrangeHelpers
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
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
|
|
|
|
static forcedinline void pushInterpolationSample (float* lastInputSamples, const float newValue) 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;
|
|
|
|
lastInputSamples[4] = lastInputSamples[3];
|
|
|
|
lastInputSamples[3] = lastInputSamples[2];
|
|
|
|
lastInputSamples[2] = lastInputSamples[1];
|
|
|
|
lastInputSamples[1] = lastInputSamples[0];
|
|
|
|
lastInputSamples[0] = newValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
static forcedinline void pushInterpolationSamples (float* lastInputSamples, const float* input, int numOut) noexcept
|
|
|
|
{
|
|
|
|
memcpy (out, in, (size_t) numOut * sizeof (float));
|
|
|
|
|
|
|
|
if (numOut >= 4)
|
|
|
|
if (numOut >= 5)
|
|
|
|
{
|
|
|
|
const float* end = in + numOut;
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
lastInputSamples[i] = *--end;
|
|
|
|
for (int i = 0; i < 5; ++i)
|
|
|
|
lastInputSamples[i] = input[--numOut];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = 0; i < numOut; ++i)
|
|
|
|
LagrangeHelpers::push (lastInputSamples, in[i]);
|
|
|
|
pushInterpolationSample (lastInputSamples, input[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return numOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
const float* const originalIn = in;
|
|
|
|
double pos = subSamplePos;
|
|
|
|
|
|
|
|
if (actualRatio < 1.0)
|
|
|
|
template <typename InterpolatorType>
|
|
|
|
static int interpolate (float* lastInputSamples, double& subSamplePos, const double actualRatio,
|
|
|
|
const float* in, float* out, const int numOut) noexcept
|
|
|
|
{
|
|
|
|
for (int i = numOut; --i >= 0;)
|
|
|
|
if (actualRatio == 1.0)
|
|
|
|
{
|
|
|
|
if (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;
|
|
|
|
|
|
|
|
if (actualRatio < 1.0)
|
|
|
|
{
|
|
|
|
for (int i = numOut; --i >= 0;)
|
|
|
|
{
|
|
|
|
LagrangeHelpers::push (lastInputSamples, *in++);
|
|
|
|
pos -= 1.0;
|
|
|
|
if (pos >= 1.0)
|
|
|
|
{
|
|
|
|
pushInterpolationSample (lastInputSamples, *in++);
|
|
|
|
pos -= 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out++ = InterpolatorType::valueAtOffset (lastInputSamples, (float) pos);
|
|
|
|
pos += actualRatio;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out++ = LagrangeHelpers::valueAtOffset (lastInputSamples, (float) pos);
|
|
|
|
pos += actualRatio;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = numOut; --i >= 0;)
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (pos < actualRatio)
|
|
|
|
for (int i = numOut; --i >= 0;)
|
|
|
|
{
|
|
|
|
LagrangeHelpers::push (lastInputSamples, *in++);
|
|
|
|
pos += 1.0;
|
|
|
|
while (pos < actualRatio)
|
|
|
|
{
|
|
|
|
pushInterpolationSample (lastInputSamples, *in++);
|
|
|
|
pos += 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos -= actualRatio;
|
|
|
|
*out++ = InterpolatorType::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos));
|
|
|
|
}
|
|
|
|
|
|
|
|
pos -= actualRatio;
|
|
|
|
*out++ = LagrangeHelpers::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
subSamplePos = pos;
|
|
|
|
return (int) (in - originalIn);
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
template <typename InterpolatorType>
|
|
|
|
static int interpolateAdding (float* lastInputSamples, double& subSamplePos, const double actualRatio,
|
|
|
|
const float* in, float* out, const int numOut, const float gain) noexcept
|
|
|
|
{
|
|
|
|
if (gain != 1.0f)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < numOut; ++i)
|
|
|
|
out[i] += in[i] * gain;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (actualRatio == 1.0)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < numOut; ++i)
|
|
|
|
out[i] += in[i];
|
|
|
|
FloatVectorOperations::addWithMultiply (out, in, gain, numOut);
|
|
|
|
pushInterpolationSamples (lastInputSamples, in, numOut);
|
|
|
|
return numOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (numOut >= 4)
|
|
|
|
{
|
|
|
|
const float* end = in + numOut;
|
|
|
|
const float* const originalIn = in;
|
|
|
|
double pos = subSamplePos;
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
lastInputSamples[i] = *--end;
|
|
|
|
if (actualRatio < 1.0)
|
|
|
|
{
|
|
|
|
for (int i = numOut; --i >= 0;)
|
|
|
|
{
|
|
|
|
if (pos >= 1.0)
|
|
|
|
{
|
|
|
|
pushInterpolationSample (lastInputSamples, *in++);
|
|
|
|
pos -= 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*out++ += gain * InterpolatorType::valueAtOffset (lastInputSamples, (float) pos);
|
|
|
|
pos += actualRatio;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i = 0; i < numOut; ++i)
|
|
|
|
LagrangeHelpers::push (lastInputSamples, in[i]);
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return numOut;
|
|
|
|
subSamplePos = pos;
|
|
|
|
return (int) (in - originalIn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const float* const originalIn = in;
|
|
|
|
double pos = subSamplePos;
|
|
|
|
//==============================================================================
|
|
|
|
template <int k>
|
|
|
|
struct LagrangeResampleHelper
|
|
|
|
{
|
|
|
|
static forcedinline void calc (float& a, float b) noexcept { a *= b * (1.0f / k); }
|
|
|
|
};
|
|
|
|
|
|
|
|
if (actualRatio < 1.0)
|
|
|
|
{
|
|
|
|
for (int i = numOut; --i >= 0;)
|
|
|
|
{
|
|
|
|
if (pos >= 1.0)
|
|
|
|
{
|
|
|
|
LagrangeHelpers::push (lastInputSamples, *in++);
|
|
|
|
pos -= 1.0;
|
|
|
|
}
|
|
|
|
template<>
|
|
|
|
struct LagrangeResampleHelper<0>
|
|
|
|
{
|
|
|
|
static forcedinline void calc (float&, float) noexcept {}
|
|
|
|
};
|
|
|
|
|
|
|
|
*out++ += gain * LagrangeHelpers::valueAtOffset (lastInputSamples, (float) pos);
|
|
|
|
pos += actualRatio;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
struct LagrangeAlgorithm
|
|
|
|
{
|
|
|
|
static forcedinline float valueAtOffset (const float* const inputs, const float offset) noexcept
|
|
|
|
{
|
|
|
|
for (int i = numOut; --i >= 0;)
|
|
|
|
{
|
|
|
|
while (pos < actualRatio)
|
|
|
|
{
|
|
|
|
LagrangeHelpers::push (lastInputSamples, *in++);
|
|
|
|
pos += 1.0;
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
pos -= actualRatio;
|
|
|
|
*out++ += gain * LagrangeHelpers::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos));
|
|
|
|
}
|
|
|
|
template <int k>
|
|
|
|
static forcedinline float calcCoefficient (float input, const float offset) noexcept
|
|
|
|
{
|
|
|
|
LagrangeResampleHelper<0 - k>::calc (input, -2.0f - offset);
|
|
|
|
LagrangeResampleHelper<1 - k>::calc (input, -1.0f - offset);
|
|
|
|
LagrangeResampleHelper<2 - k>::calc (input, 0.0f - offset);
|
|
|
|
LagrangeResampleHelper<3 - k>::calc (input, 1.0f - offset);
|
|
|
|
LagrangeResampleHelper<4 - k>::calc (input, 2.0f - offset);
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
LagrangeInterpolator::LagrangeInterpolator() noexcept { reset(); }
|
|
|
|
LagrangeInterpolator::~LagrangeInterpolator() noexcept {}
|
|
|
|
|
|
|
|
subSamplePos = pos;
|
|
|
|
return (int) (in - originalIn);
|
|
|
|
void LagrangeInterpolator::reset() noexcept
|
|
|
|
{
|
|
|
|
subSamplePos = 1.0;
|
|
|
|
|
|
|
|
for (int i = 0; i < numElementsInArray (lastInputSamples); ++i)
|
|
|
|
lastInputSamples[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LagrangeInterpolator::process (double actualRatio, const float* in, float* out, int numOut) noexcept
|
|
|
|
{
|
|
|
|
return interpolate<LagrangeAlgorithm> (lastInputSamples, subSamplePos, actualRatio, in, out, numOut);
|
|
|
|
}
|
|
|
|
|
|
|
|
int LagrangeInterpolator::processAdding (double actualRatio, const float* in, float* out, int numOut, float gain) noexcept
|
|
|
|
{
|
|
|
|
return interpolateAdding<LagrangeAlgorithm> (lastInputSamples, subSamplePos, actualRatio, in, out, numOut, gain);
|
|
|
|
}
|