X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Finterpolation.cc;h=bccaa45553484bb0eceb9e82eeb6b578a3b174a4;hb=06cc5e5240cc2bfeb4e22c742a5705566bd11dbe;hp=7dcc1b7ccbfab551c28c8c3197b09ec3464b9c6c;hpb=62e730b57ab30bb8642c5682b53b7c534d923a24;p=ardour.git diff --git a/libs/ardour/interpolation.cc b/libs/ardour/interpolation.cc index 7dcc1b7ccb..bccaa45553 100644 --- a/libs/ardour/interpolation.cc +++ b/libs/ardour/interpolation.cc @@ -1,3 +1,22 @@ +/* + 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 #include @@ -10,21 +29,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 +52,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; } @@ -73,13 +88,13 @@ CubicInterpolation::interpolate (int channel, framecnt_t nframes, Sample *input, } /* 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]); @@ -106,7 +121,7 @@ CubicInterpolation::interpolate (int channel, framecnt_t nframes, Sample *input, 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 @@ -120,17 +135,18 @@ CubicInterpolation::interpolate (int channel, framecnt_t nframes, Sample *input, 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; }