do not crash when loading old history files with MIDI edits; add all notes in region...
[ardour.git] / libs / ardour / interpolation.cc
index 066507283b6bbf8d375e12b1c113f78006bd56e7..9a45d560c0b0ef5813dba8bd3e0f79a50816ff23 100644 (file)
@@ -1,15 +1,14 @@
 #include <stdint.h>
+#include <cstdio>
+
 #include "ardour/interpolation.h"
 
 using namespace ARDOUR;
 
+
 nframes_t
-LinearInterpolation::interpolate (nframes_t nframes, Sample *input, Sample *output)
+LinearInterpolation::interpolate (int channel, nframes_t nframes, Sample *input, Sample *output)
 {
-       // the idea is that when the speed is not 1.0, we have to 
-       // interpolate between samples and then we have to store where we thought we were. 
-       // rather than being at sample N or N+1, we were at N+0.8792922
-       
        // index in the input buffers
        nframes_t   i = 0;
        
@@ -21,21 +20,64 @@ LinearInterpolation::interpolate (nframes_t nframes, Sample *input, Sample *outp
        } else {
                acceleration = 0.0;
        }
-
+       
+       distance = phase[channel];
        for (nframes_t outsample = 0; outsample < nframes; ++outsample) {
-               i = distance;
+               i = floor(distance);
                Sample fractional_phase_part = distance - i;
+               if (fractional_phase_part >= 1.0) {
+                       fractional_phase_part -= 1.0;
+                       i++;
+               }
                
                if (input && output) {
-               // Linearly interpolate into the output buffer
+               // Linearly interpolate into the output buffer
                        output[outsample] = 
                                input[i] * (1.0f - fractional_phase_part) +
                                input[i+1] * fractional_phase_part;
                }
-               distance   += _speed + acceleration;
+               distance += _speed + acceleration;
        }
        
-       i = (distance + 0.5L);
-       // playback distance
+       i = floor(distance);
+       phase[channel] = distance - floor(distance);
+       
        return i;
 }
+
+nframes_t
+CubicInterpolation::interpolate (int channel, nframes_t nframes, Sample *input, Sample *output)
+{
+    // index in the input buffers
+    nframes_t   i = 0;
+    
+    double acceleration;
+    double distance = 0.0;
+    
+    if (_speed != _target_speed) {
+        acceleration = _target_speed - _speed;
+    } else {
+        acceleration = 0.0;
+    }
+    
+    distance = phase[channel];
+    for (nframes_t outsample = 0; outsample < nframes; ++outsample) {
+        i = floor(distance);
+        Sample fractional_phase_part = distance - i;
+        if (fractional_phase_part >= 1.0) {
+            fractional_phase_part -= 1.0;
+            i++;
+        }
+        
+        if (input && output) {
+            // Cubically interpolate into the output buffer
+            output[outsample] = cube_interp(fractional_phase_part, input[i-1], input[i], input[i+1], input[i+2]);
+        }
+        distance += _speed + acceleration;
+    }
+    
+    i = floor(distance);
+    phase[channel] = distance - floor(distance);
+    
+    return i;
+}