X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fpanner.cc;h=73326e12a4537cd82214eb7ce13a40dd57731535;hb=1aadfeba45e943123b6577bfca4635892be0d9e1;hp=6a6a84040718a0e6ee2252cdb52dd3f4228d9ff9;hpb=89e4d352445e9394073804f78fbd6845e6820f20;p=ardour.git diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index 6a6a840407..73326e12a4 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -32,21 +32,25 @@ #include -#include -#include -#include -#include +#include "pbd/error.h" +#include "pbd/failed_constructor.h" +#include "pbd/xml++.h" +#include "pbd/enumwriter.h" -#include -#include -#include +#include "evoral/Curve.hpp" -#include -#include +#include "ardour/session.h" +#include "ardour/panner.h" +#include "ardour/utils.h" +#include "ardour/audio_buffer.h" + +#include "ardour/runtime_functions.h" +#include "ardour/buffer_set.h" +#include "ardour/audio_buffer.h" #include "i18n.h" -#include +#include "pbd/mathfix.h" using namespace std; using namespace ARDOUR; @@ -78,7 +82,7 @@ StreamPanner::StreamPanner (Panner& p, Evoral::Parameter param) _muted = false; _control = boost::dynamic_pointer_cast( parent.control( param, true ) ); - + x = 0.5; y = 0.5; z = 0.5; @@ -496,7 +500,7 @@ EqualPowerStereoPanner::set_state (const XMLNode& node) for (XMLNodeConstIterator iter = node.children().begin(); iter != node.children().end(); ++iter) { - if ((*iter)->name() == X_("controllable")) { + if ((*iter)->name() == X_("Controllable")) { if ((prop = (*iter)->property("name")) != 0 && prop->value() == "panner") { _control->set_state (**iter); } @@ -699,7 +703,7 @@ Multi2dPanner::set_state (const XMLNode& node) /*---------------------------------------------------------------------- */ Panner::Panner (string name, Session& s) - : Processor(s, name, PostFader) + : Processor(s, name) { //set_name_old_auto (name); set_name (name); @@ -744,15 +748,93 @@ Panner::set_bypassed (bool yn) } +void +Panner::reset_to_default () +{ + vector positions; + + switch (outputs.size()) { + case 0: + case 1: + return; + } + + if (outputs.size() == 2) { + switch (_streampanners.size()) { + case 1: + _streampanners.front()->set_position (0.5); + _streampanners.front()->pan_control()->list()->reset_default (0.5); + return; + break; + case 2: + _streampanners.front()->set_position (0.0); + _streampanners.front()->pan_control()->list()->reset_default (0.0); + _streampanners.back()->set_position (1.0); + _streampanners.back()->pan_control()->list()->reset_default (1.0); + return; + default: + break; + } + } + + vector::iterator o; + vector::iterator p; + + for (o = outputs.begin(), p = _streampanners.begin(); o != outputs.end() && p != _streampanners.end(); ++o, ++p) { + (*p)->set_position ((*o).x, (*o).y); + } +} + +void +Panner::reset_streampanner (uint32_t which) +{ + if (which >= _streampanners.size() || which >= outputs.size()) { + return; + } + + switch (outputs.size()) { + case 0: + case 1: + return; + + case 2: + switch (_streampanners.size()) { + case 1: + /* stereo out, 1 stream, default = middle */ + _streampanners.front()->set_position (0.5); + _streampanners.front()->pan_control()->list()->reset_default (0.5); + break; + case 2: + /* stereo out, 2 streams, default = hard left/right */ + if (which == 0) { + _streampanners.front()->set_position (0.0); + _streampanners.front()->pan_control()->list()->reset_default (0.0); + } else { + _streampanners.back()->set_position (1.0); + _streampanners.back()->pan_control()->list()->reset_default (1.0); + } + break; + } + return; + + default: + _streampanners[which]->set_position (outputs[which].x, outputs[which].y); + } +} + void Panner::reset (uint32_t nouts, uint32_t npans) { uint32_t n; bool changed = false; + bool do_not_and_did_not_need_panning = ((nouts < 2) && (outputs.size() < 2)); - //configure_io( ChanCount( DataType::AUDIO, nout ), ChanCount( DataType::AUDIO, nin ) ) - - if (nouts < 2 || (nouts == outputs.size() && npans == _streampanners.size())) { + /* if new and old config don't need panning, or if + the config hasn't changed, we're done. + */ + + if (do_not_and_did_not_need_panning || + ((nouts == outputs.size()) && (npans == _streampanners.size()))) { return; } @@ -770,19 +852,25 @@ Panner::reset (uint32_t nouts, uint32_t npans) changed = true; } + if (nouts < 2) { + /* no need for panning with less than 2 outputs */ + goto send_changed; + } + switch (nouts) { case 0: + /* XXX: this can never happen */ break; case 1: + /* XXX: this can never happen */ fatal << _("programming error:") << X_("Panner::reset() called with a single output") << endmsg; /*NOTREACHED*/ break; - case 2: - /* line */ + case 2: // line outputs.push_back (Output (0, 0)); outputs.push_back (Output (1.0, 0)); @@ -871,6 +959,7 @@ Panner::reset (uint32_t nouts, uint32_t npans) } } + send_changed: if (changed) { Changed (); /* EMIT SIGNAL */ } @@ -882,7 +971,7 @@ void Panner::remove (uint32_t which) { vector::iterator i; - for (i = _streampanners.begin(); i != _streampanners.end() && which; ++i, --which); + for (i = _streampanners.begin(); i != _streampanners.end() && which; ++i, --which) {} if (i != _streampanners.end()) { delete *i; @@ -890,6 +979,8 @@ Panner::remove (uint32_t which) } } + +/** Remove all our StreamPanners */ void Panner::clear_panners () { @@ -921,23 +1012,30 @@ Panner::set_automation_state (AutoState state) AutoState Panner::automation_state () const { + boost::shared_ptr l; if (!empty()) { - return ((AutomationList*)_streampanners.front()->pan_control()->list().get())->automation_state (); - } else { - return Off; + boost::shared_ptr control = _streampanners.front()->pan_control(); + if (control) { + l = boost::dynamic_pointer_cast(control->list()); + } } + + return l ? l->automation_state() : Off; } AutoStyle Panner::automation_style () const { + boost::shared_ptr l; if (!empty()) { - return ((AutomationList*)_streampanners.front()->pan_control()->list().get())->automation_style (); - } else { - return Absolute; + boost::shared_ptr control = _streampanners.front()->pan_control(); + if (control) { + l = boost::dynamic_pointer_cast(control->list()); + } } -} + return l ? l->automation_style() : Absolute; +} struct PanPlugins { string name; @@ -970,12 +1068,6 @@ Panner::state (bool full) node.add_property (X_("link_direction"), enum_2_string (_link_direction)); node.add_property (X_("bypassed"), (bypassed() ? "yes" : "no")); - snprintf (buf, sizeof (buf), "%d", _streampanners.size()); - node.add_property (X_("ins"), buf); - snprintf (buf, sizeof (buf), "%d", outputs.size()); - node.add_property (X_("outs"), buf); - /* add each output */ - for (vector::iterator o = outputs.begin(); o != outputs.end(); ++o) { XMLNode* onode = new XMLNode (X_("Output")); snprintf (buf, sizeof (buf), "%.12g", (*o).x); @@ -1057,7 +1149,7 @@ Panner::set_state (const XMLNode& node) /* note that we assume that all the stream panners are of the same type. pretty good - assumption, but its still an assumption. + assumption, but it's still an assumption. */ sp = pan_plugins[i].factory (*this, Evoral::Parameter(PanAutomation, 0, num_panners)); @@ -1087,7 +1179,7 @@ Panner::set_state (const XMLNode& node) } } - reset(num_panners, outputs.size()); + reset (outputs.size (), num_panners); /* don't try to do old-school automation loading if it wasn't marked as existing */ if ((prop = node.property (X_("automation")))) { @@ -1256,7 +1348,7 @@ Panner::set_position (float xpos, float ypos, float zpos, StreamPanner& orig) } void -Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes_t nframes, nframes_t offset, gain_t gain_coeff) +Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes_t nframes, gain_t gain_coeff) { if (outbufs.count().n_audio() == 0) { // Don't want to lose audio... @@ -1277,37 +1369,37 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes /* only one output, and gain was zero, so make it silent */ - dst.silence(offset); + dst.silence (nframes); } else if (gain_coeff == 1.0f){ /* mix all buffers into the output */ // copy the first - dst.read_from(inbufs.get_audio(0), nframes, offset); + dst.read_from(inbufs.get_audio(0), nframes); // accumulate starting with the second - if (inbufs.count().n_audio() > 0) { - BufferSet::audio_iterator i = inbufs.audio_begin(); - for (++i; i != inbufs.audio_end(); ++i) { - dst.accumulate_from(*i, nframes, offset); - } - } + if (inbufs.count().n_audio() > 0) { + BufferSet::audio_iterator i = inbufs.audio_begin(); + for (++i; i != inbufs.audio_end(); ++i) { + dst.accumulate_from(*i, nframes); + } + } } else { /* mix all buffers into the output, scaling them all by the gain */ // copy the first - dst.read_from(inbufs.get_audio(0), nframes, offset); + dst.read_from(inbufs.get_audio(0), nframes); // accumulate (with gain) starting with the second - if (inbufs.count().n_audio() > 0) { - BufferSet::audio_iterator i = inbufs.audio_begin(); - for (++i; i != inbufs.audio_end(); ++i) { - dst.accumulate_with_gain_from(*i, nframes, offset, gain_coeff); - } - } + if (inbufs.count().n_audio() > 0) { + BufferSet::audio_iterator i = inbufs.audio_begin(); + for (++i; i != inbufs.audio_end(); ++i) { + dst.accumulate_with_gain_from(*i, nframes, gain_coeff); + } + } } @@ -1316,7 +1408,7 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes /* the terrible silence ... */ for (BufferSet::audio_iterator i = outbufs.audio_begin(); i != outbufs.audio_end(); ++i) { - i->silence(nframes, offset); + i->silence(nframes); } BufferSet::audio_iterator i = inbufs.audio_begin(); @@ -1327,7 +1419,7 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes } void -Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) +Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes) { if (outbufs.count().n_audio() == 0) { // Failing to deliver audio we were asked to deliver is a bug @@ -1349,7 +1441,7 @@ Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, nframes_t start gain_coeff = speed_quietning; } - distribute_no_automation(inbufs, outbufs, nframes, offset, gain_coeff); + distribute_no_automation(inbufs, outbufs, nframes, gain_coeff); return; } @@ -1362,12 +1454,12 @@ Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, nframes_t start // FIXME: apply gain automation? // copy the first - dst.read_from(inbufs.get_audio(0), nframes, offset); + dst.read_from(inbufs.get_audio(0), nframes); // accumulate starting with the second BufferSet::audio_iterator i = inbufs.audio_begin(); for (++i; i != inbufs.audio_end(); ++i) { - dst.accumulate_from(*i, nframes, offset); + dst.accumulate_from(*i, nframes); } return; @@ -1378,7 +1470,7 @@ Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, nframes_t start /* the terrible silence ... */ for (BufferSet::audio_iterator i = outbufs.audio_begin(); i != outbufs.audio_end(); ++i) { - i->silence(nframes, offset); + i->silence(nframes); } BufferSet::audio_iterator i = inbufs.audio_begin();