+/*
+ Copyright (C) 2012 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
#include <stdint.h>
#include <cstdio>
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++;
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;
}
}
/* keep this condition out of the inner loop */
-
+
if (input && output) {
Sample inm1;
-
+
if (floor (distance) == 0.0) {
- /* best guess for the fake point we have to add to be able to interpolate at i == 0:
+ /* best guess for the fake point we have to add to be able to interpolate at i == 0:
.... maintain slope of first actual segment ...
*/
inm1 = input[i] - (input[i+1] - input[i]);
if (fractional_phase_part >= 1.0) {
fractional_phase_part -= 1.0;
++i;
- }
+ }
// Cubically interpolate into the output buffer: keep this inlined for speed and rely on compiler
// optimization to take care of the rest
inm1 = input[i];
}
- } else {
-
- /* not sure that this is ever utilized - it implies that one of the input/output buffers is missing */
+ i = floor(distance);
+ phase[channel] = distance - floor(distance);
+ } else {
+ /* used to calculate play-distance with acceleration (silent roll)
+ * (use same algorithm as real playback for identical rounding/floor'ing)
+ */
for (framecnt_t outsample = 0; outsample < nframes; ++outsample) {
distance += _speed + acceleration;
}
+ i = floor(distance);
}
- i = floor(distance);
- phase[channel] = distance - floor(distance);
-
return i;
}