save&restore gain levels; provide GUI control over relative route group bit; fix...
[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         
56         FixedPointLinearInterpolation () : phi (FIXPOINT_ONE), target_phi (FIXPOINT_ONE) {}
57     
58         void set_speed (double new_speed) {
59             target_phi = (uint64_t) (FIXPOINT_ONE * fabs(new_speed));
60             phi = target_phi;
61         }
62         
63         uint64_t get_phi() { return phi; }
64         uint64_t get_target_phi() { return target_phi; }
65         uint64_t get_last_phase() { assert(last_phase.size()); return last_phase[0]; }
66         void set_last_phase(uint64_t phase) { assert(last_phase.size()); last_phase[0] = phase; }
67         
68         void add_channel_to (int input_buffer_size, int output_buffer_size);
69         void remove_channel_from ();
70          
71         nframes_t interpolate (int channel, nframes_t nframes, Sample* input, Sample* output);
72         void reset ();
73 };
74
75  class LinearInterpolation : public Interpolation {
76  protected:
77     // the idea is that when the speed is not 1.0, we have to 
78     // interpolate between samples and then we have to store where we thought we were. 
79     // rather than being at sample N or N+1, we were at N+0.8792922
80     std::vector<double> phase;
81     
82  public:
83          void add_channel_to (int input_buffer_size, int output_buffer_size);
84          void remove_channel_from ();
85      
86          nframes_t interpolate (int channel, nframes_t nframes, Sample* input, Sample* output);
87          void reset ();
88  };
89
90 class LibSamplerateInterpolation : public Interpolation {
91  protected:
92     std::vector<SRC_STATE*>  state;
93     std::vector<SRC_DATA*>   data;
94     
95     int        error;
96     
97     void reset_state ();
98     
99  public:
100         LibSamplerateInterpolation ();
101         ~LibSamplerateInterpolation ();
102     
103         void   set_speed (double new_speed);
104         void   set_target_speed (double new_speed)   {}
105         double speed ()                        const { return _speed;      }
106         
107         void add_channel_to (int input_buffer_size, int output_buffer_size);
108         void remove_channel_from (); 
109  
110         nframes_t interpolate (int channel, nframes_t nframes, Sample* input, Sample* output);
111         void reset() { reset_state (); }
112 };
113
114 } // namespace ARDOUR
115
116 #endif