mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-09 08:14:58 +01:00
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)
This commit is contained in:
parent
35c170937d
commit
58def58bf5
3 changed files with 44 additions and 31 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue