summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2014-01-15 09:37:20 +0100
committerRobin Gareus <robin@gareus.org>2014-01-15 09:37:20 +0100
commit58def58bf50f29e42babdb5de7ca34819c00909f (patch)
tree75ac1c64665e5a33e074cb2011f0d3f955fcf72b
parent35c170937de6150ae09154f96e4920d30e83f6ce (diff)
VBAP GUI convention: top == front ^= azimuth == .5
This allows to move from stereo,mono panners to VBAP and back and also facilitates sharing pannables of all currently existing panners with semantically similar results. (somewhat dirty solution, this retains PBD::spherical_to_cartesian and maps angles pretty much everywhere else)
-rw-r--r--gtk2_ardour/panner2d.cc55
-rw-r--r--libs/ardour/speakers.cc10
-rw-r--r--libs/panners/vbap/vbap.cc10
3 files changed, 44 insertions, 31 deletions
diff --git a/gtk2_ardour/panner2d.cc b/gtk2_ardour/panner2d.cc
index 0f8b46aa56..a3befff5cf 100644
--- a/gtk2_ardour/panner2d.cc
+++ b/gtk2_ardour/panner2d.cc
@@ -166,6 +166,7 @@ Panner2d::on_size_allocate (Gtk::Allocation& alloc)
radius = min (width, height);
radius -= border;
radius /= 2;
+ radius = rint(radius) + .5;
hoffset = max ((double) (width - height), border);
voffset = max ((double) (height - width), border);
@@ -251,12 +252,8 @@ Panner2d::handle_position_change ()
uint32_t n;
double w = panner_shell->pannable()->pan_width_control->get_value();
- if (have_elevation) {
- position.position = AngularVector (panner_shell->pannable()->pan_azimuth_control->get_value() * 360.0,
- panner_shell->pannable()->pan_elevation_control->get_value() * 90.0);
- } else {
- position.position = AngularVector (panner_shell->pannable()->pan_azimuth_control->get_value() * 360.0, 0);
- }
+ position.position = AngularVector (panner_shell->pannable()->pan_azimuth_control->get_value() * 360.0,
+ panner_shell->pannable()->pan_elevation_control->get_value() * 90.0);
for (uint32_t i = 0; i < signals.size(); ++i) {
signals[i]->position = panner_shell->panner()->signal_position (i);
@@ -300,7 +297,11 @@ Panner2d::find_closest_object (gdouble x, gdouble y, bool& is_signal)
/* start with the position itself */
- position.position.cartesian (c);
+ PBD::AngularVector dp = position.position;
+ if (!have_elevation) dp.ele = 0;
+ dp.azi = 270 - dp.azi;
+ dp.cartesian (c);
+
cart_to_gtk (c);
best_distance = sqrt ((c.x - x) * (c.x - x) +
(c.y - y) * (c.y - y));
@@ -342,9 +343,11 @@ Panner2d::find_closest_object (gdouble x, gdouble y, bool& is_signal)
if (!closest) {
for (Targets::const_iterator i = speakers.begin(); i != speakers.end(); ++i) {
candidate = *i;
-
- candidate->position.cartesian (c);
- cart_to_gtk (c);
+ PBD::AngularVector sp = candidate->position;
+ sp.azi = 270 -sp.azi;
+ CartesianVector c;
+ sp.cartesian (c);
+ cart_to_gtk (c);
distance = sqrt ((c.x - x) * (c.x - x) +
(c.y - y) * (c.y - y));
@@ -426,14 +429,14 @@ Panner2d::on_expose_event (GdkEventExpose *event)
/* horizontal line of "crosshairs" */
cairo_set_source_rgba (cr, 0.282, 0.517, 0.662, 1.0);
- cairo_move_to (cr, 0.0, rint(radius) + .5);
- cairo_line_to (cr, diameter, rint(radius) + .5);
+ cairo_move_to (cr, 0.0, radius);
+ cairo_line_to (cr, diameter, radius);
cairo_stroke (cr);
/* vertical line of "crosshairs" */
- cairo_move_to (cr, rint(radius) + .5, 0);
- cairo_line_to (cr, rint(radius) + .5, diameter);
+ cairo_move_to (cr, radius, 0);
+ cairo_line_to (cr, radius, diameter);
cairo_stroke (cr);
/* the circle on which signals live */
@@ -456,15 +459,17 @@ Panner2d::on_expose_event (GdkEventExpose *event)
}
if (!panner_shell->bypassed()) {
+ /* convention top == front ^= azimuth == .5 (same as stereo/mono panners) */
if (signals.size() > 1) {
/* arc to show "diffusion" */
double width_angle = fabs (panner_shell->pannable()->pan_width_control->get_value()) * 2 * M_PI;
- double position_angle = (2 * M_PI) - panner_shell->pannable()->pan_azimuth_control->get_value() * 2 * M_PI;
+ double position_angle = panner_shell->pannable()->pan_azimuth_control->get_value() * 2 * M_PI;
cairo_save (cr);
cairo_translate (cr, radius, radius);
+ cairo_rotate (cr, M_PI / 2.0);
cairo_rotate (cr, position_angle - (width_angle/2.0));
cairo_move_to (cr, 0, 0);
cairo_arc_negative (cr, 0, 0, radius, width_angle, 0.0);
@@ -493,7 +498,10 @@ Panner2d::on_expose_event (GdkEventExpose *event)
/* draw position */
- position.position.cartesian (c);
+ PBD::AngularVector dp = position.position;
+ if (!have_elevation) dp.ele = 0;
+ dp.azi = 270 - dp.azi;
+ dp.cartesian (c);
cart_to_gtk (c);
cairo_new_path (cr);
@@ -505,7 +513,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
/* signals */
- if (signals.size() > 1) {
+ if (signals.size() > 0) {
for (Targets::iterator i = signals.begin(); i != signals.end(); ++i) {
Target* signal = *i;
@@ -516,6 +524,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
*/
PBD::AngularVector sp = signal->position;
if (!have_elevation) sp.ele = 0;
+ sp.azi += 270.0;
sp.cartesian (c);
cart_to_gtk (c);
@@ -553,9 +562,10 @@ Panner2d::on_expose_event (GdkEventExpose *event)
if (speaker->visible) {
+ PBD::AngularVector sp = speaker->position;
+ sp.azi += 270.0;
CartesianVector c;
-
- speaker->position.cartesian (c);
+ sp.cartesian (c);
cart_to_gtk (c);
snprintf (buf, sizeof (buf), "%d", n);
@@ -564,7 +574,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
cairo_move_to (cr, c.x, c.y);
cairo_save (cr);
- cairo_rotate (cr, -(speaker->position.azi/360.0) * (2.0 * M_PI));
+ cairo_rotate (cr, -(sp.azi/360.0) * (2.0 * M_PI));
if (small) {
cairo_scale (cr, 0.8, 0.8);
} else {
@@ -588,7 +598,8 @@ Panner2d::on_expose_event (GdkEventExpose *event)
/* move the text in just a bit */
- AngularVector textpos (speaker->position.azi, speaker->position.ele, 0.85);
+ AngularVector textpos (speaker->position.azi + 270.0, speaker->position.ele, 0.85);
+
textpos.cartesian (c);
cart_to_gtk (c);
cairo_move_to (cr, c.x, c.y);
@@ -716,6 +727,7 @@ Panner2d::handle_motion (gint evx, gint evy, GdkModifierType state)
if (!have_elevation) {
clamp_to_circle (cp.x, cp.y);
cp.angular (av);
+ av.azi = fmod(270 - av.azi, 360);
if (drag_target == &position) {
double degree_fract = av.azi / 360.0;
panner_shell->panner()->set_position (degree_fract);
@@ -727,6 +739,7 @@ Panner2d::handle_motion (gint evx, gint evy, GdkModifierType state)
double r2d = 180.0 / M_PI;
av.azi = r2d * atan2(cp.y, cp.x);
av.ele = r2d * asin(cp.z);
+ av.azi = fmod(270 - av.azi, 360);
if (drag_target == &position) {
double azi_fract = av.azi / 360.0;
diff --git a/libs/ardour/speakers.cc b/libs/ardour/speakers.cc
index 2acc9659ef..bbad254f6e 100644
--- a/libs/ardour/speakers.cc
+++ b/libs/ardour/speakers.cc
@@ -149,7 +149,7 @@ Speakers::move_speaker (int id, const AngularVector& new_position)
void
Speakers::setup_default_speakers (uint32_t n)
{
- double o = 90.0;
+ double o = 180.0;
/* default assignment of speaker position for n speakers */
@@ -229,12 +229,12 @@ Speakers::setup_default_speakers (uint32_t n)
*/
if (n % 2) {
- deg = 90.0 - degree_step;
+ deg = 360 + o + degree_step;
} else {
- deg = 90.0;
+ deg = 360 + o;
}
- for (i = 0; i < n; ++i, deg += degree_step) {
- add_speaker (AngularVector (deg, 0.0));
+ for (i = 0; i < n; ++i, deg -= degree_step) {
+ add_speaker (AngularVector (fmod(deg, 360), 0.0));
}
}
}
diff --git a/libs/panners/vbap/vbap.cc b/libs/panners/vbap/vbap.cc
index e15e2abb4c..2ab91cf3c4 100644
--- a/libs/panners/vbap/vbap.cc
+++ b/libs/panners/vbap/vbap.cc
@@ -122,7 +122,7 @@ 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<Signal*>::iterator s = _signals.begin(); s != _signals.end(); ++s) {
@@ -137,7 +137,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 */
@@ -421,7 +421,7 @@ VBAPanner::value_as_string (boost::shared_ptr<AutomationControl> ac) const
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)));
@@ -475,11 +475,11 @@ VBAPanner::set_elevation (double e)
void
VBAPanner::reset ()
{
- set_position (0);
+ set_position (.5);
if (_signals.size() > 1) {
set_width (1.0 - (1.0 / (double)_signals.size()));
} else {
- set_width (0);
+ set_width (1.0);
}
set_elevation (0);