X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Fpanner.h;h=1838fb5f56b807c97227b6fa767f291af1b8b25b;hb=71a90399fe8561310b848fbfb8d28a65a395a6c1;hp=9d6a248de0af7b3c2c7f69b7b0b798a7ebf400e1;hpb=e8fede43eeda1fba263f79ac5647bc7abf955733;p=ardour.git diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h index 9d6a248de0..1838fb5f56 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-2011 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 @@ -26,299 +26,177 @@ #include #include -#include "pbd/stateful.h" -#include "pbd/controllable.h" #include "pbd/cartesian.h" +#include "pbd/signals.h" +#include "pbd/stateful.h" +#include "ardour/libardour_visibility.h" #include "ardour/types.h" #include "ardour/automation_control.h" -#include "ardour/processor.h" +#include "ardour/automatable.h" + + +/* This section is for actual panners to use. They will include this file, + * declare ARDOURPANNER_DLL_EXPORTS during compilation, and ... voila. + */ + +#ifdef ARDOURPANNER_DLL_EXPORTS // defined if we are building a panner implementation + #define ARDOURPANNER_API LIBARDOUR_DLL_EXPORT + #else + #define ARDOURPANNER_API LIBARDOUR_DLL_IMPORT + #endif +#define ARDOURPANNER_LOCAL LIBARDOUR_DLL_LOCAL namespace ARDOUR { class Session; -class Panner; +class Pannable; class BufferSet; class AudioBuffer; class Speakers; -class StreamPanner : public PBD::Stateful +class LIBARDOUR_API Panner : public PBD::Stateful, public PBD::ScopedConnectionList { - public: - StreamPanner (Panner& p, Evoral::Parameter param); - ~StreamPanner (); - - void set_muted (bool yn); - bool muted() const { return _muted; } - - const PBD::AngularVector& get_position() const { return _angles; } - const PBD::AngularVector& get_effective_position() const { return _effective_angles; } - void set_position (const PBD::AngularVector&, bool link_call = false); - void set_diffusion (double); - - void distribute (AudioBuffer &, BufferSet &, gain_t, pframes_t); - void distribute_automated (AudioBuffer &, BufferSet &, framepos_t, framepos_t, pframes_t, pan_t **); - - /* the basic StreamPanner API */ - - /** - * 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, pframes_t nframes) = 0; - virtual void do_distribute_automated (AudioBuffer& src, BufferSet& obufs, - framepos_t start, framepos_t end, pframes_t nframes, - pan_t** buffers) = 0; +public: + Panner (boost::shared_ptr); + ~Panner (); - boost::shared_ptr pan_control() { return _control; } + virtual boost::shared_ptr get_speakers() const { return boost::shared_ptr(); } - PBD::Signal0 Changed; /* for position or diffusion */ - PBD::Signal0 StateChanged; /* for mute, mono */ + virtual ChanCount in() const = 0; + virtual ChanCount out() const = 0; - 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 (std::istream&, std::string path, uint32_t&) = 0; - - struct PanControllable : public AutomationControl { - PanControllable (Session& s, std::string name, StreamPanner* p, Evoral::Parameter param) - : AutomationControl (s, param, - boost::shared_ptr(new AutomationList(param)), name) - , streampanner (p) - { assert (param.type() == PanAutomation); } - - AutomationList* alist() { return (AutomationList*)_list.get(); } - StreamPanner* streampanner; - - void set_value (double); - double get_value (void) const; - double lower () const; - }; - - protected: - friend class Panner; - Panner& parent; - - void set_mono (bool); - - PBD::AngularVector _angles; - PBD::AngularVector _effective_angles; - double _diffusion; - - bool _muted; - bool _mono; - - boost::shared_ptr _control; + virtual void configure_io (ARDOUR::ChanCount /*in*/, ARDOUR::ChanCount /*out*/) {} - XMLNode& get_state (); + /* derived implementations of these methods must indicate + whether it is legal for a Controllable to use the + value of the argument (post-call) in a call to + Controllable::set_value(). - /* Update internal parameters based on this.angles */ - virtual void update () = 0; -}; + they have a choice of: -class BaseStereoPanner : public StreamPanner -{ - public: - BaseStereoPanner (Panner&, Evoral::Parameter param); - ~BaseStereoPanner (); - - /* this class just leaves the pan law itself to be defined - by the update(), do_distribute_automated() - methods. derived classes also need a factory method - and a type name. See EqualPowerStereoPanner as an example. + * return true, leave argument unchanged + * return true, modify argument + * return false */ - void do_distribute (AudioBuffer& src, BufferSet& obufs, gain_t gain_coeff, pframes_t nframes); + virtual bool clamp_position (double&) { return true; } + virtual bool clamp_width (double&) { return true; } + virtual bool clamp_elevation (double&) { return true; } - static double azimuth_to_lr_fract (double azi) { - /* 180.0 degrees=> left => 0.0 */ - /* 0.0 degrees => right => 1.0 */ - return 1.0 - (azi/180.0); - } - - static double lr_fract_to_azimuth (double fract) { - /* fract = 0.0 => degrees = 180.0 => left */ - /* fract = 1.0 => degrees = 0.0 => right */ - return 180.0 - (fract * 180.0); - } - - /* old school automation loading */ - - int load (std::istream&, std::string path, uint32_t&); - - protected: - float left; - float right; - float desired_left; - float desired_right; - float left_interp; - float right_interp; -}; + virtual std::pair position_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); } + virtual std::pair width_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); } + virtual std::pair elevation_range () const { return std::make_pair (-DBL_MAX, DBL_MAX); } -class EqualPowerStereoPanner : public BaseStereoPanner -{ - public: - EqualPowerStereoPanner (Panner&, Evoral::Parameter param); - ~EqualPowerStereoPanner (); + virtual void set_position (double) { } + virtual void set_width (double) { } + virtual void set_elevation (double) { } - void do_distribute_automated (AudioBuffer& src, BufferSet& obufs, - framepos_t start, framepos_t end, pframes_t nframes, - pan_t** buffers); + virtual double position () const { return 0.0; } + virtual double width () const { return 0.0; } + virtual double elevation () const { return 0.0; } - void get_current_coefficients (pan_t*) const; - void get_desired_coefficients (pan_t*) const; + virtual PBD::AngularVector signal_position (uint32_t) const { return PBD::AngularVector(); } - static StreamPanner* factory (Panner&, Evoral::Parameter param, Speakers&); - static std::string name; + virtual void reset () = 0; - XMLNode& state (bool full_state); - XMLNode& get_state (void); - int set_state (const XMLNode&, int version); + /* azimut, width or elevation updated -> recalc signal_position -> emit Changed */ + PBD::Signal0 SignalPositionChanged; - private: - void update (); -}; + void set_automation_state (AutoState); + AutoState automation_state() const; + void set_automation_style (AutoStyle); + AutoStyle automation_style() const; -/** 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: - struct Output { - PBD::AngularVector position; - pan_t current_pan; - pan_t desired_pan; - - Output (const PBD::AngularVector& a) - : position (a), current_pan (0), desired_pan (0) {} + virtual std::set what_can_be_automated() const; + virtual std::string describe_parameter (Evoral::Parameter); + virtual std::string value_as_string (boost::shared_ptr) const; - }; + bool touching() const; - Panner (std::string name, Session&); - virtual ~Panner (); + static double azimuth_to_lr_fract (double azi) { + /* 180.0 degrees=> left => 0.0 */ + /* 0.0 degrees => right => 1.0 */ - void clear_panners (); - bool empty() const { return _streampanners.empty(); } + /* humans can only distinguish 1 degree of arc between two positions, + so force azi back to an integral value before computing + */ - void set_automation_state (AutoState); - AutoState automation_state() const; - void set_automation_style (AutoStyle); - AutoStyle automation_style() const; - bool touching() const; + return 1.0 - (rint(azi)/180.0); + } - std::string describe_parameter (Evoral::Parameter param); + static double lr_fract_to_azimuth (double fract) { + /* fract = 0.0 => degrees = 180.0 => left */ + /* fract = 1.0 => degrees = 0.0 => right */ - bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return true; }; + /* humans can only distinguish 1 degree of arc between two positions, + so force azi back to an integral value after computing + */ - /// The fundamental Panner function - void run (BufferSet& src, BufferSet& dest, framepos_t start_frame, framepos_t end_frames, pframes_t nframes); + return rint (180.0 - (fract * 180.0)); + } - bool bypassed() const { return _bypassed; } - void set_bypassed (bool yn); - bool mono () const { return _mono; } - void set_mono (bool); + /** + * Pan some input buffers to a number of output buffers. + * + * @param ibufs Input buffers (one per panner input) + * @param obufs Output buffers (one per panner output). + * @param gain_coeff fixed, additional gain coefficient to apply to output samples. + * @param nframes Number of frames in the input. + * + * Derived panners can choose to implement these if they need to gain more + * control over the panning algorithm. The default is to call + * distribute_one() or distribute_one_automated() on each input buffer to + * deliver it to each output buffer. + * + * If a panner does not need to override this default behaviour, it can + * just implement distribute_one() and distribute_one_automated() (below). + */ + virtual void distribute (BufferSet& ibufs, BufferSet& obufs, gain_t gain_coeff, pframes_t nframes); + virtual void distribute_automated (BufferSet& ibufs, BufferSet& obufs, + framepos_t start, framepos_t end, pframes_t nframes, + pan_t** buffers); - 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 (); + int set_state (const XMLNode&, int version); + XMLNode& get_state (); - XMLNode& get_state (void); - XMLNode& state (bool full); - int set_state (const XMLNode&, int version); + boost::shared_ptr pannable() const { return _pannable; } static bool equivalent (pan_t a, pan_t b) { return fabsf (a - b) < 0.002; // about 1 degree of arc for a stereo panner } + static bool equivalent (const PBD::AngularVector& a, const PBD::AngularVector& b) { - /* XXX azimuth only, at present */ + /* XXX azimuth only, at present */ return fabs (a.azi - b.azi) < 1.0; } - void move_output (uint32_t, float x, float y); - uint32_t nouts() const { return outputs.size(); } - Output& output (uint32_t n) { return outputs[n]; } - - enum LinkDirection { - SameDirection, - OppositeDirection - }; - - LinkDirection link_direction() const { return _link_direction; } - void set_link_direction (LinkDirection); - - bool linked() const { return _linked; } - void set_linked (bool yn); - - 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 (const PBD::AngularVector&, StreamPanner& orig); - - /* old school automation */ - - int load (); - - boost::shared_ptr pan_control (int id, uint32_t chan=0) { - return automation_control (Evoral::Parameter (PanAutomation, chan, id)); - } - - boost::shared_ptr pan_control (int id, uint32_t chan=0) const { - return automation_control (Evoral::Parameter (PanAutomation, chan, id)); - } + virtual void freeze (); + virtual void thaw (); - boost::shared_ptr direction_control () { - return automation_control (Evoral::Parameter (PanAutomation, 0, 100)); - } +protected: + boost::shared_ptr _pannable; - boost::shared_ptr width_control () { - return automation_control (Evoral::Parameter (PanAutomation, 0, 200)); - } + virtual void distribute_one (AudioBuffer&, BufferSet& obufs, gain_t gain_coeff, pframes_t nframes, uint32_t which) = 0; + virtual void distribute_one_automated (AudioBuffer&, BufferSet& obufs, + framepos_t start, framepos_t end, pframes_t nframes, + pan_t** buffers, uint32_t which) = 0; - void set_stereo_position (double); - void set_stereo_width (double); - bool set_stereo_pan (double pos, double width); - - static std::string value_as_string (double); - - private: - /* disallow copy construction */ - Panner (Panner const &); - - void distribute_no_automation(BufferSet& src, BufferSet& dest, pframes_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; - - void setup_speakers (uint32_t nouts); - void setup_meta_controls (); - - /* old school automation handling */ - - std::string automation_path; + int32_t _frozen; }; -} // namespace ARDOUR +} // namespace + +extern "C" { +struct LIBARDOUR_API PanPluginDescriptor { + std::string name; + std::string panner_uri; + std::string gui_uri; + int32_t in; + int32_t out; + uint32_t priority; + ARDOUR::Panner* (*factory)(boost::shared_ptr, boost::shared_ptr); +}; +} -#endif /*__ardour_panner_h__ */ +#endif /* __ardour_panner_h__ */