mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
GenericInterpolator: Refactor to avoid repetition
Also fixes an issue in which `numInputSamplesAvailable` was assigned instead of `exceeded`, Github issue #1114. Co-authored-by: Tatsuya Shiozawa <shio.tatsu99@gmail.com>
This commit is contained in:
parent
34341bc597
commit
d28815601a
1 changed files with 119 additions and 217 deletions
|
|
@ -39,6 +39,16 @@ namespace juce
|
|||
template <class InterpolatorTraits, int memorySize>
|
||||
class JUCE_API GenericInterpolator
|
||||
{
|
||||
static auto processReplacingCallback()
|
||||
{
|
||||
return [] (auto, auto newValue) { return newValue; };
|
||||
}
|
||||
|
||||
static auto processAddingCallback (float gain)
|
||||
{
|
||||
return [gain] (auto oldValue, auto newValue) { return oldValue + gain * newValue; };
|
||||
}
|
||||
|
||||
public:
|
||||
GenericInterpolator() noexcept { reset(); }
|
||||
|
||||
|
|
@ -81,7 +91,11 @@ public:
|
|||
float* outputSamples,
|
||||
int numOutputSamplesToProduce) noexcept
|
||||
{
|
||||
return interpolate (speedRatio, inputSamples, outputSamples, numOutputSamplesToProduce);
|
||||
return interpolateImpl (speedRatio,
|
||||
inputSamples,
|
||||
outputSamples,
|
||||
numOutputSamplesToProduce,
|
||||
processReplacingCallback());
|
||||
}
|
||||
|
||||
/** Resamples a stream of samples.
|
||||
|
|
@ -106,8 +120,13 @@ public:
|
|||
int numInputSamplesAvailable,
|
||||
int wrapAround) noexcept
|
||||
{
|
||||
return interpolate (speedRatio, inputSamples, outputSamples,
|
||||
numOutputSamplesToProduce, numInputSamplesAvailable, wrapAround);
|
||||
return interpolateImpl (speedRatio,
|
||||
inputSamples,
|
||||
outputSamples,
|
||||
numOutputSamplesToProduce,
|
||||
numInputSamplesAvailable,
|
||||
wrapAround,
|
||||
processReplacingCallback());
|
||||
}
|
||||
|
||||
/** Resamples a stream of samples, adding the results to the output data
|
||||
|
|
@ -131,7 +150,11 @@ public:
|
|||
int numOutputSamplesToProduce,
|
||||
float gain) noexcept
|
||||
{
|
||||
return interpolateAdding (speedRatio, inputSamples, outputSamples, numOutputSamplesToProduce, gain);
|
||||
return interpolateImpl (speedRatio,
|
||||
inputSamples,
|
||||
outputSamples,
|
||||
numOutputSamplesToProduce,
|
||||
processAddingCallback (gain));
|
||||
}
|
||||
|
||||
/** Resamples a stream of samples, adding the results to the output data
|
||||
|
|
@ -162,8 +185,13 @@ public:
|
|||
int wrapAround,
|
||||
float gain) noexcept
|
||||
{
|
||||
return interpolateAdding (speedRatio, inputSamples, outputSamples,
|
||||
numOutputSamplesToProduce, numInputSamplesAvailable, wrapAround, gain);
|
||||
return interpolateImpl (speedRatio,
|
||||
inputSamples,
|
||||
outputSamples,
|
||||
numOutputSamplesToProduce,
|
||||
numInputSamplesAvailable,
|
||||
wrapAround,
|
||||
processAddingCallback (gain));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -255,10 +283,89 @@ private:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
int interpolate (double speedRatio,
|
||||
const float* input,
|
||||
float* output,
|
||||
int numOutputSamplesToProduce) noexcept
|
||||
template <typename Process>
|
||||
int interpolateImpl (double speedRatio,
|
||||
const float* input,
|
||||
float* output,
|
||||
int numOutputSamplesToProduce,
|
||||
int numInputSamplesAvailable,
|
||||
int wrap,
|
||||
Process process)
|
||||
{
|
||||
auto originalIn = input;
|
||||
auto pos = subSamplePos;
|
||||
bool exceeded = false;
|
||||
|
||||
const auto pushSample = [&]
|
||||
{
|
||||
if (exceeded)
|
||||
{
|
||||
pushInterpolationSample (0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushInterpolationSample (*input++);
|
||||
|
||||
if (--numInputSamplesAvailable <= 0)
|
||||
{
|
||||
if (wrap > 0)
|
||||
{
|
||||
input -= wrap;
|
||||
numInputSamplesAvailable += wrap;
|
||||
}
|
||||
else
|
||||
{
|
||||
exceeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (speedRatio < 1.0)
|
||||
{
|
||||
for (int i = numOutputSamplesToProduce; --i >= 0;)
|
||||
{
|
||||
if (pos >= 1.0)
|
||||
{
|
||||
pushSample();
|
||||
pos -= 1.0;
|
||||
}
|
||||
|
||||
*output = process (*output, InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer));
|
||||
++output;
|
||||
pos += speedRatio;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numOutputSamplesToProduce; --i >= 0;)
|
||||
{
|
||||
while (pos < speedRatio)
|
||||
{
|
||||
pushSample();
|
||||
pos += 1.0;
|
||||
}
|
||||
|
||||
pos -= speedRatio;
|
||||
*output = process (*output, InterpolatorTraits::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos), indexBuffer));
|
||||
++output;
|
||||
}
|
||||
}
|
||||
|
||||
subSamplePos = pos;
|
||||
|
||||
if (wrap == 0)
|
||||
return (int) (input - originalIn);
|
||||
|
||||
return ((int) (input - originalIn) + wrap) % wrap;
|
||||
}
|
||||
|
||||
template <typename Process>
|
||||
int interpolateImpl (double speedRatio,
|
||||
const float* input,
|
||||
float* output,
|
||||
int numOutputSamplesToProduce,
|
||||
Process process)
|
||||
{
|
||||
auto pos = subSamplePos;
|
||||
int numUsed = 0;
|
||||
|
|
@ -271,213 +378,8 @@ private:
|
|||
pos -= 1.0;
|
||||
}
|
||||
|
||||
*output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);
|
||||
pos += speedRatio;
|
||||
--numOutputSamplesToProduce;
|
||||
}
|
||||
|
||||
subSamplePos = pos;
|
||||
return numUsed;
|
||||
}
|
||||
|
||||
int interpolate (double speedRatio,
|
||||
const float* input, float* output,
|
||||
int numOutputSamplesToProduce,
|
||||
int numInputSamplesAvailable,
|
||||
int wrap) noexcept
|
||||
{
|
||||
auto originalIn = input;
|
||||
auto pos = subSamplePos;
|
||||
bool exceeded = false;
|
||||
|
||||
if (speedRatio < 1.0)
|
||||
{
|
||||
for (int i = numOutputSamplesToProduce; --i >= 0;)
|
||||
{
|
||||
if (pos >= 1.0)
|
||||
{
|
||||
if (exceeded)
|
||||
{
|
||||
pushInterpolationSample (0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushInterpolationSample (*input++);
|
||||
|
||||
if (--numInputSamplesAvailable <= 0)
|
||||
{
|
||||
if (wrap > 0)
|
||||
{
|
||||
input -= wrap;
|
||||
numInputSamplesAvailable += wrap;
|
||||
}
|
||||
else
|
||||
{
|
||||
exceeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos -= 1.0;
|
||||
}
|
||||
|
||||
*output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);
|
||||
pos += speedRatio;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numOutputSamplesToProduce; --i >= 0;)
|
||||
{
|
||||
while (pos < speedRatio)
|
||||
{
|
||||
if (exceeded)
|
||||
{
|
||||
pushInterpolationSample (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushInterpolationSample (*input++);
|
||||
|
||||
if (--numInputSamplesAvailable <= 0)
|
||||
{
|
||||
if (wrap > 0)
|
||||
{
|
||||
input -= wrap;
|
||||
numInputSamplesAvailable += wrap;
|
||||
}
|
||||
else
|
||||
{
|
||||
exceeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos += 1.0;
|
||||
}
|
||||
|
||||
pos -= speedRatio;
|
||||
*output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos), indexBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
subSamplePos = pos;
|
||||
|
||||
if (wrap == 0)
|
||||
return (int) (input - originalIn);
|
||||
|
||||
return ((int) (input - originalIn) + wrap) % wrap;
|
||||
}
|
||||
|
||||
int interpolateAdding (double speedRatio,
|
||||
const float* input,
|
||||
float* output,
|
||||
int numOutputSamplesToProduce,
|
||||
int numInputSamplesAvailable,
|
||||
int wrap,
|
||||
float gain) noexcept
|
||||
{
|
||||
auto originalIn = input;
|
||||
auto pos = subSamplePos;
|
||||
bool exceeded = false;
|
||||
|
||||
if (speedRatio < 1.0)
|
||||
{
|
||||
for (int i = numOutputSamplesToProduce; --i >= 0;)
|
||||
{
|
||||
if (pos >= 1.0)
|
||||
{
|
||||
if (exceeded)
|
||||
{
|
||||
pushInterpolationSample (0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushInterpolationSample (*input++);
|
||||
|
||||
if (--numInputSamplesAvailable <= 0)
|
||||
{
|
||||
if (wrap > 0)
|
||||
{
|
||||
input -= wrap;
|
||||
numInputSamplesAvailable += wrap;
|
||||
}
|
||||
else
|
||||
{
|
||||
numInputSamplesAvailable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos -= 1.0;
|
||||
}
|
||||
|
||||
*output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);
|
||||
pos += speedRatio;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numOutputSamplesToProduce; --i >= 0;)
|
||||
{
|
||||
while (pos < speedRatio)
|
||||
{
|
||||
if (exceeded)
|
||||
{
|
||||
pushInterpolationSample (0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushInterpolationSample (*input++);
|
||||
|
||||
if (--numInputSamplesAvailable <= 0)
|
||||
{
|
||||
if (wrap > 0)
|
||||
{
|
||||
input -= wrap;
|
||||
numInputSamplesAvailable += wrap;
|
||||
}
|
||||
else
|
||||
{
|
||||
exceeded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos += 1.0;
|
||||
}
|
||||
|
||||
pos -= speedRatio;
|
||||
*output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos), indexBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
subSamplePos = pos;
|
||||
|
||||
if (wrap == 0)
|
||||
return (int) (input - originalIn);
|
||||
|
||||
return ((int) (input - originalIn) + wrap) % wrap;
|
||||
}
|
||||
|
||||
int interpolateAdding (double speedRatio,
|
||||
const float* input,
|
||||
float* output,
|
||||
int numOutputSamplesToProduce,
|
||||
float gain) noexcept
|
||||
{
|
||||
auto pos = subSamplePos;
|
||||
int numUsed = 0;
|
||||
|
||||
while (numOutputSamplesToProduce > 0)
|
||||
{
|
||||
while (pos >= 1.0)
|
||||
{
|
||||
pushInterpolationSample (input[numUsed++]);
|
||||
pos -= 1.0;
|
||||
}
|
||||
|
||||
*output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);
|
||||
*output = process (*output, InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer));
|
||||
++output;
|
||||
pos += speedRatio;
|
||||
--numOutputSamplesToProduce;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue