diff --git a/gtk2_ardour/loudness_dialog.cc b/gtk2_ardour/loudness_dialog.cc index 6b8793c3a3..1e74e8565a 100644 --- a/gtk2_ardour/loudness_dialog.cc +++ b/gtk2_ardour/loudness_dialog.cc @@ -23,8 +23,8 @@ #include "pbd/unwind.h" #include "ardour/dB.h" -#include "ardour/plugin_manager.h" #include "ardour/plugin_insert.h" +#include "ardour/plugin_manager.h" #include "ardour/processor.h" #include "ardour/session.h" @@ -40,9 +40,11 @@ #include "gtkmm2ext/utils.h" #include "widgets/ardour_spacer.h" +#include "widgets/prompter.h" #include "widgets/tooltips.h" #include "ardour_message.h" +#include "export_analysis_graphs.h" #include "export_report.h" #include "loudness_dialog.h" #include "ui_config.h" @@ -53,39 +55,19 @@ using namespace Gtk; using namespace ARDOUR; using namespace ArdourWidgets; -/* https://www.masteringthemix.com/blogs/learn/76296773-mastering-audio-for-soundcloud-itunes-spotify-and-youtube - * https://youlean.co/loudness-standards-full-comparison-table/ - */ -LoudnessDialog::LoudnessPreset LoudnessDialog::presets[] = -{ - /* | dbFS dBTP LUFS short mom. | FS, TP , int, sht, mom |maxIntg| notes */ - {"-Analysis Only-", { false, false, false, false, false}, { 0, 0.0, 0, 0, 0 }, { 0.0, -200.0}}, - {"EBU R128", { false, true, true, false, false}, { 0, -1.0, -23, 0, 0 }, {-22.5, -23.5}}, // +/- 0.5 LU - {"EBU R128 S1", { false, true, true, true, false}, { 0, -1.0, -23, -18, 0 }, {-22.5, -23.5}}, // +/- 0.5 LU - {"ATSC A/85", { false, true, true, true, false}, { 0, -2.0, -24, 0, 0 }, {-22.0, -26.0}}, // +/- 2 LU - {"AES Streaming", { false, true, true, false, false}, { 0, -1.0, -18, 0, 0 }, {-16.0, -20.0}}, // min/max Integrated: -20 / -16 LUFS - same as "ASWG-R001 PORTABLE" - {"ASWG-R001 HOME", { false, true, true, true, false}, { 0, -1.0, -24, 0, 0 }, {-22.0, -26.0}}, // +/- 2 LU - {"Digital Peak", { true, false, false, false, false}, { 0, 0.0, 0, 0, 0 }, { 0.0, -200.0}}, - {"CD", { true, true, true, false, false}, { 0, -0.1, -9, 0, 0 }, { 0.0, -200.0}}, - - {"Amazon Music", { false, true, true, false, false}, { 0, -2.0, -14, 0, 0 }, { -9.0, -19.0}}, // -9 to -19 LUFS - {"Apple Music", { false, true, true, false, false}, { 0, -1.0, -16, 0, 0 }, {-15.0, -17.0}}, // (+/- 1.0 LU) - {"Deezer", { false, true, true, false, false}, { 0, -1.0, -15, 0, 0 }, {-14.0, -16.0}}, // -14 to -16 LUFS - {"Soundcloud", { false, true, true, false, false}, { 0, -1.0, -10, 0, 0 }, { -8.0, -13.0}}, // -8 to -13 LUFS - {"Spotify", { false, true, true, false, false}, { 0, -1.0, -14, 0, 0 }, { -8.0, -20.0}}, // Spotify use replay-gain to match -14 or -11 .. - {"Spotify Loud", { false, true, true, false, false}, { 0, -2.0, -11, 0, 0 }, { -5.0, -17.0}}, // .. so the min/max range is arbitrary +/- 6dB - {"Youtube", { false, true, true, false, false}, { 0, -1.0, -14, 0, 0 }, {-13.0, -15.0}}, // -13 to -15 LUFS -}; - -LoudnessDialog::LoudnessPreset LoudnessDialog::_preset = LoudnessDialog::presets [1]; +bool LoudnessDialog::_first_time = true; +CLoudnessPreset LoudnessDialog::_last_preset; LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) : ArdourDialog (as ? _("Loudness Assistant") : _("Loudness Analyzer and Normalizer")) + , _lp (false) , _session (s) , _range (ar) , _status (s->get_export_status ()) , _autostart (as) - , _conformity_expander (_("Conformity Analysis (with gain applied)")) + , _conformity_frame (_("Conformity Analysis (with gain applied)")) + , _save_preset (_("Save")) + , _remove_preset (_("Remove")) , _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) @@ -93,13 +75,13 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) , _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 Graphical Analysis")) + , _show_report_button (_("Analysis Report")) , _custom_pos_button (_("Custom Amplifier Position"), ArdourButton::led_default_elements, true) - , _dbfs_adjustment ( 0.00, -90.00, 0.00, 0.1, 0.2) - , _dbtp_adjustment ( -1.0, -90.00, 0.00, 0.1, 0.2) - , _lufs_i_adjustment (-23.0, -90.00, 0.00, 0.1, 1.0) - , _lufs_s_adjustment (-20.0, -90.00, 0.00, 0.1, 1.0) - , _lufs_m_adjustment (-17.0, -90.00, 0.00, 0.1, 1.0) + , _dbfs_adjustment (0.00, -10.00, 0.00, 0.1, 0.2) + , _dbtp_adjustment (-1.0, -10.00, 0.00, 0.1, 0.2) + , _lufs_i_adjustment (-23.0, -90.00, 0.00, 0.5, 1.0) + , _lufs_s_adjustment (-20.0, -90.00, 0.00, 0.5, 1.0) + , _lufs_m_adjustment (-17.0, -90.00, 0.00, 0.5, 1.0) , _dbfs_spinbutton (_dbfs_adjustment, 0.1, 1) , _dbtp_spinbutton (_dbtp_adjustment, 0.1, 1) , _lufs_i_spinbutton (_lufs_i_adjustment, 0.1, 1) @@ -110,11 +92,19 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) , _ignore_preset (false) , _ignore_change (false) { + _preset = _lp[0]; + if (_first_time) { + _first_time = false; + _last_preset = _lp[0]; + } + + _preset = _last_preset; + /* Dialog can be displayed from the mixer, override global transient_parent */ unset_transient_for (); /* query initial gain */ - _gain_out = accurate_coefficient_to_dB (_session->master_volume()->get_value()); + _gain_out = accurate_coefficient_to_dB (_session->master_volume ()->get_value ()); /* setup styles */ _start_analysis_button.set_name ("generic button"); @@ -128,6 +118,9 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) _start_analysis_button.set_size_request (-1, req.height * 1.1); _rt_analysis_button.set_size_request (-1, req.height * 1.1); + _save_preset.set_name ("generic button"); + _remove_preset.set_name ("generic button"); + _dbfs_btn.set_name ("generic button"); _dbtp_btn.set_name ("generic button"); _lufs_i_btn.set_name ("generic button"); @@ -140,105 +133,117 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) _lufs_s_btn.set_led_left (true); _lufs_m_btn.set_led_left (true); + _preset_dropdown.set_can_focus (true); _start_analysis_button.set_can_focus (true); _rt_analysis_button.set_can_focus (true); _show_report_button.set_can_focus (true); _custom_pos_button.set_can_focus (true); + _save_preset.set_can_focus (true); + _remove_preset.set_can_focus (true); _dbfs_btn.set_can_focus (true); _dbtp_btn.set_can_focus (true); _lufs_i_btn.set_can_focus (true); _lufs_s_btn.set_can_focus (true); _lufs_m_btn.set_can_focus (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()); + _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()); + _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_out_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()); - _gain_exceeds_label.modify_font (UIConfiguration::instance().get_NormalFont()); + _gain_out_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 ()); + _gain_exceeds_label.modify_font (UIConfiguration::instance ().get_NormalFont ()); /* result display layout */ -#define ROW row, row +1 +#define ROW row, row + 1 - int row; + int row = 0; Label* l; - Table* t = manage (new Table (12, 4, false)); + Table* t = manage (new Table (11, 8, false)); t->set_spacings (4); - l = manage (new Label (_("Analysis Results"), ALIGN_LEFT)); - l->set_use_markup (true); - t->attach (*l, 0, 1, 0, 1); l = manage (new Label (_("Preset:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, 1, 2); + t->attach (*l, 0, 1, ROW, SHRINK | FILL); + t->attach (_preset_dropdown, 1, 3, ROW); - t->attach (_show_report_button, 1, 4, 0, 1); - t->attach (_preset_dropdown, 1, 3, 1, 2); + t->attach (_save_preset, 3, 4, ROW, SHRINK | FILL); + t->attach (_remove_preset, 4, 5, ROW, SHRINK | FILL); + /* horiz space */ + l = manage (new Label (" ", ALIGN_LEFT)); + t->attach (*l, 5, 6, ROW, SHRINK, SHRINK, 6, 0); + + l = manage (new Label (" ", ALIGN_LEFT)); + t->attach (*l, 6, 7, ROW); + + t->attach (_show_report_button, 7, 8, ROW, SHRINK | FILL); + + ++row; l = manage (new Label (_("Target"), ALIGN_CENTER)); l->set_use_markup (true); - t->attach (*l, 1, 2, 2, 3); + t->attach (*l, 2, 3, ROW); l = manage (new Label (_("Measured"), ALIGN_CENTER)); l->set_use_markup (true); - t->attach (*l, 2, 3, 2, 3); + t->attach (*l, 3, 4, ROW); l = manage (new Label (_("Delta"), ALIGN_CENTER)); l->set_use_markup (true); - t->attach (*l, 3, 4, 2, 3); + t->attach (*l, 4, 5, ROW); - row = 3; - t->attach (_dbfs_btn, 0, 1, ROW); ++row; - t->attach (_dbtp_btn, 0, 1, ROW); ++row; - t->attach (_lufs_i_btn, 0, 1, ROW); ++row; - t->attach (_lufs_s_btn, 0, 1, ROW); ++row; - t->attach (_lufs_m_btn, 0, 1, ROW); ++row; + row = 2; + t->attach (_dbfs_btn, 0, 2, ROW); ++row; + t->attach (_dbtp_btn, 0, 2, ROW); ++row; + t->attach (_lufs_i_btn, 0, 2, ROW); ++row; + t->attach (_lufs_s_btn, 0, 2, ROW); ++row; + t->attach (_lufs_m_btn, 0, 2, ROW); ++row; ++row; // spacer l = manage (new Label (_("Gain to normalize:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, ROW); ++row; + t->attach (*l, 0, 2, ROW); ++row; l = manage (new Label (_("Previous output gain:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, ROW); ++row; + t->attach (*l, 0, 2, ROW); ++row; l = manage (new Label (_("Total gain:"), ALIGN_LEFT)); - t->attach (*l, 0, 1, ROW); ++row; + t->attach (*l, 0, 2, ROW); - row = 3; - t->attach (_dbfs_spinbutton, 1, 2, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; - t->attach (_dbtp_spinbutton, 1, 2, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; - t->attach (_lufs_i_spinbutton, 1, 2, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; - t->attach (_lufs_s_spinbutton, 1, 2, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; - t->attach (_lufs_m_spinbutton, 1, 2, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; + row = 2; + t->attach (_dbfs_spinbutton, 2, 3, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; + t->attach (_dbtp_spinbutton, 2, 3, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; + t->attach (_lufs_i_spinbutton, 2, 3, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; + t->attach (_lufs_s_spinbutton, 2, 3, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; + t->attach (_lufs_m_spinbutton, 2, 3, ROW, EXPAND|FILL, EXPAND|FILL, 8, 0); ++row; - row = 3; - t->attach (_dbfs_label, 2, 3, ROW); ++row; - t->attach (_dbtp_label, 2, 3, ROW); ++row; - t->attach (_lufs_i_label, 2, 3, ROW); ++row; - t->attach (_lufs_s_label, 2, 3, ROW); ++row; - t->attach (_lufs_m_label, 2, 3, ROW); ++row; + row = 2; + t->attach (_dbfs_label, 3, 4, ROW); ++row; + t->attach (_dbtp_label, 3, 4, ROW); ++row; + t->attach (_lufs_i_label, 3, 4, ROW); ++row; + t->attach (_lufs_s_label, 3, 4, ROW); ++row; + t->attach (_lufs_m_label, 3, 4, ROW); ++row; - row = 3; - t->attach (_delta_dbfs_label, 3, 4, ROW); ++row; - t->attach (_delta_dbtp_label, 3, 4, ROW); ++row; - t->attach (_delta_lufs_i_label, 3, 4, ROW); ++row; - t->attach (_delta_lufs_s_label, 3, 4, ROW); ++row; - t->attach (_delta_lufs_m_label, 3, 4, ROW); ++row; + row = 2; + t->attach (_delta_dbfs_label, 4, 5, ROW); ++row; + t->attach (_delta_dbtp_label, 4, 5, ROW); ++row; + t->attach (_delta_lufs_i_label, 4, 5, ROW); ++row; + t->attach (_delta_lufs_s_label, 4, 5, ROW); ++row; + t->attach (_delta_lufs_m_label, 4, 5, ROW); ++row; ArdourHSpacer* spc = manage (new ArdourHSpacer (1.0)); - t->attach (*spc, 2, 4, ROW); ++row; - t->attach (_gain_norm_label, 3, 4, ROW); ++row; - t->attach (_gain_out_label, 3, 4, ROW); ++row; - t->attach (_gain_exceeds_label, 2, 3, ROW); - t->attach (_gain_total_label, 3, 4, ROW); ++row; - t->attach (_custom_pos_button, 1, 4, ROW); ++row; + t->attach (*spc, 3, 5, ROW); ++row; + t->attach (_gain_norm_label, 4, 5, ROW); ++row; + t->attach (_gain_out_label, 4, 5, ROW); ++row; + t->attach (_gain_exceeds_label, 3, 4, ROW); + t->attach (_gain_total_label, 4, 5, ROW); + t->attach (_custom_pos_button, 7, 8, row - 1, row + 1, SHRINK | FILL, SHRINK); + t->attach (_conformity_frame, 6, 8, 1, row - 3, SHRINK | FILL, EXPAND | FILL, 0, 0); set_tooltip (_custom_pos_button, _("When enabled an amplifier processor is used to apply the gain. " @@ -265,8 +270,11 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) _gain_total_label.set_alignment (ALIGN_RIGHT); _gain_exceeds_label.set_alignment (ALIGN_RIGHT); + HBox* hb = manage (new (HBox)); + hb->pack_start (_loudness_graph, true, false); + + _result_box.pack_start (*hb, false, false, 0); _result_box.pack_start (*t, false, false, 6); - _result_box.pack_start (_conformity_expander, false, false, 6); /* analysis progress layout */ _progress_box.pack_start (_progress_bar, false, false, 6); @@ -277,27 +285,25 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) l = manage (new Label ()); l->set_markup (_("Loudness Analysis\n")); l->set_alignment (ALIGN_LEFT, ALIGN_TOP); - t->attach (*l, 0, 1, 0, 1, EXPAND|FILL, FILL, 8, 2); + t->attach (*l, 0, 1, 0, 1, EXPAND | FILL, FILL, 8, 2); l = manage (new Label ()); l->set_line_wrap (); l->set_alignment (ALIGN_LEFT, ALIGN_TOP); l->set_markup (_( - "This allows the user to analyze and conform the loudness of the signal at the master-bus " - "output of the complete session, as it would be exported. " - "When using this feature, remember to disable normalization in the session export profile." - )); - t->attach (*l, 0, 1, 1, 2, EXPAND|FILL, FILL, 8, 2); + "This allows the user to analyze and conform the loudness of the signal at the master-bus " + "output of the complete session, as it would be exported. " + "When using this feature, remember to disable normalization in the session export profile.")); + t->attach (*l, 0, 1, 1, 2, EXPAND | FILL, FILL, 8, 2); l = manage (new Label ()); l->set_line_wrap (); l->set_alignment (ALIGN_LEFT, ALIGN_TOP); l->set_markup (_( - "By default, a faster-than-realtime export is used to assess the loudness of the " - "session. If any outboard gear is used, a realtime export is available, to " - "play at normal speed." - )); - t->attach (*l, 0, 1, 2, 3, EXPAND|FILL, FILL, 8, 2); + "By default, a faster-than-realtime export is used to assess the loudness of the " + "session. If any outboard gear is used, a realtime export is available, to " + "play at normal speed.")); + t->attach (*l, 0, 1, 2, 3, EXPAND | FILL, FILL, 8, 2); Alignment* align = manage (new Alignment (0, 0, 1, 0)); align->add (_start_analysis_button); @@ -310,39 +316,44 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) _setup_box.pack_start (*t, false, false, 6); /* global layout */ - get_vbox()->pack_start (_setup_box); - get_vbox()->pack_start (_progress_box); - get_vbox()->pack_start (_result_box); + get_vbox ()->pack_start (_setup_box); + get_vbox ()->pack_start (_progress_box); + get_vbox ()->pack_start (_result_box); - _progress_box.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); /* fill in presets */ - for (size_t i = 0; i < sizeof (presets) / sizeof (LoudnessDialog::LoudnessPreset); ++i) { + for (size_t i = 0; i < _lp.n_presets (); ++i) { using namespace Gtkmm2ext; - _preset_dropdown.AddMenuElem (MenuElemNoMnemonic (presets[i].name, sigc::bind (sigc::mem_fun (*this, &LoudnessDialog::load_preset), i))); + _preset_dropdown.AddMenuElem (MenuElemNoMnemonic (_lp[i].label, sigc::bind (sigc::mem_fun (*this, &LoudnessDialog::load_preset), i))); } - _initial_preset_name = _preset.name; - if (_preset.name != _("Custom")) { - /* call _menu.set_active to initialize 'current_active' item */ - PBD::Unwinder uw (_ignore_preset, true); - _preset_dropdown.set_active (_preset.name); - } apply_preset (); - _conformity_expander.set_expanded(false); + if (!_lp.find_preset (_preset)) { + _preset.label = _("Custom"); + } + + check_preset (); + _gain_out_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::showpos, std::fixed, _gain_out)); + /* setup graph */ + _loudness_graph.signal_size_request ().connect (sigc::mem_fun (*this, &LoudnessDialog::graph_size_request)); + _loudness_graph.signal_expose_event ().connect (sigc::mem_fun (*this, &LoudnessDialog::graph_expose_event)); + /* connect signals */ - _cancel_button->signal_clicked().connect (sigc::mem_fun (this, &LoudnessDialog::cancel_analysis)); - _dbfs_spinbutton.signal_value_changed().connect (mem_fun (*this, &LoudnessDialog::update_settings)); - _dbtp_spinbutton.signal_value_changed().connect (mem_fun (*this, &LoudnessDialog::update_settings)); - _lufs_i_spinbutton.signal_value_changed().connect (mem_fun (*this, &LoudnessDialog::update_settings)); - _lufs_s_spinbutton.signal_value_changed().connect (mem_fun (*this, &LoudnessDialog::update_settings)); - _lufs_m_spinbutton.signal_value_changed().connect (mem_fun (*this, &LoudnessDialog::update_settings)); + _cancel_button->signal_clicked ().connect (sigc::mem_fun (this, &LoudnessDialog::cancel_analysis)); + _dbfs_spinbutton.signal_value_changed ().connect (mem_fun (*this, &LoudnessDialog::update_settings)); + _dbtp_spinbutton.signal_value_changed ().connect (mem_fun (*this, &LoudnessDialog::update_settings)); + _lufs_i_spinbutton.signal_value_changed ().connect (mem_fun (*this, &LoudnessDialog::update_settings)); + _lufs_s_spinbutton.signal_value_changed ().connect (mem_fun (*this, &LoudnessDialog::update_settings)); + _lufs_m_spinbutton.signal_value_changed ().connect (mem_fun (*this, &LoudnessDialog::update_settings)); + _save_preset.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::save_preset)); + _remove_preset.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::remove_preset)); _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::update_settings)); @@ -350,7 +361,6 @@ LoudnessDialog::LoudnessDialog (Session* s, AudioRange const& ar, bool as) _lufs_i_btn.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::update_settings)); _lufs_s_btn.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::update_settings)); _lufs_m_btn.signal_clicked.connect (mem_fun (*this, &LoudnessDialog::update_settings)); - _conformity_expander.property_expanded().signal_changed().connect( sigc::mem_fun(*this, &LoudnessDialog::toggle_conformity_display)); _ok_button->set_sensitive (false); _show_report_button.set_sensitive (false); @@ -365,7 +375,7 @@ void LoudnessDialog::cancel_analysis () { if (_status->running ()) { - _status->abort(); + _status->abort (); } } @@ -405,19 +415,7 @@ LoudnessDialog::run () _session->master_volume ()->set_value (dB_to_coefficient (gain_db ()), PBD::Controllable::NoGroup); _session->master_out()->set_volume_applies_to_output (!_custom_pos_button.get_active ()); - _preset.level[0] = _dbfs_spinbutton.get_value(); - _preset.level[1] = _dbtp_spinbutton.get_value(); - _preset.level[2] = _lufs_i_spinbutton.get_value(); - _preset.level[3] = _lufs_s_spinbutton.get_value(); - _preset.level[4] = _lufs_m_spinbutton.get_value(); - _preset.enable[0] = _dbfs_btn.get_active (); - _preset.enable[1] = _dbtp_btn.get_active (); - _preset.enable[2] = _lufs_i_btn.get_active (); - _preset.enable[3] = _lufs_s_btn.get_active (); - _preset.enable[4] = _lufs_m_btn.get_active (); - } else { - /* retore preset name, in case user has changed it */ - _preset.name = _initial_preset_name; + _last_preset = _preset; } return r; @@ -426,7 +424,7 @@ LoudnessDialog::run () gint LoudnessDialog::progress_timeout () { - float progress = ((float) _status->processed_samples_current_timespan) / _status->total_samples_current_timespan; + float progress = ((float)_status->processed_samples_current_timespan) / _status->total_samples_current_timespan; _progress_bar.set_text ("Analyzing"); _progress_bar.set_fraction (progress); return true; @@ -435,18 +433,19 @@ LoudnessDialog::progress_timeout () int LoudnessDialog::analyze () { - /* These are ensured in Editor::measure_master_loudness () */ - assert (_session->master_out()); + /* These are ensured in Editor::measure_master_loudness () */ + assert (_session->master_out ()); assert (_session->master_volume ()); - assert (_session->master_out()->output()); - assert (_session->master_out()->output()->n_ports().n_audio() == 2); + assert (_session->master_out ()->output ()); + assert (_session->master_out ()->output ()->n_ports ().n_audio () == 2); assert (_range.start < _range.end); - ExportTimespanPtr tsp = _session->get_export_handler()->add_timespan(); - boost::shared_ptr ccp = _session->get_export_handler()->add_channel_config(); - boost::shared_ptr fnp = _session->get_export_handler()->add_filename(); - boost::shared_ptr fmp = _session->get_export_handler()->add_format(); + ExportTimespanPtr tsp = _session->get_export_handler ()->add_timespan (); + + boost::shared_ptr ccp = _session->get_export_handler ()->add_channel_config (); + boost::shared_ptr fnp = _session->get_export_handler ()->add_filename (); + boost::shared_ptr fmp = _session->get_export_handler ()->add_format (); /* setup format */ fmp->set_tag (false); @@ -465,9 +464,9 @@ LoudnessDialog::analyze () tsp->set_name ("master"); /* setup channels, use master out */ - IO* master_out = _session->master_out()->output().get(); - for (uint32_t n = 0; n < master_out->n_ports().n_audio(); ++n) { - PortExportChannel * channel = new PortExportChannel (); + IO* master_out = _session->master_out ()->output ().get (); + for (uint32_t n = 0; n < master_out->n_ports ().n_audio (); ++n) { + PortExportChannel* channel = new PortExportChannel (); channel->add_port (master_out->audio (n)); ExportChannelPtr chan_ptr (channel); ccp->register_channel (chan_ptr); @@ -475,9 +474,9 @@ LoudnessDialog::analyze () /* do audio export */ boost::shared_ptr b; - _session->get_export_handler()->reset (); - _session->get_export_handler()->add_export_config (tsp, ccp, fmp, fnp, b); - _session->get_export_handler()->do_export(); + _session->get_export_handler ()->reset (); + _session->get_export_handler ()->add_export_config (tsp, ccp, fmp, fnp, b); + _session->get_export_handler ()->do_export (); /* show progress */ _setup_box.hide (); @@ -488,27 +487,27 @@ LoudnessDialog::analyze () get_size (wr.width, wr.height); resize (wr.width, 60); - sigc::connection progress_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &LoudnessDialog::progress_timeout), 100); + sigc::connection progress_connection = Glib::signal_timeout ().connect (sigc::mem_fun (*this, &LoudnessDialog::progress_timeout), 100); while (_status->running ()) { - if (gtk_events_pending()) { + if (gtk_events_pending ()) { gtk_main_iteration (); } else { Glib::usleep (10000); } } - progress_connection.disconnect(); + progress_connection.disconnect (); _progress_box.hide_all (); /* done */ - _status->finish (TRS_UI); + _status->finish (TRS_UI); - if (!_status->aborted() && _status->result_map.size () != 1) { + if (!_status->aborted () && _status->result_map.size () != 1) { ArdourMessageDialog (_("Loudness measurement returned no results. Likely because the analyzed range is to short."), false, MESSAGE_ERROR).run (); return 1; } - return _status->aborted() ? 1 : 0; + return _status->aborted () ? 1 : 0; } void @@ -516,7 +515,79 @@ LoudnessDialog::display_report () { ExportReport er (_("Export Loudness Report"), _status->result_map); er.set_transient_for (*this); - er.run(); + er.run (); +} + +void +LoudnessDialog::save_preset () +{ + assert (_preset.user); + ArdourWidgets::Prompter name_prompter (*this, true, true); + name_prompter.set_title (_("Save Loudness Preset")); + name_prompter.set_prompt (_("Name:")); + name_prompter.add_button (_("Save"), Gtk::RESPONSE_ACCEPT); + name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); + name_prompter.set_initial_text (_preset.label, _preset.label != _("Custom")); + name_prompter.show_all (); + + bool saved = false; + bool done = false; + std::string result; + + while (!done) { + switch (name_prompter.run ()) { + case Gtk::RESPONSE_ACCEPT: + name_prompter.get_result (result); + name_prompter.hide (); + if (result.length()) { + if (result == _("Custom")) { + /* ask again */ + continue; + } + _preset.label = result; + _preset.report = false; + if (_lp.push_back (_preset)) { + done = true; + saved = true; + } else { + /* Invalid Name, ask again */ + } + } else { + /* nothing entered, just get out of here */ + done = true; + } + break; + default: + done = true; + break; + } + } + if (saved) { + _preset_dropdown.clear_items (); + for (size_t i = 0; i < _lp.n_presets (); ++i) { + using namespace Gtkmm2ext; + _preset_dropdown.AddMenuElem (MenuElemNoMnemonic (_lp[i].label, sigc::bind (sigc::mem_fun (*this, &LoudnessDialog::load_preset), i))); + } + PBD::Unwinder uw (_ignore_preset, true); + _preset_dropdown.set_active (_preset.label); + _save_preset.set_sensitive (false); + _remove_preset.set_sensitive (_preset.user); + } +} + +void +LoudnessDialog::remove_preset () +{ + assert (_preset.user); + if (_lp.erase (_preset)) { + _preset_dropdown.clear_items (); + for (size_t i = 0; i < _lp.n_presets (); ++i) { + using namespace Gtkmm2ext; + _preset_dropdown.AddMenuElem (MenuElemNoMnemonic (_lp[i].label, sigc::bind (sigc::mem_fun (*this, &LoudnessDialog::load_preset), i))); + } + _preset.label = _("Custom"); + update_settings (); + } } void @@ -525,7 +596,9 @@ LoudnessDialog::load_preset (size_t n) if (_ignore_preset) { return; } - _preset = presets[n]; + _preset = _lp[n]; + _save_preset.set_sensitive (false); + _remove_preset.set_sensitive (_preset.user); apply_preset (); calculate_gain (); } @@ -534,7 +607,7 @@ void LoudnessDialog::apply_preset () { PBD::Unwinder uw (_ignore_change, true); - _preset_dropdown.set_text (_preset.name); + _preset_dropdown.set_text (_preset.label); _dbfs_btn.set_active (_preset.enable[0]); _dbtp_btn.set_active (_preset.enable[1]); @@ -559,15 +632,44 @@ LoudnessDialog::update_sensitivity () _lufs_m_spinbutton.set_sensitive (_lufs_m_btn.get_active () && _lufs_m_btn.sensitive ()); } +void +LoudnessDialog::check_preset () +{ + if (_lp.find_preset (_preset)) { + _save_preset.set_sensitive (false); + _remove_preset.set_sensitive (_preset.user); + } else { + if (!_preset.user) { + _preset.label = _("Custom"); + } + _preset.user = true; + _preset.report = false; + _save_preset.set_sensitive (true); + _remove_preset.set_sensitive (false); + } + _preset_dropdown.set_text (_preset.label); +} + void LoudnessDialog::update_settings () { if (_ignore_change) { return; } - _preset.name = _("Custom"); - _preset_dropdown.set_text (_preset.name); + /* check if preset with current settings exists */ + _preset.level[0] = _dbfs_spinbutton.get_value (); + _preset.level[1] = _dbtp_spinbutton.get_value (); + _preset.level[2] = _lufs_i_spinbutton.get_value (); + _preset.level[3] = _lufs_s_spinbutton.get_value (); + _preset.level[4] = _lufs_m_spinbutton.get_value (); + _preset.enable[0] = _dbfs_btn.get_active (); + _preset.enable[1] = _dbtp_btn.get_active (); + _preset.enable[2] = _lufs_i_btn.get_active (); + _preset.enable[3] = _lufs_s_btn.get_active (); + _preset.enable[4] = _lufs_m_btn.get_active (); + + check_preset (); update_sensitivity (); calculate_gain (); } @@ -583,19 +685,22 @@ LoudnessDialog::display_results () { AnalysisResults const& ar (_status->result_map); assert (ar.size () == 1); - ExportAnalysisPtr p = ar.begin()->second; + ExportAnalysisPtr p = ar.begin ()->second; - if (!p->have_loudness || !p->have_dbtp) { + if (!p->have_loudness || !p->have_dbtp || !p->have_lufs_graph) { ArdourMessageDialog ( - string_compose (_("True-peak and loudness measurement failed. %1-VAMP analysis plugin is missing on your system. Please contact your vendor."), PROGRAM_NAME), - false, MESSAGE_ERROR).run (); + string_compose (_("True-peak and loudness measurement failed. %1-VAMP analysis plugin is missing on your system. Please contact your vendor."), PROGRAM_NAME), + false, MESSAGE_ERROR) + .run (); } + plot_graph (p); + _dbfs = accurate_coefficient_to_dB (p->peak); _dbtp = accurate_coefficient_to_dB (p->truepeak); - _lufs_i = p->integrated_loudness > -200 ? p->integrated_loudness : -std::numeric_limits::infinity(); - _lufs_s = p->max_loudness_short > -200 ? p->max_loudness_short : -std::numeric_limits::infinity(); - _lufs_m = p->max_loudness_momentary > - 200 ? p->max_loudness_momentary : -std::numeric_limits::infinity(); + _lufs_i = p->integrated_loudness > -200 ? p->integrated_loudness : -std::numeric_limits::infinity (); + _lufs_s = p->max_loudness_short > -200 ? p->max_loudness_short : -std::numeric_limits::infinity (); + _lufs_m = p->max_loudness_momentary > -200 ? p->max_loudness_momentary : -std::numeric_limits::infinity (); _dbfs_btn.set_sensitive (_dbfs > -300); _dbtp_btn.set_sensitive (_dbtp > -300); @@ -619,17 +724,24 @@ LoudnessDialog::display_results () void LoudnessDialog::calculate_gain () { - float dbfs = _dbfs_spinbutton.get_value(); - float dbtp = _dbtp_spinbutton.get_value(); - float lufs_i = _lufs_i_spinbutton.get_value(); - float lufs_s = _lufs_s_spinbutton.get_value(); - float lufs_m = _lufs_m_spinbutton.get_value(); + float dbfs = _dbfs_spinbutton.get_value (); + float dbtp = _dbtp_spinbutton.get_value (); + float lufs_i = _lufs_i_spinbutton.get_value (); + float lufs_s = _lufs_s_spinbutton.get_value (); + float lufs_m = _lufs_m_spinbutton.get_value (); - float gain = 0; - bool set = false; + float gain = 0; + bool set = false; -#define MIN_IF_SET(A, B) \ - { if (set) { gain = std::min (gain, (A) - (B));} else { gain = (A) - (B); } set = true; } +#define MIN_IF_SET(A, B) \ + { \ + if (set) { \ + gain = std::min (gain, (A) - (B)); \ + } else { \ + gain = (A) - (B); \ + } \ + set = true; \ + } if (_dbfs_btn.get_active () && _dbfs_btn.sensitive ()) { MIN_IF_SET (dbfs, _dbfs); @@ -659,7 +771,7 @@ LoudnessDialog::calculate_gain () _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 = gain; bool in_range = gain_db () >= -40 && gain_db () <= 40; _gain_norm_label.set_text (string_compose (_("%1 dB"), std::setprecision (2), std::showpos, std::fixed, _gain_norm)); @@ -668,89 +780,119 @@ LoudnessDialog::calculate_gain () _gain_total_label.set_markup (_(" \u00B140 dB")); } else { _gain_exceeds_label.set_text (X_("")); - _gain_total_label.set_markup (string_compose (_("%1 dB"), std::setw(7), std::setprecision (2), std::showpos, std::fixed, gain_db ())); + _gain_total_label.set_markup (string_compose (_("%1 dB"), std::setw (7), std::setprecision (2), std::showpos, std::fixed, gain_db ())); } test_conformity (); _ok_button->set_sensitive (in_range); } -void -LoudnessDialog::toggle_conformity_display () -{ - if (_conformity_expander.get_expanded ()) { - test_conformity (); - } else { - const int child_height = _conformity_expander.get_child ()->get_height (); - _conformity_expander.remove (); - - Gtk::Requisition wr; - get_size (wr.width, wr.height); - wr.height -= child_height; - resize (wr.width, wr.height); - } -} - void LoudnessDialog::test_conformity () { - if (!_conformity_expander.get_expanded ()) { - return; - } - if (_conformity_expander.get_child ()) { - _conformity_expander.remove (); + if (_conformity_frame.get_child ()) { + _conformity_frame.remove (); } const float dbfs = rintf ((_dbfs + _gain_norm) * 10.f) / 10.f; const float dbtp = rintf ((_dbtp + _gain_norm) * 10.f) / 10.f; const float lufs_i = rintf ((_lufs_i + _gain_norm) * 10.f) / 10.f; - Table* t = manage (new Table ()); - size_t n_pset = sizeof (presets) / sizeof (LoudnessDialog::LoudnessPreset); + Table* t = manage (new Table ()); + size_t n_pset = _lp.n_presets (); size_t n_rows = ceil (n_pset / 3.0); size_t row = 0; size_t col = 0; - uint32_t c_good = UIConfigurationBase::instance().color ("alert:green"); // OK / green - uint32_t c_warn = UIConfigurationBase::instance().color ("alert:yellow"); // Warning / yellow - uint32_t c_fail = UIConfigurationBase::instance().color ("alert:red"); // Fail / red + uint32_t c_good = UIConfigurationBase::instance ().color ("alert:green"); // OK / green + uint32_t c_warn = UIConfigurationBase::instance ().color ("alert:yellow"); // Warning / yellow + uint32_t c_fail = UIConfigurationBase::instance ().color ("alert:red"); // Fail / red Gdk::Color color_good = ARDOUR_UI_UTILS::gdk_color_from_rgba (c_good); Gdk::Color color_warn = ARDOUR_UI_UTILS::gdk_color_from_rgba (c_warn); Gdk::Color color_fail = ARDOUR_UI_UTILS::gdk_color_from_rgba (c_fail); for (size_t i = 1; i < n_pset; ++i) { - Label* l = manage (new Label (presets[i].name + ":", ALIGN_LEFT)); - t->attach (*l, col, col + 1, row, row + 1, EXPAND|FILL, SHRINK, 2, 0); + CLoudnessPreset const& preset = _lp[i]; + Label* l = manage (new Label (preset.label + ":", ALIGN_LEFT)); + t->attach (*l, col, col + 1, row, row + 1, EXPAND | FILL, SHRINK, 2, 0); - if (lufs_i > presets[i].max_integrated[0] - || (presets[i].enable[0] && dbfs > presets[i].level[0]) - || (presets[i].enable[1] && dbtp > presets[i].level[1]) + if (lufs_i > preset.LUFS_range[0] + || (preset.enable[0] && dbfs > preset.level[0]) + || (preset.enable[1] && dbtp > preset.level[1]) ) { - l = manage (new Label ("\u274C", ALIGN_CENTER)); // "X" + l = manage (new Label ("\u274C", ALIGN_CENTER)); // cross mark + l->modify_font (UIConfiguration::instance ().get_NormalMonospaceFont ()); l->modify_fg (Gtk::STATE_NORMAL, color_fail); + Gtkmm2ext::set_size_request_to_display_given_text (*l, "\u274C\u2714", 0, 0); set_tooltip (*l, "The signal is too loud."); - } else if (lufs_i < presets[i].max_integrated[1]) { - l = manage (new Label ("\u2713", ALIGN_CENTER)); // "check-mark" - maybe use inv-box: \u274C + } else if (lufs_i < preset.LUFS_range[1]) { + l = manage (new Label ("\u2714", ALIGN_CENTER)); // heavy check mark + l->modify_font (UIConfiguration::instance ().get_NormalMonospaceFont ()); l->modify_fg (Gtk::STATE_NORMAL, color_warn); + Gtkmm2ext::set_size_request_to_display_given_text (*l, "\u274C\u2714", 0, 0); set_tooltip (*l, "The signal is too quiet, but satisfies the max. loudness spec."); } else { - l = manage (new Label ("\u2713", ALIGN_CENTER)); // "check-mark" + l = manage (new Label ("\u2714", ALIGN_CENTER)); // heavy check mark + l->modify_font (UIConfiguration::instance ().get_NormalMonospaceFont ()); l->modify_fg (Gtk::STATE_NORMAL, color_good); set_tooltip (*l, "Signal loudness is within the spec."); + Gtkmm2ext::set_size_request_to_display_given_text (*l, "\u274C\u2714", 0, 0); } t->attach (*l, col + 1, col + 2, row, row + 1, SHRINK, SHRINK, 2, 0); if (++row == n_rows) { ArdourVSpacer* spc = manage (new ArdourVSpacer (1.0)); - t->attach (*spc, col + 2, col + 3, 0, n_rows, FILL, EXPAND|FILL, 8, 0); + t->attach (*spc, col + 2, col + 3, 0, n_rows, FILL, EXPAND | FILL, 8, 0); row = 0; col += 3; } } - _conformity_expander.add (*t); - _conformity_expander.show_all (); + t->set_border_width (6); + _conformity_frame.add (*t); + _conformity_frame.show_all (); +} + +void +LoudnessDialog::graph_size_request (Gtk::Requisition* req) +{ + if (_loudness_surf) { + req->width = _loudness_surf->get_width (); + req->height = _loudness_surf->get_height (); + } else { + req->width = 1; + req->height = 1; + } +} + +bool +LoudnessDialog::graph_expose_event (GdkEventExpose* ev) +{ + Cairo::RefPtr cr = _loudness_graph.get_window ()->create_cairo_context (); +#if 0 + Gtk::Allocation a = _loudness_graph.get_allocation (); + double const width = a.get_width (); + double const height = a.get_height (); +#endif + + cr->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); + cr->clip (); + + if (_loudness_surf) { + cr->set_source (_loudness_surf, 0, 0); + cr->set_operator (Cairo::OPERATOR_OVER); + cr->paint (); + } + + return true; +} + +void +LoudnessDialog::plot_graph (ExportAnalysisPtr p) +{ + _loudness_surf = ArdourGraphs::plot_loudness (get_pango_context (), p, -1, 0, _session->nominal_sample_rate ()); + _loudness_graph.queue_resize (); } diff --git a/gtk2_ardour/loudness_dialog.h b/gtk2_ardour/loudness_dialog.h index 3a3c98abda..0780f7bb9d 100644 --- a/gtk2_ardour/loudness_dialog.h +++ b/gtk2_ardour/loudness_dialog.h @@ -19,8 +19,10 @@ #ifndef _gtkardour_loudness_dialog_h_ #define _gtkardour_loudness_dialog_h_ +#include #include -#include +#include +#include #include #include #include @@ -31,9 +33,11 @@ #include "ardour_dialog.h" #include "progress_reporter.h" +#include "loudness_settings.h" namespace ARDOUR { class AudioRange; + class ExportAnalysis; class ExportStatus; class PluginInsert; class Processor; @@ -58,26 +62,28 @@ private: gint progress_timeout (); void display_results (); void display_report (); + void save_preset (); + void remove_preset (); void calculate_gain (); void load_preset (size_t); void apply_preset (); + void peak_radio (bool); void update_settings (); + void check_preset (); void update_sensitivity (); void test_conformity (); - void toggle_conformity_display (); - struct LoudnessPreset - { - std::string name; - bool enable[5]; - float level[5]; - float max_integrated[2]; - }; + void plot_graph (boost::shared_ptr); + void graph_size_request (Gtk::Requisition*); + bool graph_expose_event (GdkEventExpose*); - static LoudnessPreset presets[]; - static LoudnessPreset _preset; + ALoudnessPresets _lp; + CLoudnessPreset _preset; + + static bool _first_time; + static CLoudnessPreset _last_preset; ARDOUR::Session* _session; ARDOUR::AudioRange const& _range; @@ -87,34 +93,41 @@ private: Gtk::VBox _setup_box; Gtk::VBox _progress_box; Gtk::VBox _result_box; - Gtk::Expander _conformity_expander; + Gtk::Frame _conformity_frame; Gtk::ProgressBar _progress_bar; Gtk::Button* _ok_button; Gtk::Button* _cancel_button; + ArdourWidgets::ArdourButton _save_preset; + ArdourWidgets::ArdourButton _remove_preset; + 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; - Gtk::Label _lufs_s_label; - Gtk::Label _lufs_m_label; + Gtk::Label _dbfs_label; + Gtk::Label _dbtp_label; + Gtk::Label _lufs_i_label; + Gtk::Label _lufs_s_label; + Gtk::Label _lufs_m_label; - Gtk::Label _delta_dbfs_label; - Gtk::Label _delta_dbtp_label; - Gtk::Label _delta_lufs_i_label; - Gtk::Label _delta_lufs_s_label; - Gtk::Label _delta_lufs_m_label; + Gtk::Label _delta_dbfs_label; + Gtk::Label _delta_dbtp_label; + Gtk::Label _delta_lufs_i_label; + Gtk::Label _delta_lufs_s_label; + Gtk::Label _delta_lufs_m_label; - Gtk::Label _gain_out_label; - Gtk::Label _gain_amp_label; - Gtk::Label _gain_norm_label; - Gtk::Label _gain_total_label; - Gtk::Label _gain_exceeds_label; + Gtk::Label _gain_out_label; + Gtk::Label _gain_amp_label; + Gtk::Label _gain_norm_label; + Gtk::Label _gain_total_label; + Gtk::Label _gain_exceeds_label; + + Gtk::DrawingArea _loudness_graph; + + Cairo::RefPtr _loudness_surf; ArdourWidgets::ArdourButton _rt_analysis_button; ArdourWidgets::ArdourButton _start_analysis_button; @@ -122,19 +135,18 @@ private: ArdourWidgets::ArdourButton _custom_pos_button; ArdourWidgets::ArdourDropdown _preset_dropdown; - std::string _initial_preset_name; - Gtk::Adjustment _dbfs_adjustment; - Gtk::Adjustment _dbtp_adjustment; - Gtk::Adjustment _lufs_i_adjustment; - Gtk::Adjustment _lufs_s_adjustment; - Gtk::Adjustment _lufs_m_adjustment; + Gtk::Adjustment _dbfs_adjustment; + Gtk::Adjustment _dbtp_adjustment; + Gtk::Adjustment _lufs_i_adjustment; + Gtk::Adjustment _lufs_s_adjustment; + Gtk::Adjustment _lufs_m_adjustment; Gtk::SpinButton _dbfs_spinbutton; - Gtk::SpinButton _dbtp_spinbutton; - Gtk::SpinButton _lufs_i_spinbutton; - Gtk::SpinButton _lufs_s_spinbutton; - Gtk::SpinButton _lufs_m_spinbutton; + Gtk::SpinButton _dbtp_spinbutton; + Gtk::SpinButton _lufs_i_spinbutton; + Gtk::SpinButton _lufs_s_spinbutton; + Gtk::SpinButton _lufs_m_spinbutton; float _dbfs; float _dbtp;