a2945ffc2b2eb29a55337947556cf97641593aa9
[ardour.git] / libs / ardour / ardour / interpolation.h
1 #include <math.h>
2 #include <samplerate.h>
3
4 #include "ardour/types.h"
5
6 #ifndef __interpolation_h__
7 #define __interpolation_h__
8
9 namespace ARDOUR {
10
11 class Interpolation {
12  protected:
13          double   _speed, _target_speed;
14              
15  public:
16          Interpolation () { _speed = 1.0; }
17      
18          void set_speed (double new_speed)          { _speed = new_speed; }
19          void set_target_speed (double new_speed)   { _target_speed = new_speed; }
20
21          double target_speed()          const { return _target_speed; }
22          double speed()                 const { return _speed; }
23          
24          void add_channel_to (int input_buffer_size, int output_buffer_size) {}
25          void remove_channel_from () {}
26   
27          void reset () {}
28 };
29
30 // 40.24 fixpoint math
31 #define FIXPOINT_ONE 0x1000000
32
33 class FixedPointLinearInterpolation : public Interpolation {
34     protected:
35     /// speed in fixed point math
36     uint64_t      phi;
37     
38     /// target speed in fixed point math
39     uint64_t      target_phi;
40     
41     std::vector<uint64_t> last_phase;
42
43         // Fixed point is just an integer with an implied scaling factor. 
44         // In 40.24 the scaling factor is 2^24 = 16777216,  
45         // so a value of 10*2^24 (in integer space) is equivalent to 10.0. 
46         //
47         // The advantage is that addition and modulus [like x = (x + y) % 2^40]  
48         // have no rounding errors and no drift, and just require a single integer add.
49         // (swh)
50         
51         static const int64_t fractional_part_mask  = 0xFFFFFF;
52         static const Sample  binary_scaling_factor = 16777216.0f;
53     
54     public:
55         FixedPointLinearInterpolation () : phi (FIXPOINT_ONE), target_phi (FIXPOINT_ONE) {}
56     
57         void set_speed (double new_speed) {
58             target_phi = (uint64_t) (FIXPOINT_ONE * fabs(new_speed));
59             phi = target_phi;
60         }
61         
62         void add_channel_to (int input_buffer_size, int output_buffer_size);
63         void remove_channel_from ();
64          
65         nframes_t interpolate (int channel, nframes_t nframes, Sample* input, Sample* output);
66         void reset ();
67 };
68
69  class LinearInterpolation : public Interpolation {
70  protected:
71     // the idea is that when the speed is not 1.0, we have to 
72     // interpolate between samples and then we have to store where we thought we were. 
73     // rather than being at sample N or N+1, we were at N+0.8792922
74     std::vector<double> phase;
75     
76  public:
77          void add_channel_to (int input_buffer_size, int output_buffer_size);
78          void remove_channel_from ();
79      
80          nframes_t interpolate (int channel, nframes_t nframes, Sample* input, Sample* output);
81          void reset ();
82  };
83
84 class LibSamplerateInterpolation : public Interpolation {
85  protected:
86     std::vector<SRC_STATE*>  state;
87     std::vector<SRC_DATA*>   data;
88     
89     int        error;
90     
91     void reset_state ();
92     
93  public:
94         LibSamplerateInterpolation ();
95         ~LibSamplerateInterpolation ();
96     
97         void   set_speed (double new_speed);
98         void   set_target_speed (double new_speed)   {}
99         double speed ()                        const { return _speed;      }
100         
101         void add_channel_to (int input_buffer_size, int output_buffer_size);
102         void remove_channel_from (); 
103  
104         nframes_t interpolate (int channel, nframes_t nframes, Sample* input, Sample* output);
105         void reset() { reset_state (); }
106 };
107
108 } // namespace ARDOUR
109
110 #endif