From 9f3f017736c252b198a86324227e797032c76114 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 3 Nov 2014 18:41:57 -0500 Subject: Check whether frequency controls are audible or low and provide appropriate controls. Always clamp set value to controller range. --- gtk2_ardour/automation_controller.cc | 64 ++++++++++++++++++++++++------- gtk2_ardour/automation_controller.h | 2 +- libs/ardour/ardour/parameter_descriptor.h | 2 + 3 files changed, 53 insertions(+), 15 deletions(-) diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc index 20ef5ab21c..55670b280a 100644 --- a/gtk2_ardour/automation_controller.cc +++ b/gtk2_ardour/automation_controller.cc @@ -150,12 +150,34 @@ AutomationController::end_touch () } } +static double +midi_note_to_hz(int note) +{ + const double tuning = 440.0; + return tuning * pow(2, (note - 69.0) / 12.0); +} + +static double +clamp(double val, double min, double max) +{ + if (val < min) { + return min; + } else if (val > max) { + return max; + } + return val; +} + void AutomationController::run_note_select_dialog() { - NoteSelectDialog* dialog = new NoteSelectDialog(); + const ARDOUR::ParameterDescriptor& desc = _controllable->desc(); + NoteSelectDialog* dialog = new NoteSelectDialog(); if (dialog->run() == Gtk::RESPONSE_ACCEPT) { - _controllable->set_value(dialog->note_number()); + const double value = ((_controllable->desc().unit == ARDOUR::ParameterDescriptor::HZ) + ? midi_note_to_hz(dialog->note_number()) + : dialog->note_number()); + _controllable->set_value(clamp(value, desc.lower, desc.upper)); } delete dialog; } @@ -163,17 +185,22 @@ AutomationController::run_note_select_dialog() void AutomationController::set_freq_beats(double beats) { - const ARDOUR::Session& session = _controllable->session(); - const ARDOUR::Tempo& tempo = session.tempo_map().tempo_at(0); - const double bpm = tempo.beats_per_minute(); - const double bps = bpm / 60.0; - _controllable->set_value(bps / beats); + const ARDOUR::ParameterDescriptor& desc = _controllable->desc(); + const ARDOUR::Session& session = _controllable->session(); + const framepos_t pos = session.transport_frame(); + const ARDOUR::Tempo& tempo = session.tempo_map().tempo_at(pos); + const double bpm = tempo.beats_per_minute(); + const double bps = bpm / 60.0; + const double freq = bps / beats; + _controllable->set_value(clamp(freq, desc.lower, desc.upper)); } void AutomationController::set_ratio(double ratio) { - _controllable->set_value(_controllable->get_value() * ratio); + const ARDOUR::ParameterDescriptor& desc = _controllable->desc(); + const double value = _controllable->get_value() * ratio; + _controllable->set_value(clamp(value, desc.lower, desc.upper)); } bool @@ -185,14 +212,15 @@ AutomationController::on_button_release(GdkEventButton* ev) return false; } - if (_controllable->desc().unit == ARDOUR::ParameterDescriptor::MIDI_NOTE) { + const ARDOUR::ParameterDescriptor& desc = _controllable->desc(); + if (desc.unit == ARDOUR::ParameterDescriptor::MIDI_NOTE) { Gtk::Menu* menu = manage(new Menu()); MenuList& items = menu->items(); items.push_back(MenuElem(_("Select Note..."), sigc::mem_fun(*this, &AutomationController::run_note_select_dialog))); menu->popup(1, ev->time); return true; - } else if (_controllable->desc().unit == ARDOUR::ParameterDescriptor::HZ) { + } else if (desc.unit == ARDOUR::ParameterDescriptor::HZ) { Gtk::Menu* menu = manage(new Menu()); MenuList& items = menu->items(); items.push_back(MenuElem(_("Halve"), @@ -201,10 +229,18 @@ AutomationController::on_button_release(GdkEventButton* ev) items.push_back(MenuElem(_("Double"), sigc::bind(sigc::mem_fun(*this, &AutomationController::set_ratio), 2.0))); - for (double beats = 1.0; beats <= 16; ++beats) { - items.push_back(MenuElem(string_compose(_("Set to %1 beat(s)"), (int)beats), - sigc::bind(sigc::mem_fun(*this, &AutomationController::set_freq_beats), - beats))); + const bool is_audible = desc.upper > 40.0; + const bool is_low = desc.lower < 1.0; + if (is_audible) { + items.push_back(MenuElem(_("Select Note..."), + sigc::mem_fun(*this, &AutomationController::run_note_select_dialog))); + } + if (is_low) { + for (double beats = 1.0; beats <= 16; ++beats) { + items.push_back(MenuElem(string_compose(_("Set to %1 beat(s)"), (int)beats), + sigc::bind(sigc::mem_fun(*this, &AutomationController::set_freq_beats), + beats))); + } } menu->popup(1, ev->time); return true; diff --git a/gtk2_ardour/automation_controller.h b/gtk2_ardour/automation_controller.h index 6350c5b67e..8b00645c80 100644 --- a/gtk2_ardour/automation_controller.h +++ b/gtk2_ardour/automation_controller.h @@ -79,7 +79,7 @@ private: void value_changed(); bool _ignore_change; - boost::shared_ptr _printer; + boost::shared_ptr _printer; boost::shared_ptr _controllable; Gtk::Adjustment* _adjustment; sigc::connection _screen_update_connection; diff --git a/libs/ardour/ardour/parameter_descriptor.h b/libs/ardour/ardour/parameter_descriptor.h index d647183b2d..f4dc3c819c 100644 --- a/libs/ardour/ardour/parameter_descriptor.h +++ b/libs/ardour/ardour/parameter_descriptor.h @@ -43,6 +43,7 @@ struct ParameterDescriptor ParameterDescriptor(const Evoral::Parameter& parameter) : key((uint32_t)-1) , datatype(Variant::VOID) + , unit(NONE) , normal(parameter.normal()) , lower(parameter.min()) , upper(parameter.max()) @@ -66,6 +67,7 @@ struct ParameterDescriptor ParameterDescriptor() : key((uint32_t)-1) , datatype(Variant::VOID) + , unit(NONE) , normal(0) , lower(0) , upper(0) -- cgit v1.2.3