X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fardour%2Fspeakers.cc;h=7c7b02f0cc796ab4bbda3b637d8f186aac1e289e;hb=d01cb7910faddbf13b7190ceca990a2cafb71f95;hp=c5495f204de5ac98b5c8f703a953b24d38c1b877;hpb=553cf2982c4905c5a08f305ce2772beaa8c50324;p=ardour.git diff --git a/libs/ardour/speakers.cc b/libs/ardour/speakers.cc index c5495f204d..7c7b02f0cc 100644 --- a/libs/ardour/speakers.cc +++ b/libs/ardour/speakers.cc @@ -16,93 +16,289 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "pbd/error.h" +#include "pbd/convert.h" +#include "pbd/locale_guard.h" + #include "ardour/speaker.h" #include "ardour/speakers.h" +#include "i18n.h" + using namespace ARDOUR; using namespace PBD; using namespace std; Speaker::Speaker (int i, const AngularVector& position) - : id (i) + : id (i) +{ + move (position); +} + +Speaker::Speaker (Speaker const & o) + : id (o.id) + , _coords (o._coords) + , _angles (o._angles) { - move (position); + +} + +Speaker & +Speaker::operator= (Speaker const & o) +{ + if (&o == this) { + return *this; + } + + id = o.id; + _coords = o._coords; + _angles = o._angles; + + return *this; } void Speaker::move (const AngularVector& new_position) { - _angles = new_position; - _angles.cartesian (_coords); + _angles = new_position; + _angles.cartesian (_coords); + + PositionChanged (); /* EMIT SIGNAL */ } Speakers::Speakers () { } +Speakers::Speakers (const Speakers& s) + : Stateful () +{ + _speakers = s._speakers; +} + Speakers::~Speakers () { } +Speakers& +Speakers::operator= (const Speakers& s) +{ + if (&s != this) { + _speakers = s._speakers; + } + return *this; +} + void Speakers::dump_speakers (ostream& o) { - for (vector::iterator i = _speakers.begin(); i != _speakers.end(); ++i) { - o << "Speaker " << (*i).id << " @ " - << (*i).coords().x << ", " << (*i).coords().y << ", " << (*i).coords().z - << " azimuth " << (*i).angles().azi - << " elevation " << (*i).angles().ele - << " distance " << (*i).angles().length - << endl; - } + for (vector::iterator i = _speakers.begin(); i != _speakers.end(); ++i) { + o << "Speaker " << (*i).id << " @ " + << (*i).coords().x << ", " << (*i).coords().y << ", " << (*i).coords().z + << " azimuth " << (*i).angles().azi + << " elevation " << (*i).angles().ele + << " distance " << (*i).angles().length + << endl; + } } void Speakers::clear_speakers () { - _speakers.clear (); - update (); + _speakers.clear (); + update (); } -int +int Speakers::add_speaker (const AngularVector& position) { - int id = _speakers.size(); + int id = _speakers.size(); - cerr << "Added speaker " << id << " at " << position.azi << " /= " << position.ele << endl; + _speakers.push_back (Speaker (id, position)); + update (); - _speakers.push_back (Speaker (id, position)); - update (); - - dump_speakers (cerr); - Changed (); + Changed (); - return id; -} + return id; +} void Speakers::remove_speaker (int id) { - for (vector::iterator i = _speakers.begin(); i != _speakers.end(); ) { - if ((*i).id == id) { - i = _speakers.erase (i); - update (); - break; - } - } + for (vector::iterator i = _speakers.begin(); i != _speakers.end(); ++i) { + if (i->id == id) { + i = _speakers.erase (i); + update (); + break; + } + } } void Speakers::move_speaker (int id, const AngularVector& new_position) { - for (vector::iterator i = _speakers.begin(); i != _speakers.end(); ++i) { - if ((*i).id == id) { - (*i).move (new_position); - update (); - break; - } + for (vector::iterator i = _speakers.begin(); i != _speakers.end(); ++i) { + if ((*i).id == id) { + (*i).move (new_position); + update (); + break; + } + } +} + +void +Speakers::setup_default_speakers (uint32_t n) +{ + double o = 180.0; + + /* default assignment of speaker position for n speakers */ + + assert (n>0); + + switch (n) { + case 1: + add_speaker (AngularVector (o +0.0, 0.0)); + break; + + case 2: + add_speaker (AngularVector (o +60.0, 0.0)); + add_speaker (AngularVector (o -60.0, 0.0)); + break; + + case 3: + add_speaker (AngularVector (o +60.0, 0.0)); + add_speaker (AngularVector (o -60.0, 0.0)); + add_speaker (AngularVector (o +180.0, 0.0)); + break; + case 4: + /* 4.0 with regular spacing */ + add_speaker (AngularVector (o +45.0, 0.0)); + add_speaker (AngularVector (o -45.0, 0.0)); + add_speaker (AngularVector (o +135.0, 0.0)); + add_speaker (AngularVector (o -135.0, 0.0)); + break; + case 5: + /* 5.0 with regular spacing */ + add_speaker (AngularVector (o +72.0, 0.0)); + add_speaker (AngularVector (o -72.0, 0.0)); + add_speaker (AngularVector (o +0.0, 0.0)); + add_speaker (AngularVector (o +144.0, 0.0)); + add_speaker (AngularVector (o -144.0, 0.0)); + break; + case 6: + /* 6.0 with regular spacing */ + add_speaker (AngularVector (o +60.0, 0.0)); + add_speaker (AngularVector (o -60.0, 0.0)); + add_speaker (AngularVector (o +0.0, 0.0)); + add_speaker (AngularVector (o +120.0, 0.0)); + add_speaker (AngularVector (o -120.0, 0.0)); + add_speaker (AngularVector (o +180.0, 0.0)); + break; + case 7: + /* 7.0 with regular front spacing */ + add_speaker (AngularVector (o +45.0, 0.0)); + add_speaker (AngularVector (o -45.0, 0.0)); + add_speaker (AngularVector (o +0.0, 0.0)); + add_speaker (AngularVector (o +90.0, 0.0)); + add_speaker (AngularVector (o -90.0, 0.0)); + add_speaker (AngularVector (o +150.0, 0.0)); + add_speaker (AngularVector (o -150.0, 0.0)); + break; + case 10: + /* 5+4 with 45°/90° spacing */ + add_speaker (AngularVector (o +45.0, 0.0)); + add_speaker (AngularVector (o -45.0, 0.0)); + add_speaker (AngularVector (o +0.0, 0.0)); + add_speaker (AngularVector (o +135.0, 0.0)); + add_speaker (AngularVector (o -135.0, 0.0)); + add_speaker (AngularVector (o +45.0, 60.0)); + add_speaker (AngularVector (o -45.0, 60.0)); + add_speaker (AngularVector (o +135.0, 60.0)); + add_speaker (AngularVector (o -135.0, 60.0)); + add_speaker (AngularVector (o +0.0, 90.0)); + break; + + default: + { + double degree_step = 360.0 / n; + double deg; + uint32_t i; + + /* even number of speakers? make sure the top two are either side of "top". + otherwise, just start at the "top" (90.0 degrees) and rotate around + */ + + if (n % 2) { + deg = 360 + o + degree_step; + } else { + deg = 360 + o; + } + for (i = 0; i < n; ++i, deg -= degree_step) { + add_speaker (AngularVector (fmod(deg, 360), 0.0)); + } + } } } +XMLNode& +Speakers::get_state () +{ + XMLNode* node = new XMLNode (X_("Speakers")); + char buf[32]; + LocaleGuard lg (X_("C")); + + for (vector::const_iterator i = _speakers.begin(); i != _speakers.end(); ++i) { + XMLNode* speaker = new XMLNode (X_("Speaker")); + snprintf (buf, sizeof (buf), "%.12g", (*i).angles().azi); + speaker->add_property (X_("azimuth"), buf); + snprintf (buf, sizeof (buf), "%.12g", (*i).angles().ele); + speaker->add_property (X_("elevation"), buf); + snprintf (buf, sizeof (buf), "%.12g", (*i).angles().length); + speaker->add_property (X_("distance"), buf); + node->add_child_nocopy (*speaker); + } + + return *node; +} + +int +Speakers::set_state (const XMLNode& node, int /*version*/) +{ + XMLNodeConstIterator i; + const XMLProperty* prop; + double a, e, d; + LocaleGuard lg (X_("C")); + int n = 0; + + _speakers.clear (); + + for (i = node.children().begin(); i != node.children().end(); ++i, ++n) { + if ((*i)->name() == X_("Speaker")) { + if ((prop = (*i)->property (X_("azimuth"))) == 0) { + warning << _("Speaker information is missing azimuth - speaker ignored") << endmsg; + continue; + } + a = atof (prop->value()); + + if ((prop = (*i)->property (X_("elevation"))) == 0) { + warning << _("Speaker information is missing elevation - speaker ignored") << endmsg; + continue; + } + e = atof (prop->value()); + + if ((prop = (*i)->property (X_("distance"))) == 0) { + warning << _("Speaker information is missing distance - speaker ignored") << endmsg; + continue; + } + d = atof (prop->value()); + + add_speaker (AngularVector (a, e, d)); + } + } + + update (); + + return 0; +}