X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpanners%2Fvbap%2Fvbap.cc;h=e6cbd3655ff741be3e69946cafa3664768eafd54;hb=9192a2e96947e8ebb5e4bff2ad502222d9db65d4;hp=23683fde08e1680a870594a23402e4fd3d833ddf;hpb=a1a3f6c8265264227ce19f731bf1863aff229a94;p=ardour.git diff --git a/libs/panners/vbap/vbap.cc b/libs/panners/vbap/vbap.cc index 23683fde08..e6cbd3655f 100644 --- a/libs/panners/vbap/vbap.cc +++ b/libs/panners/vbap/vbap.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Paul Davis + Copyright (C) 2012 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 @@ -42,7 +42,7 @@ #include "vbap.h" #include "vbap_speakers.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace PBD; using namespace ARDOUR; @@ -72,7 +72,7 @@ void VBAPanner::Signal::resize_gains (uint32_t n) { gains.assign (n, 0.0); -} +} VBAPanner::VBAPanner (boost::shared_ptr p, boost::shared_ptr s) : Panner (p) @@ -81,6 +81,9 @@ VBAPanner::VBAPanner (boost::shared_ptr p, boost::shared_ptr _pannable->pan_azimuth_control->Changed.connect_same_thread (*this, boost::bind (&VBAPanner::update, this)); _pannable->pan_elevation_control->Changed.connect_same_thread (*this, boost::bind (&VBAPanner::update, this)); _pannable->pan_width_control->Changed.connect_same_thread (*this, boost::bind (&VBAPanner::update, this)); + if (!_pannable->has_state()) { + reset(); + } update (); } @@ -109,7 +112,7 @@ VBAPanner::configure_io (ChanCount in, ChanCount /* ignored - we use Speakers */ for (uint32_t i = 0; i < n; ++i) { Signal* s = new Signal (_pannable->session(), *this, i, _speakers->n_speakers()); _signals.push_back (s); - + } update (); @@ -123,10 +126,10 @@ VBAPanner::update () if (_signals.size() > 1) { double w = - (_pannable->pan_width_control->get_value()); - double signal_direction = _pannable->pan_azimuth_control->get_value() - (w/2); + double signal_direction = 1.0 - (_pannable->pan_azimuth_control->get_value() + (w/2)); double grd_step_per_signal = w / (_signals.size() - 1); for (vector::iterator s = _signals.begin(); s != _signals.end(); ++s) { - + Signal* signal = *s; int over = signal_direction; @@ -138,7 +141,7 @@ VBAPanner::update () signal_direction += grd_step_per_signal; } } else if (_signals.size() == 1) { - double center = _pannable->pan_azimuth_control->get_value() * 360.0; + double center = (1.0 - _pannable->pan_azimuth_control->get_value()) * 360.0; /* width has no role to play if there is only 1 signal: VBAP does not do "diffusion" of a single channel */ @@ -150,8 +153,8 @@ VBAPanner::update () SignalPositionChanged(); /* emit */ } -void -VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele) +void +VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele) { /* calculates gain factors using loudspeaker setup and given direction */ double cartdir[3]; @@ -159,8 +162,10 @@ VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele) int i,j,k; double small_g; double big_sm_g, gtmp[3]; + const int dimension = _speakers->dimension(); + assert(dimension == 2 || dimension == 3); - spherical_to_cartesian (azi, ele, 1.0, cartdir[0], cartdir[1], cartdir[2]); + spherical_to_cartesian (azi, ele, 1.0, cartdir[0], cartdir[1], cartdir[2]); big_sm_g = -100000.0; gains[0] = gains[1] = gains[2] = 0; @@ -170,12 +175,12 @@ VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele) small_g = 10000000.0; - for (j = 0; j < _speakers->dimension(); j++) { + for (j = 0; j < dimension; j++) { gtmp[j] = 0.0; - for (k = 0; k < _speakers->dimension(); k++) { - gtmp[j] += cartdir[k] * _speakers->matrix(i)[j*_speakers->dimension()+k]; + for (k = 0; k < dimension; k++) { + gtmp[j] += cartdir[k] * _speakers->matrix(i)[j * dimension + k]; } if (gtmp[j] < small_g) { @@ -187,8 +192,8 @@ VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele) big_sm_g = small_g; - gains[0] = gtmp[0]; - gains[1] = gtmp[1]; + gains[0] = gtmp[0]; + gains[1] = gtmp[1]; speaker_ids[0] = _speakers->speaker_for_tuple (i, 0); speaker_ids[1] = _speakers->speaker_for_tuple (i, 1); @@ -202,11 +207,11 @@ VBAPanner::compute_gains (double gains[3], int speaker_ids[3], int azi, int ele) } } } - + power = sqrt (gains[0]*gains[0] + gains[1]*gains[1] + gains[2]*gains[2]); if (power > 0) { - gains[0] /= power; + gains[0] /= power; gains[1] /= power; gains[2] /= power; } @@ -259,7 +264,7 @@ VBAPanner::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co assert (sz == obufs.count().n_audio()); int8_t *outputs = (int8_t*)alloca(sz); // on the stack, no malloc - + /* set initial state of each output "record" */ @@ -277,12 +282,12 @@ VBAPanner::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co if (signal->outputs[o] != -1) { /* used last time */ outputs[signal->outputs[o]] |= 1; - } + } if (signal->desired_outputs[o] != -1) { /* used this time */ outputs[signal->desired_outputs[o]] |= 1<<1; - } + } } /* at this point, we can test a speaker's status: @@ -291,7 +296,7 @@ VBAPanner::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co (*outputs[o] & 2) <= in use this time (*outputs[o] & 3) == 3 <= in use both times *outputs[o] == 0 <= not in use either time - + */ for (int o = 0; o < 3; ++o) { @@ -305,14 +310,14 @@ VBAPanner::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co pan = gain_coefficient * signal->desired_gains[o]; if (pan == 0.0 && signal->gains[output] == 0.0) { - + /* nothing deing delivered to this output */ signal->gains[output] = 0.0; - + } else if (fabs (pan - signal->gains[output]) > 0.00001) { - - /* signal to this output but the gain coefficient has changed, so + + /* signal to this output but the gain coefficient has changed, so interpolate between them. */ @@ -321,10 +326,10 @@ VBAPanner::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co signal->gains[output] = pan; } else { - + /* signal to this output, same gain as before so just copy with gain */ - + mix_buffers_with_gain (obufs.get_audio (output).data(),src,nframes,pan); signal->gains[output] = pan; } @@ -349,9 +354,9 @@ VBAPanner::distribute_one (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain_co */ } -void +void VBAPanner::distribute_one_automated (AudioBuffer& /*src*/, BufferSet& /*obufs*/, - framepos_t /*start*/, framepos_t /*end*/, + framepos_t /*start*/, framepos_t /*end*/, pframes_t /*nframes*/, pan_t** /*buffers*/, uint32_t /*which*/) { /* XXX to be implemented */ @@ -385,7 +390,7 @@ VBAPanner::out() const return ChanCount (DataType::AUDIO, _speakers->n_speakers()); } -std::set +std::set VBAPanner::what_can_be_automated() const { set s; @@ -398,15 +403,15 @@ VBAPanner::what_can_be_automated() const } return s; } - + string VBAPanner::describe_parameter (Evoral::Parameter p) { switch (p.type()) { case PanAzimuthAutomation: - return _("Direction"); + return _("Azimuth"); case PanWidthAutomation: - return _("Diffusion"); + return _("Width"); case PanElevationAutomation: return _("Elevation"); default: @@ -414,24 +419,24 @@ VBAPanner::describe_parameter (Evoral::Parameter p) } } -string -VBAPanner::value_as_string (boost::shared_ptr ac) const +string +VBAPanner::value_as_string (boost::shared_ptr ac) const { /* DO NOT USE LocaleGuard HERE */ double val = ac->get_value(); switch (ac->parameter().type()) { case PanAzimuthAutomation: /* direction */ - return string_compose (_("%1\u00B0"), int (rint (val * 360.0))); - + return string_compose (_("%1\u00B0"), (int (rint (val * 360.0))+180)%360); + case PanWidthAutomation: /* diffusion */ return string_compose (_("%1%%"), (int) floor (100.0 * fabs(val))); case PanElevationAutomation: /* elevation */ return string_compose (_("%1\u00B0"), (int) floor (90.0 * fabs(val))); - + default: - return _pannable->value_as_string (ac); + return _("unused"); } } @@ -446,7 +451,7 @@ VBAPanner::signal_position (uint32_t n) const } boost::shared_ptr -VBAPanner::get_speakers () const +VBAPanner::get_speakers () const { return _speakers->parent(); } @@ -458,26 +463,30 @@ VBAPanner::set_position (double p) int over = p; over -= (p >= 0) ? 0 : 1; p -= (double)over; - _pannable->pan_azimuth_control->set_value (p); + _pannable->pan_azimuth_control->set_value (p, Controllable::NoGroup); } void VBAPanner::set_width (double w) { - _pannable->pan_width_control->set_value (min (1.0, max (-1.0, w))); + _pannable->pan_width_control->set_value (min (1.0, max (-1.0, w)), Controllable::NoGroup); } void VBAPanner::set_elevation (double e) { - _pannable->pan_elevation_control->set_value (min (1.0, max (0.0, e))); + _pannable->pan_elevation_control->set_value (min (1.0, max (0.0, e)), Controllable::NoGroup); } void VBAPanner::reset () { - set_position (0); - set_width (1); + set_position (.5); + if (_signals.size() > 1) { + set_width (1.0 - (1.0 / (double)_signals.size())); + } else { + set_width (1.0); + } set_elevation (0); update ();