X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Fpanner.h;h=62512f6181c1b0f8211525ff22944e43bde6e9c8;hb=606a65321d72fe354db49f0c74a5c6968eb87a53;hp=32d512c2534e2c3c350d37019c2aeab52c6d1a8b;hpb=1987df571c861e89fa96dd1622bdc9908d0d768d;p=ardour.git diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h index 32d512c253..62512f6181 100644 --- a/libs/ardour/ardour/panner.h +++ b/libs/ardour/ardour/panner.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 Paul Davis + Copyright (C) 2004 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,36 +15,35 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ #ifndef __ardour_panner_h__ #define __ardour_panner_h__ #include +#include #include #include #include -#include -#include -#include +#include "pbd/stateful.h" +#include "pbd/controllable.h" -#include -#include - -using std::istream; -using std::ostream; +#include "ardour/types.h" +#include "ardour/automation_control.h" +#include "ardour/processor.h" namespace ARDOUR { class Session; class Panner; +class BufferSet; +class AudioBuffer; -class StreamPanner : public sigc::trackable, public Stateful +class StreamPanner : public PBD::Stateful { public: - StreamPanner (Panner& p); + StreamPanner (Panner& p, Evoral::Parameter param); ~StreamPanner (); void set_muted (bool yn); @@ -54,55 +53,54 @@ class StreamPanner : public sigc::trackable, public Stateful void set_position (float x, float y, bool link_call = false); void set_position (float x, float y, float z, bool link_call = false); - void get_position (float& xpos) const { xpos = x; } - void get_position (float& xpos, float& ypos) const { xpos = x; ypos = y; } - void get_position (float& xpos, float& ypos, float& zpos) const { xpos = x; ypos = y; zpos = z; } + void get_position (float& xpos) const { xpos = _x; } + void get_position (float& xpos, float& ypos) const { xpos = _x; ypos = _y; } + void get_position (float& xpos, float& ypos, float& zpos) const { xpos = _x; ypos = _y; zpos = _z; } void get_effective_position (float& xpos) const { xpos = effective_x; } void get_effective_position (float& xpos, float& ypos) const { xpos = effective_x; ypos = effective_y; } void get_effective_position (float& xpos, float& ypos, float& zpos) const { xpos = effective_x; ypos = effective_y; zpos = effective_z; } - /* the basic panner API */ - - virtual void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nframes_t nframes) = 0; - virtual void distribute_automated (Sample* src, Sample** obufs, - nframes_t start, nframes_t end, nframes_t nframes, pan_t** buffers) = 0; + void distribute (AudioBuffer &, BufferSet &, gain_t, nframes_t); + void distribute_automated (AudioBuffer &, BufferSet &, nframes_t, nframes_t, nframes_t, pan_t **); - /* automation */ + /* the basic StreamPanner API */ - virtual void snapshot (nframes_t now) = 0; - virtual void transport_stopped (nframes_t frame) = 0; - virtual void set_automation_state (AutoState) = 0; - virtual void set_automation_style (AutoStyle) = 0; - - PBD::Controllable& control() { return _control; } - - /* XXX this is wrong. for multi-dimensional panners, there - must surely be more than 1 automation curve. - */ + /** + * Pan some input samples to a number of output buffers. + * + * @param src Input buffer. + * @param obufs Output buffers (one per panner output). + * @param gain_coeff Gain coefficient to apply to output samples. + * @param nframes Number of frames in the input. + */ + virtual void do_distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, nframes_t nframes) = 0; + virtual void do_distribute_automated (AudioBuffer& src, BufferSet& obufs, + nframes_t start, nframes_t end, nframes_t nframes, pan_t** buffers) = 0; - virtual Curve& automation() = 0; + boost::shared_ptr pan_control() { return _control; } - sigc::signal Changed; /* for position */ - sigc::signal StateChanged; /* for mute */ + PBD::Signal0 Changed; /* for position */ + PBD::Signal0 StateChanged; /* for mute, mono */ - int set_state (const XMLNode&); + int set_state (const XMLNode&, int version); virtual XMLNode& state (bool full_state) = 0; - + Panner & get_parent() { return parent; } - - /* old school automation loading */ - virtual int load (istream&, string path, uint32_t&) = 0; + /* old school automation loading */ + virtual int load (std::istream&, std::string path, uint32_t&) = 0; protected: friend class Panner; Panner& parent; - float x; - float y; - float z; + void set_mono (bool); + float _x; + float _y; + float _z; + /* these are for automation. they store the last value used by the most recent process() cycle. */ @@ -111,48 +109,34 @@ class StreamPanner : public sigc::trackable, public Stateful float effective_y; float effective_z; - bool _muted; - - struct PanControllable : public PBD::Controllable { - PanControllable (std::string name, StreamPanner& p) : Controllable (name), panner (p) {} - - StreamPanner& panner; - - void set_value (float); - float get_value (void) const; - bool can_send_feedback() const; - }; + bool _muted; + bool _mono; - PanControllable _control; + boost::shared_ptr _control; void add_state (XMLNode&); + + /* Update internal parameters based on _x, _y and _z */ virtual void update () = 0; }; class BaseStereoPanner : public StreamPanner { public: - BaseStereoPanner (Panner&); + BaseStereoPanner (Panner&, Evoral::Parameter param); ~BaseStereoPanner (); /* this class just leaves the pan law itself to be defined - by the update(), distribute_automated() + by the update(), do_distribute_automated() methods. derived classes also need a factory method and a type name. See EqualPowerStereoPanner as an example. */ - void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nframes_t nframes); - - void snapshot (nframes_t now); - void transport_stopped (nframes_t frame); - void set_automation_state (AutoState); - void set_automation_style (AutoStyle); - - Curve& automation() { return _automation; } + void do_distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, nframes_t nframes); /* old school automation loading */ - int load (istream&, string path, uint32_t&); + int load (std::istream&, std::string path, uint32_t&); protected: float left; @@ -161,28 +145,26 @@ class BaseStereoPanner : public StreamPanner float desired_right; float left_interp; float right_interp; - - Curve _automation; }; class EqualPowerStereoPanner : public BaseStereoPanner { public: - EqualPowerStereoPanner (Panner&); + EqualPowerStereoPanner (Panner&, Evoral::Parameter param); ~EqualPowerStereoPanner (); - void distribute_automated (Sample* src, Sample** obufs, - nframes_t start, nframes_t end, nframes_t nframes, pan_t** buffers); + void do_distribute_automated (AudioBuffer& src, BufferSet& obufs, + nframes_t start, nframes_t end, nframes_t nframes, pan_t** buffers); void get_current_coefficients (pan_t*) const; void get_desired_coefficients (pan_t*) const; - static StreamPanner* factory (Panner&); - static string name; + static StreamPanner* factory (Panner&, Evoral::Parameter param); + static std::string name; XMLNode& state (bool full_state); XMLNode& get_state (void); - int set_state (const XMLNode&); + int set_state (const XMLNode&, int version); private: void update (); @@ -191,69 +173,51 @@ class EqualPowerStereoPanner : public BaseStereoPanner class Multi2dPanner : public StreamPanner { public: - Multi2dPanner (Panner& parent); + Multi2dPanner (Panner& parent, Evoral::Parameter); ~Multi2dPanner (); - void snapshot (nframes_t now); - void transport_stopped (nframes_t frame); - void set_automation_state (AutoState); - void set_automation_style (AutoStyle); - - /* XXX this is wrong. for multi-dimensional panners, there - must surely be more than 1 automation curve. - */ - - Curve& automation() { return _automation; } - - void distribute (Sample* src, Sample** obufs, gain_t gain_coeff, nframes_t nframes); - void distribute_automated (Sample* src, Sample** obufs, - nframes_t start, nframes_t end, nframes_t nframes, pan_t** buffers); + void do_distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, nframes_t nframes); + void do_distribute_automated (AudioBuffer& src, BufferSet& obufs, + nframes_t start, nframes_t end, nframes_t nframes, pan_t** buffers); - static StreamPanner* factory (Panner&); - static string name; + static StreamPanner* factory (Panner&, Evoral::Parameter); + static std::string name; - XMLNode& state (bool full_state); + XMLNode& state (bool full_state); XMLNode& get_state (void); - int set_state (const XMLNode&); + int set_state (const XMLNode&, int version); /* old school automation loading */ - int load (istream&, string path, uint32_t&); + int load (std::istream&, std::string path, uint32_t&); private: - Curve _automation; void update (); }; -class Panner : public std::vector, public Stateful, public sigc::trackable + +/** Class to pan from some number of inputs to some number of outputs. + * This class has a number of StreamPanners, one for each input. + */ +class Panner : public SessionObject, public Automatable { - public: +public: struct Output { - float x; - float y; - pan_t current_pan; - pan_t desired_pan; - - Output (float xp, float yp) - : x (xp), y (yp), current_pan (0.0f), desired_pan (0.f) {} - - }; + float x; + float y; + pan_t current_pan; + pan_t desired_pan; - Panner (string name, Session&); - virtual ~Panner (); + Output (float xp, float yp) + : x (xp), y (yp), current_pan (0), desired_pan (0) {} - bool bypassed() const { return _bypassed; } - void set_bypassed (bool yn); + }; - StreamPanner* add (); - void remove (uint32_t which); - void clear (); - void reset (uint32_t noutputs, uint32_t npans); + Panner (std::string name, Session&); + virtual ~Panner (); - void snapshot (nframes_t now); - void transport_stopped (nframes_t frame); - - void clear_automation (); + void clear_panners (); + bool empty() const { return _streampanners.empty(); } void set_automation_state (AutoState); AutoState automation_state() const; @@ -261,12 +225,26 @@ class Panner : public std::vector, public Stateful, public sigc:: AutoStyle automation_style() const; bool touching() const; + bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return true; }; + + /// The fundamental Panner function + void run (BufferSet& src, BufferSet& dest, sframes_t start_frame, sframes_t end_frames, nframes_t nframes); + + bool bypassed() const { return _bypassed; } + void set_bypassed (bool yn); + bool mono () const { return _mono; } + void set_mono (bool); + + StreamPanner* add (); + void remove (uint32_t which); + void reset (uint32_t noutputs, uint32_t npans); + void reset_streampanner (uint32_t which_panner); + void reset_to_default (); + XMLNode& get_state (void); XMLNode& state (bool full); - int set_state (const XMLNode&); + int set_state (const XMLNode&, int version); - sigc::signal Changed; - static bool equivalent (pan_t a, pan_t b) { return fabsf (a - b) < 0.002; // about 1 degree of arc for a stereo panner } @@ -275,9 +253,6 @@ class Panner : public std::vector, public Stateful, public sigc:: uint32_t nouts() const { return outputs.size(); } Output& output (uint32_t n) { return outputs[n]; } - std::vector outputs; - Session& session() const { return _session; } - enum LinkDirection { SameDirection, OppositeDirection @@ -285,15 +260,19 @@ class Panner : public std::vector, public Stateful, public sigc:: LinkDirection link_direction() const { return _link_direction; } void set_link_direction (LinkDirection); - + bool linked() const { return _linked; } void set_linked (bool yn); - sigc::signal LinkStateChanged; - sigc::signal StateChanged; /* for bypass */ + StreamPanner &streampanner( uint32_t n ) const { assert( n < _streampanners.size() ); return *_streampanners[n]; } + uint32_t npanners() const { return _streampanners.size(); } + + PBD::Signal0 Changed; /* panner and/or outputs count changed */ + PBD::Signal0 LinkStateChanged; + PBD::Signal0 StateChanged; /* for bypass */ /* only StreamPanner should call these */ - + void set_position (float x, StreamPanner& orig); void set_position (float x, float y, StreamPanner& orig); void set_position (float x, float y, float z, StreamPanner& orig); @@ -302,12 +281,41 @@ class Panner : public std::vector, public Stateful, public sigc:: int load (); + struct PanControllable : public AutomationControl { + PanControllable (Session& s, std::string name, Panner& p, Evoral::Parameter param) + : AutomationControl (s, param, + boost::shared_ptr(new AutomationList(param)), name) + , panner (p) + { assert(param.type() != NullAutomation); } + + AutomationList* alist() { return (AutomationList*)_list.get(); } + Panner& panner; + + void set_value (double); + double get_value (void) const; + }; + + boost::shared_ptr pan_control (int id, int chan=0) { + return automation_control (Evoral::Parameter (PanAutomation, chan, id)); + } + + boost::shared_ptr pan_control (int id, int chan=0) const { + return automation_control (Evoral::Parameter (PanAutomation, chan, id)); + } + + static std::string value_as_string (double); + private: + /* disallow copy construction */ + Panner (Panner const &); - Session& _session; + void distribute_no_automation(BufferSet& src, BufferSet& dest, nframes_t nframes, gain_t gain_coeff); + std::vector _streampanners; ///< one StreamPanner per input + std::vector outputs; uint32_t current_outs; bool _linked; bool _bypassed; + bool _mono; LinkDirection _link_direction; static float current_automation_version_number; @@ -315,7 +323,6 @@ class Panner : public std::vector, public Stateful, public sigc:: /* old school automation handling */ std::string automation_path; - void set_name (std::string); }; } // namespace ARDOUR