13
0

Fix linear interpolator to avoid error accumulation.

git-svn-id: svn://localhost/ardour2/branches/3.0@12044 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2012-04-20 17:52:42 +00:00
parent ffe5a6c5c2
commit 842bddde1e
2 changed files with 14 additions and 20 deletions

View File

@ -10,21 +10,18 @@ framecnt_t
LinearInterpolation::interpolate (int channel, framecnt_t nframes, Sample *input, Sample *output)
{
// index in the input buffers
framecnt_t i = 0;
framecnt_t i = 0;
double acceleration;
double distance = 0.0;
double acceleration = 0;
if (_speed != _target_speed) {
acceleration = _target_speed - _speed;
} else {
acceleration = 0.0;
}
distance = phase[channel];
for (framecnt_t outsample = 0; outsample < nframes; ++outsample) {
i = floor(distance);
Sample fractional_phase_part = distance - i;
double const d = phase[channel] + outsample * (_speed + acceleration);
i = floor(d);
Sample fractional_phase_part = d - i;
if (fractional_phase_part >= 1.0) {
fractional_phase_part -= 1.0;
i++;
@ -36,12 +33,11 @@ LinearInterpolation::interpolate (int channel, framecnt_t nframes, Sample *input
input[i] * (1.0f - fractional_phase_part) +
input[i+1] * fractional_phase_part;
}
distance += _speed + acceleration;
}
double const distance = phase[channel] + nframes * (_speed + acceleration);
i = floor(distance);
phase[channel] = distance - floor(distance);
phase[channel] = distance - i;
return i;
}

View File

@ -54,15 +54,13 @@ InterpolationTest::linearInterpolationTest ()
result = linear.interpolate (0, NUM_SAMPLES, input, output);
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * linear.speed()), result);
/* This one fails due too error accumulation
cout << "\nSpeed: 0.002";
linear.reset();
linear.set_speed (0.002);
linear.set_target_speed (linear.speed());
result = linear.interpolate (0, NUM_SAMPLES, input, output);
linear.speed();
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * linear.speed()), result);
*/
// cout << "\nSpeed: 0.002";
linear.reset();
linear.set_speed (0.002);
linear.set_target_speed (linear.speed());
result = linear.interpolate (0, NUM_SAMPLES, input, output);
linear.speed();
CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * linear.speed()), result);
// cout << "\nSpeed: 2.0";
linear.reset();