summaryrefslogtreecommitdiff
path: root/libs/ardour/interpolation.cc
diff options
context:
space:
mode:
authorHans Baier <hansfbaier@googlemail.com>2009-06-10 00:03:28 +0000
committerHans Baier <hansfbaier@googlemail.com>2009-06-10 00:03:28 +0000
commitf284d28d5306114e9badc9077835683e541420e0 (patch)
tree500bbe83900479c1a0780e780242187cd51bc9ef /libs/ardour/interpolation.cc
parentd039e2e80ff2179aef7430c53ca41e43297d9065 (diff)
libardour: * Add basic classes for later support of multiple interpolation algorithms for varispeed
* Add unit tests: Test which shows how the varispeed implementation in diskstream is broken. git-svn-id: svn://localhost/ardour2/branches/3.0@5144 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour/interpolation.cc')
-rw-r--r--libs/ardour/interpolation.cc43
1 files changed, 43 insertions, 0 deletions
diff --git a/libs/ardour/interpolation.cc b/libs/ardour/interpolation.cc
new file mode 100644
index 0000000000..7aece6453c
--- /dev/null
+++ b/libs/ardour/interpolation.cc
@@ -0,0 +1,43 @@
+#include <stdint.h>
+#include "ardour/interpolation.h"
+
+nframes_t
+LinearInterpolation::interpolate (nframes_t nframes, Sample *input, Sample *output)
+{
+ // the idea behind phase 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
+ // so the "phase" element, if you want to think about this way,
+ // varies from 0 to 1, representing the "offset" between samples
+ uint64_t phase = last_phase;
+
+ // acceleration
+ int64_t phi_delta;
+
+ // phi = fixed point speed
+ if (phi != target_phi) {
+ phi_delta = ((int64_t)(target_phi - phi)) / nframes;
+ } else {
+ phi_delta = 0;
+ }
+
+ // index in the input buffers
+ nframes_t i = 0;
+
+ for (nframes_t outsample = 0; outsample < nframes; ++outsample) {
+ i = phase >> 24;
+ Sample fractional_phase_part = (phase & fractional_part_mask) / binary_scaling_factor;
+
+ // Linearly interpolate into the output buffer
+ // using fixed point math
+ output[outsample] =
+ input[i] * (1.0f - fractional_phase_part) +
+ input[i+1] * fractional_phase_part;
+ phase += phi + phi_delta;
+ }
+
+ last_phase = (phase & fractional_part_mask);
+
+ // playback distance
+ return i;
+}