From fced1a5dc15ee6e492b6401e2b9d0a632cf80412 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 22 Jul 2020 03:26:19 +0200 Subject: [PATCH] Cont'd work on Loudness Assistant * use relative gain for analysis * allow to select constraints * tweak UI layout, use monospace font --- gtk2_ardour/editor.cc | 2 +- gtk2_ardour/editor_export_audio.cc | 6 +- gtk2_ardour/loudness_dialog.cc | 157 +++++++++++++++++++++++------ gtk2_ardour/loudness_dialog.h | 23 ++++- gtk2_ardour/mixer_strip.cc | 2 +- 5 files changed, 148 insertions(+), 42 deletions(-) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 7eb3eec087..46f7abc73d 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1920,7 +1920,7 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items) edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection))); edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection))); edit_items.push_back (SeparatorElem()); - edit_items.push_back (MenuElem (_("Analyze Session Loudness..."), sigc::mem_fun(*this, &Editor::analyze_range_export))); + edit_items.push_back (MenuElem (_("Loudness Assistant..."), sigc::mem_fun(*this, &Editor::analyze_range_export))); edit_items.push_back (SeparatorElem()); edit_items.push_back ( diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc index 82e4d303cd..3d6b4729c4 100644 --- a/gtk2_ardour/editor_export_audio.cc +++ b/gtk2_ardour/editor_export_audio.cc @@ -134,18 +134,16 @@ Editor::measure_master_loudness (bool range_selection) } ARDOUR::AudioRange ar (start, end, 0); - float prev_gain = _session->master_volume()->get_value(); - _session->master_volume ()->set_value (GAIN_COEFF_UNITY, Controllable::NoGroup); LoudnessDialog ld (_session, ar, range_selection); + ld.set_gain_offset_db (accurate_coefficient_to_dB (_session->master_volume()->get_value())); + if (own_window ()) { ld.set_transient_for (*own_window ()); } if (ld.run () == RESPONSE_APPLY) { _session->master_volume ()->set_value (dB_to_coefficient (ld.gain_db ()), Controllable::NoGroup); - } else { - _session->master_volume ()->set_value (prev_gain, Controllable::NoGroup); } } diff --git a/gtk2_ardour/loudness_dialog.cc b/gtk2_ardour/loudness_dialog.cc index b3098f4963..89f7278867 100644 --- a/gtk2_ardour/loudness_dialog.cc +++ b/gtk2_ardour/loudness_dialog.cc @@ -30,10 +30,13 @@ #include "ardour/export_status.h" #include "ardour/export_timespan.h" +#include "gtkmm2ext/utils.h" + #include "widgets/ardour_spacer.h" #include "export_report.h" #include "loudness_dialog.h" +#include "ui_config.h" #include "pbd/i18n.h" @@ -42,11 +45,16 @@ using namespace ARDOUR; using namespace ArdourWidgets; LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) - : ArdourDialog (_("Loudness Mate")) + : ArdourDialog (as ? _("Loudness Assistant") : _("Loudness Analyzer and Normalizer")) , _session (s) , _range (ar) , _status (s->get_export_status ()) , _autostart (as) + , _dbfs_btn (_("Peak:"), ArdourButton::led_default_elements, true) + , _dbtp_btn (_("True Peak:"), ArdourButton::led_default_elements, true) + , _lufs_i_btn (_("Integrated Loudness:"), ArdourButton::led_default_elements, true) + , _lufs_s_btn (_("Max. Short Loudness:"), ArdourButton::led_default_elements, true) + , _lufs_m_btn (_("Max. Momentary Loudness:"), ArdourButton::led_default_elements, true) , _rt_analysis_button (_("Realtime"), ArdourButton::led_default_elements, true) , _start_analysis_button (_("Analyze")) , _show_report_button (_("Show Detailed Report")) @@ -60,12 +68,41 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) , _lufs_i_spinbutton (_lufs_i_adjustment, 0.1, 1) , _lufs_s_spinbutton (_lufs_s_adjustment, 0.1, 1) , _lufs_m_spinbutton (_lufs_m_adjustment, 0.1, 1) - , _gain (0) + , _gain_init (0) + , _gain_norm (0) { _start_analysis_button.set_name ("generic button"); _rt_analysis_button.set_name ("generic button"); _show_report_button.set_name ("generic button"); + _dbfs_btn.set_name ("generic button"); + _dbtp_btn.set_name ("generic button"); + _lufs_i_btn.set_name ("generic button"); + _lufs_s_btn.set_name ("generic button"); + _lufs_m_btn.set_name ("generic button"); + + _dbfs_btn.set_led_left (true); + _dbtp_btn.set_led_left (true); + _lufs_i_btn.set_led_left (true); + _lufs_s_btn.set_led_left (true); + _lufs_m_btn.set_led_left (true); + + _dbfs_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _dbtp_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _lufs_i_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _lufs_s_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _lufs_m_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + + _delta_dbfs_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _delta_dbtp_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _delta_lufs_i_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _delta_lufs_s_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _delta_lufs_m_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + + _gain_init_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _gain_norm_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + _gain_total_label.modify_font (UIConfiguration::instance().get_NormalMonospaceFont()); + Label* l; Table* t = manage (new Table (8, 3, false)); t->set_spacings (4); @@ -85,18 +122,18 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) l->set_use_markup (true); t->attach (*l, 3, 4, 1, 2); - l = manage (new Label (_("Peak:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, 2, 3); - l = manage (new Label (_("True Peak:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, 3, 4); - l = manage (new Label (_("Integrated Loudness:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, 4, 5); - l = manage (new Label (_("Max. Short Loudness:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, 5, 6); - l = manage (new Label (_("Max. Momentary Loudness:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, 6, 7); - l = manage (new Label (_("Suggested Gain:"), ALIGN_LEFT)); + t->attach (_dbfs_btn, 0, 1, 2, 3); + t->attach (_dbtp_btn, 0, 1, 3, 4); + t->attach (_lufs_i_btn, 0, 1, 4, 5); + t->attach (_lufs_s_btn, 0, 1, 5, 6); + t->attach (_lufs_m_btn, 0, 1, 6, 7); + + l = manage (new Label (_("Gain to normalize:"), ALIGN_LEFT)); t->attach (*l, 0, 1, 8, 9); + l = manage (new Label (_("Previously applied gain:"), ALIGN_LEFT)); + t->attach (*l, 0, 1, 9, 10); + l = manage (new Label (_("Total gain:"), ALIGN_LEFT)); + t->attach (*l, 0, 1, 10, 11); t->attach (_dbfs_label, 1, 2, 2, 3); t->attach (_dbtp_label, 1, 2, 3, 4); @@ -104,11 +141,11 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) t->attach (_lufs_s_label, 1, 2, 5, 6); t->attach (_lufs_m_label, 1, 2, 6, 7); - t->attach (_dbfs_spinbutton, 2, 3, 2, 3); - t->attach (_dbtp_spinbutton, 2, 3, 3, 4); - t->attach (_lufs_i_spinbutton, 2, 3, 4, 5); - t->attach (_lufs_s_spinbutton, 2, 3, 5, 6); - t->attach (_lufs_m_spinbutton, 2, 3, 6, 7); + t->attach (_dbfs_spinbutton, 2, 3, 2, 3, EXPAND|FILL, EXPAND|FILL, 8, 0); + t->attach (_dbtp_spinbutton, 2, 3, 3, 4, EXPAND|FILL, EXPAND|FILL, 8, 0); + t->attach (_lufs_i_spinbutton, 2, 3, 4, 5, EXPAND|FILL, EXPAND|FILL, 8, 0); + t->attach (_lufs_s_spinbutton, 2, 3, 5, 6, EXPAND|FILL, EXPAND|FILL, 8, 0); + t->attach (_lufs_m_spinbutton, 2, 3, 6, 7, EXPAND|FILL, EXPAND|FILL, 8, 0); t->attach (_delta_dbfs_label, 3, 4, 2, 3); t->attach (_delta_dbtp_label, 3, 4, 3, 4); @@ -117,8 +154,26 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) t->attach (_delta_lufs_m_label, 3, 4, 6, 7); ArdourHSpacer* spc = manage (new ArdourHSpacer (1.0)); - t->attach (*spc , 1, 4, 7, 8); - t->attach (_gain_label, 3, 4, 8, 9); + t->attach (*spc , 1, 4, 7, 8); + t->attach (_gain_norm_label, 3, 4, 8, 9); + t->attach (_gain_init_label, 3, 4, 9, 10); + t->attach (_gain_total_label, 3, 4, 10, 11); + + _dbfs_label.set_alignment (ALIGN_RIGHT); + _dbtp_label.set_alignment (ALIGN_RIGHT); + _lufs_i_label.set_alignment (ALIGN_RIGHT); + _lufs_s_label.set_alignment (ALIGN_RIGHT); + _lufs_m_label.set_alignment (ALIGN_RIGHT); + + _delta_dbfs_label.set_alignment (ALIGN_RIGHT); + _delta_dbtp_label.set_alignment (ALIGN_RIGHT); + _delta_lufs_i_label.set_alignment (ALIGN_RIGHT); + _delta_lufs_s_label.set_alignment (ALIGN_RIGHT); + _delta_lufs_m_label.set_alignment (ALIGN_RIGHT); + + _gain_norm_label.set_alignment (ALIGN_RIGHT); + _gain_init_label.set_alignment (ALIGN_RIGHT); + _gain_total_label.set_alignment (ALIGN_RIGHT); _result_box.pack_start (*t, false, false, 6); _progress_box.pack_start (_progress_bar, false, false, 6); @@ -147,11 +202,19 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) get_vbox()->pack_start (_setup_box); get_vbox()->pack_start (_progress_box); get_vbox()->pack_start (_result_box); - get_vbox()->set_size_request(400,-1); + + _progress_box.set_size_request (400,-1); _ok_button = add_button (Stock::APPLY, RESPONSE_APPLY); _cancel_button = add_button (Stock::CANCEL, RESPONSE_CANCEL); + // TODO preset, remember + _dbfs_btn.set_active (false); + _dbtp_btn.set_active (true); + _lufs_i_btn.set_active (true); + _lufs_s_btn.set_active (false); + _lufs_m_btn.set_active (false); + _cancel_button->signal_clicked().connect (sigc::mem_fun (this, &LoudnessDialog::cancel_analysis)); _dbfs_spinbutton.signal_value_changed().connect (mem_fun (*this, &LoudnessDialog::calculate_gain)); _dbtp_spinbutton.signal_value_changed().connect (mem_fun (*this, &LoudnessDialog::calculate_gain)); @@ -160,6 +223,11 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) _lufs_m_spinbutton.signal_value_changed().connect (mem_fun (*this, &LoudnessDialog::calculate_gain)); _show_report_button.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::display_report)); _start_analysis_button.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::start_analysis)); + _dbfs_btn.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::calculate_gain)); + _dbtp_btn.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::calculate_gain)); + _lufs_i_btn.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::calculate_gain)); + _lufs_s_btn.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::calculate_gain)); + _lufs_m_btn.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::calculate_gain)); _ok_button->set_sensitive (false); _show_report_button.set_sensitive (false); @@ -335,17 +403,42 @@ LoudnessDialog::calculate_gain () float lufs_s = _lufs_s_spinbutton.get_value(); float lufs_m = _lufs_m_spinbutton.get_value(); - _gain = dbfs - _dbfs; - _gain = std::min (_gain, dbtp - _dbtp); - _gain = std::min (_gain, lufs_i - _lufs_i); - _gain = std::min (_gain, lufs_s - _lufs_s); - _gain = std::min (_gain, lufs_m - _lufs_m); + float gain = 0; + bool set = false; - _delta_dbfs_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::fixed, dbfs - _dbfs)); - _delta_dbtp_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::fixed, dbtp - _dbtp)); - _delta_lufs_i_label.set_text (string_compose (_("%1 LU"), std::setprecision (2), std::fixed, lufs_i - _lufs_i)); - _delta_lufs_s_label.set_text (string_compose (_("%1 LU"), std::setprecision (2), std::fixed, lufs_s - _lufs_s)); - _delta_lufs_m_label.set_text (string_compose (_("%1 LU"), std::setprecision (2), std::fixed, lufs_m - _lufs_m)); +#define MIN_IF_SET(A, B) \ + { if (set) { gain = std::min (gain, (A) - (B));} else { gain = (A) - (B); } set = true; } - _gain_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::fixed, _gain)); + if (_dbfs_btn.get_active ()) { + MIN_IF_SET (dbfs, _dbfs); + } + if (_dbtp_btn.get_active ()) { + MIN_IF_SET (dbtp, _dbtp); + } + if (_lufs_i_btn.get_active ()) { + MIN_IF_SET (lufs_i, _lufs_i); + } + if (_lufs_s_btn.get_active ()) { + MIN_IF_SET (lufs_s, _lufs_s); + } + if (_lufs_m_btn.get_active ()) { + MIN_IF_SET (lufs_m, _lufs_m); + } + + _delta_dbfs_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::showpos, std::fixed, dbfs - _dbfs)); + _delta_dbtp_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::showpos, std::fixed, dbtp - _dbtp)); + _delta_lufs_i_label.set_text (string_compose (_("%1 LU"), std::setprecision (2), std::showpos, std::fixed, lufs_i - _lufs_i)); + _delta_lufs_s_label.set_text (string_compose (_("%1 LU"), std::setprecision (2), std::showpos, std::fixed, lufs_s - _lufs_s)); + _delta_lufs_m_label.set_text (string_compose (_("%1 LU"), std::setprecision (2), std::showpos, std::fixed, lufs_m - _lufs_m)); + + _delta_dbfs_label.set_sensitive (_dbfs_btn.get_active ()); + _delta_dbtp_label.set_sensitive (_dbtp_btn.get_active ()); + _delta_lufs_i_label.set_sensitive (_lufs_i_btn.get_active ()); + _delta_lufs_s_label.set_sensitive (_lufs_s_btn.get_active ()); + _delta_lufs_m_label.set_sensitive (_lufs_m_btn.get_active ()); + + _gain_norm = gain; + _gain_norm_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::showpos, std::fixed, _gain_norm)); + _gain_init_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::showpos, std::fixed, _gain_init)); + _gain_total_label.set_markup (string_compose (_("%1 dB"), std::setw(7), std::setprecision (2), std::showpos, std::fixed, gain_db ())); } diff --git a/gtk2_ardour/loudness_dialog.h b/gtk2_ardour/loudness_dialog.h index 4aec71373f..1a4de88e28 100644 --- a/gtk2_ardour/loudness_dialog.h +++ b/gtk2_ardour/loudness_dialog.h @@ -38,7 +38,13 @@ class LoudnessDialog : public ArdourDialog public: LoudnessDialog (ARDOUR::Session*, ARDOUR::AudioRange const&, bool); int run (); - float gain_db () const { return _gain; } + + void set_gain_offset_db (float db) { + _gain_init = db; + } + float gain_db () const { + return _gain_norm + _gain_init; + } protected: bool on_delete_event (GdkEventAny*); @@ -64,6 +70,12 @@ private: Gtk::Button* _ok_button; Gtk::Button* _cancel_button; + ArdourWidgets::ArdourButton _dbfs_btn; + ArdourWidgets::ArdourButton _dbtp_btn; + ArdourWidgets::ArdourButton _lufs_i_btn; + ArdourWidgets::ArdourButton _lufs_s_btn; + ArdourWidgets::ArdourButton _lufs_m_btn; + Gtk::Label _dbfs_label; Gtk::Label _dbtp_label; Gtk::Label _lufs_i_label; @@ -76,8 +88,9 @@ private: Gtk::Label _delta_lufs_s_label; Gtk::Label _delta_lufs_m_label; - - Gtk::Label _gain_label; + Gtk::Label _gain_init_label; + Gtk::Label _gain_norm_label; + Gtk::Label _gain_total_label; ArdourWidgets::ArdourButton _rt_analysis_button; ArdourWidgets::ArdourButton _start_analysis_button; @@ -100,5 +113,7 @@ private: float _lufs_i; float _lufs_s; float _lufs_m; - float _gain; + + float _gain_init; + float _gain_norm; }; diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 8e99786952..783ab20e15 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -603,7 +603,7 @@ MixerStrip::set_route (boost::shared_ptr rt) assert (route()->volume_control()); _volume_control_knob = manage (new ArdourKnob (ArdourKnob::default_elements, ArdourKnob::Flags (ArdourKnob::Detent | ArdourKnob::ArcToZero))); - _loudess_analysis_button = manage (new ArdourButton (S_("Loudness|LM"))); + _loudess_analysis_button = manage (new ArdourButton (S_("Loudness|LAN"))); set_tooltip (_loudess_analysis_button, _("Measure loudness of the session, normalize master output volume")); _volume_control_knob->set_size_request (PX_SCALE(19), PX_SCALE(19));