'libs/panners' - Streamline my previous API changes and include Tim's additions to...
[ardour.git] / libs / ardour / ardour / panner.h
1 /*
2     Copyright (C) 2004-2011 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef __ardour_panner_h__
21 #define __ardour_panner_h__
22
23 #include <cmath>
24 #include <cassert>
25 #include <vector>
26 #include <string>
27 #include <iostream>
28
29 #include "pbd/cartesian.h"
30 #include "pbd/signals.h"
31 #include "pbd/stateful.h"
32
33 #include "ardour/types.h"
34 #include "ardour/automation_control.h"
35 #include "ardour/automatable.h"
36
37 #ifndef ARDOURPANNER_IS_IN_SHARED_LIB
38         #define ARDOURPANNER_IS_IN_SHARED_LIB 1
39 #endif
40
41 #if ARDOURPANNER_IS_IN_SHARED_LIB && !defined(ARDOURPANNER_API)
42         #define ARDOURPANNER_CAPICALLTYPE __cdecl
43
44         #if defined(COMPILER_MSVC) || defined(COMPILER_MINGW)
45                 #if defined(BUILDING_ARDOURPANNERS)
46                         #define ARDOURPANNER_LOCAL
47                         #define ARDOURPANNER_API   __declspec(dllexport)
48                 #else
49                         #define ARDOURPANNER_LOCAL
50                         #define ARDOURPANNER_API   __declspec(dllimport)
51                 #endif
52         #else
53                 #if !defined(COMPILER_GCC)
54                         #warning "Attempting to export symbols with an unspecified compiler! GCC assumed!"
55                 #endif
56
57                 #define ARDOURPANNER_LOCAL __attribute__ ((visibility("hidden")))
58                 #define ARDOURPANNER_API   __attribute__ ((visibility("default")))
59         #endif
60 #elif !defined(ARDOURPANNER_API)
61         #define ARDOURPANNER_CAPICALLTYPE __cdecl
62
63         /* This library was built statically.    */
64         /* Visibility is determined by the code. */
65         #define ARDOURPANNER_API
66         #define ARDOURPANNER_LOCAL
67 #endif
68
69 namespace ARDOUR {
70
71 class Session;
72 class Pannable;
73 class BufferSet;
74 class AudioBuffer;
75 class Speakers;
76
77 class Panner : public PBD::Stateful, public PBD::ScopedConnectionList
78 {
79 public:
80         Panner (boost::shared_ptr<Pannable>);
81         ~Panner ();
82
83         virtual boost::shared_ptr<Speakers> get_speakers() const { return boost::shared_ptr<Speakers>(); }
84
85         virtual ChanCount in() const = 0;
86         virtual ChanCount out() const = 0;
87
88         virtual void configure_io (ARDOUR::ChanCount /*in*/, ARDOUR::ChanCount /*out*/) {}
89
90         /* derived implementations of these methods must indicate
91            whether it is legal for a Controllable to use the
92            value of the argument (post-call) in a call to
93            Controllable::set_value().
94
95            they have a choice of:
96
97            * return true, leave argument unchanged
98            * return true, modify argument
99            * return false
100         */
101
102         virtual bool clamp_position (double&) { return true; }
103         virtual bool clamp_width (double&) { return true; }
104         virtual bool clamp_elevation (double&) { return true; }
105
106         virtual std::pair<double, double> position_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); }
107         virtual std::pair<double, double> width_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); }
108         virtual std::pair<double, double> elevation_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); }
109
110         virtual void set_position (double) { }
111         virtual void set_width (double) { }
112         virtual void set_elevation (double) { }
113
114         virtual double position () const { return 0.0; }
115         virtual double width () const { return 0.0; }
116         virtual double elevation () const { return 0.0; }
117
118         virtual PBD::AngularVector signal_position (uint32_t) const { return PBD::AngularVector(); }
119
120         virtual void reset () = 0;
121
122         void      set_automation_state (AutoState);
123         AutoState automation_state() const;
124         void      set_automation_style (AutoStyle);
125         AutoStyle automation_style() const;
126
127         virtual std::set<Evoral::Parameter> what_can_be_automated() const;
128         virtual std::string describe_parameter (Evoral::Parameter);
129         virtual std::string value_as_string (boost::shared_ptr<AutomationControl>) const;
130
131         bool touching() const;
132
133         static double azimuth_to_lr_fract (double azi) {
134                 /* 180.0 degrees=> left => 0.0 */
135                 /* 0.0 degrees => right => 1.0 */
136
137                 /* humans can only distinguish 1 degree of arc between two positions,
138                    so force azi back to an integral value before computing
139                 */
140
141                 return 1.0 - (rint(azi)/180.0);
142         }
143
144         static double lr_fract_to_azimuth (double fract) {
145                 /* fract = 0.0 => degrees = 180.0 => left */
146                 /* fract = 1.0 => degrees = 0.0 => right */
147
148                 /* humans can only distinguish 1 degree of arc between two positions,
149                    so force azi back to an integral value after computing
150                 */
151
152                 return rint (180.0 - (fract * 180.0));
153         }
154
155         /**
156          *  Pan some input buffers to a number of output buffers.
157          *
158          *  @param ibufs Input buffers (one per panner input)
159          *  @param obufs Output buffers (one per panner output).
160          *  @param gain_coeff fixed, additional gain coefficient to apply to output samples.
161          *  @param nframes Number of frames in the input.
162          *
163          *  Derived panners can choose to implement these if they need to gain more
164          *  control over the panning algorithm.  The default is to call
165          *  distribute_one() or distribute_one_automated() on each input buffer to
166          *  deliver it to each output buffer.
167          *
168          *  If a panner does not need to override this default behaviour, it can
169          *  just implement distribute_one() and distribute_one_automated() (below).
170          */
171         virtual void distribute (BufferSet& ibufs, BufferSet& obufs, gain_t gain_coeff, pframes_t nframes);
172         virtual void distribute_automated (BufferSet& ibufs, BufferSet& obufs,
173                                            framepos_t start, framepos_t end, pframes_t nframes,
174                                            pan_t** buffers);
175
176         int set_state (const XMLNode&, int version);
177         XMLNode& get_state ();
178         
179         boost::shared_ptr<Pannable> pannable() const { return _pannable; }
180
181         static bool equivalent (pan_t a, pan_t b) {
182                 return fabsf (a - b) < 0.002; // about 1 degree of arc for a stereo panner
183         }
184
185         static bool equivalent (const PBD::AngularVector& a, const PBD::AngularVector& b) {
186                 /* XXX azimuth only, at present */
187                 return fabs (a.azi - b.azi) < 1.0;
188         }
189
190         virtual void freeze ();
191         virtual void thaw ();
192
193 protected:
194         boost::shared_ptr<Pannable> _pannable;
195
196         virtual void distribute_one (AudioBuffer&, BufferSet& obufs, gain_t gain_coeff, pframes_t nframes, uint32_t which) = 0;
197         virtual void distribute_one_automated (AudioBuffer&, BufferSet& obufs,
198                                                framepos_t start, framepos_t end, pframes_t nframes,
199                                                pan_t** buffers, uint32_t which) = 0;
200
201         int32_t _frozen;
202 };
203
204 } // namespace
205
206 extern "C" {
207 struct PanPluginDescriptor {
208         std::string name;
209         int32_t in;
210         int32_t out;
211         ARDOUR::Panner* (*factory)(boost::shared_ptr<ARDOUR::Pannable>, boost::shared_ptr<ARDOUR::Speakers>);
212 };
213 }
214
215 #endif /* __ardour_panner_h__ */