libardour: * Add basic classes for later support of multiple interpolation algorithms...
[ardour.git] / libs / ardour / interpolation.cc
1 #include <stdint.h>
2 #include "ardour/interpolation.h"
3
4 nframes_t
5 LinearInterpolation::interpolate (nframes_t nframes, Sample *input, Sample *output)
6 {
7         // the idea behind phase is that when the speed is not 1.0, we have to 
8         // interpolate between samples and then we have to store where we thought we were. 
9         // rather than being at sample N or N+1, we were at N+0.8792922
10         // so the "phase" element, if you want to think about this way, 
11         // varies from 0 to 1, representing the "offset" between samples
12         uint64_t    phase = last_phase;
13         
14         // acceleration
15         int64_t     phi_delta;
16
17         // phi = fixed point speed
18         if (phi != target_phi) {
19                 phi_delta = ((int64_t)(target_phi - phi)) / nframes;
20         } else {
21                 phi_delta = 0;
22         }
23         
24         // index in the input buffers
25         nframes_t   i = 0;
26
27         for (nframes_t outsample = 0; outsample < nframes; ++outsample) {
28                 i = phase >> 24;
29                 Sample fractional_phase_part = (phase & fractional_part_mask) / binary_scaling_factor;
30                 
31         // Linearly interpolate into the output buffer
32         // using fixed point math
33                 output[outsample] = 
34                         input[i] * (1.0f - fractional_phase_part) +
35                         input[i+1] * fractional_phase_part;
36                 phase += phi + phi_delta;
37         }
38
39         last_phase = (phase & fractional_part_mask);
40         
41         // playback distance
42         return i;
43 }