2020-07-19 18:29:56 -04:00
/*
* Copyright ( C ) 2020 Robin Gareus < robin @ gareus . org >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA .
*/
2020-08-04 15:22:05 -04:00
# include <gtkmm/alignment.h>
2020-07-19 18:29:56 -04:00
# include <gtkmm/label.h>
# include <gtkmm/stock.h>
2020-07-22 20:58:59 -04:00
# include "pbd/unwind.h"
2020-07-19 18:29:56 -04:00
# include "ardour/dB.h"
2020-07-25 02:14:04 -04:00
# include "ardour/plugin_insert.h"
2021-04-11 19:32:00 -04:00
# include "ardour/plugin_manager.h"
2020-07-25 02:14:04 -04:00
# include "ardour/processor.h"
2020-07-20 18:40:11 -04:00
# include "ardour/session.h"
2020-07-19 18:29:56 -04:00
# include "ardour/export_channel_configuration.h"
# include "ardour/export_filename.h"
# include "ardour/export_format_base.h"
# include "ardour/export_format_specification.h"
# include "ardour/export_handler.h"
# include "ardour/export_status.h"
# include "ardour/export_timespan.h"
2020-07-22 20:58:59 -04:00
# include "gtkmm2ext/menu_elems.h"
2020-07-21 21:26:19 -04:00
# include "gtkmm2ext/utils.h"
2020-07-20 22:45:46 -04:00
# include "widgets/ardour_spacer.h"
2021-04-11 19:32:00 -04:00
# include "widgets/prompter.h"
2020-07-25 02:14:04 -04:00
# include "widgets/tooltips.h"
2020-07-20 22:45:46 -04:00
2020-07-25 02:14:04 -04:00
# include "ardour_message.h"
2021-04-11 19:32:00 -04:00
# include "export_analysis_graphs.h"
2020-07-19 18:29:56 -04:00
# include "export_report.h"
# include "loudness_dialog.h"
2020-07-21 21:26:19 -04:00
# include "ui_config.h"
2020-07-19 18:29:56 -04:00
# include "pbd/i18n.h"
using namespace Gtk ;
using namespace ARDOUR ;
2020-07-20 22:45:46 -04:00
using namespace ArdourWidgets ;
2020-07-19 18:29:56 -04:00
2021-04-11 19:32:00 -04:00
bool LoudnessDialog : : _first_time = true ;
CLoudnessPreset LoudnessDialog : : _last_preset ;
2020-07-22 20:58:59 -04:00
2020-09-26 11:14:59 -04:00
LoudnessDialog : : LoudnessDialog ( Session * s , TimelineRange const & ar , bool as )
2020-07-21 21:26:19 -04:00
: ArdourDialog ( as ? _ ( " Loudness Assistant " ) : _ ( " Loudness Analyzer and Normalizer " ) )
2021-04-11 19:32:00 -04:00
, _lp ( false )
2020-07-19 18:29:56 -04:00
, _session ( s )
2020-07-20 18:40:11 -04:00
, _range ( ar )
2020-07-19 18:29:56 -04:00
, _status ( s - > get_export_status ( ) )
2020-07-20 22:45:46 -04:00
, _autostart ( as )
2021-04-11 19:32:00 -04:00
, _conformity_frame ( _ ( " Conformity Analysis (with gain applied) " ) )
, _save_preset ( _ ( " Save " ) )
, _remove_preset ( _ ( " Remove " ) )
2020-07-21 21:26:19 -04:00
, _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 )
2020-07-20 22:45:46 -04:00
, _rt_analysis_button ( _ ( " Realtime " ) , ArdourButton : : led_default_elements , true )
, _start_analysis_button ( _ ( " Analyze " ) )
2021-04-11 19:32:00 -04:00
, _show_report_button ( _ ( " Analysis Report " ) )
2020-08-01 04:14:38 -04:00
, _custom_pos_button ( _ ( " Custom Amplifier Position " ) , ArdourButton : : led_default_elements , true )
2021-04-11 19:32:00 -04:00
, _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 )
2020-07-19 18:29:56 -04:00
, _dbfs_spinbutton ( _dbfs_adjustment , 0.1 , 1 )
, _dbtp_spinbutton ( _dbtp_adjustment , 0.1 , 1 )
2020-07-20 22:45:46 -04:00
, _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 )
2020-07-25 02:14:04 -04:00
, _gain_out ( 0 )
2020-07-21 21:26:19 -04:00
, _gain_norm ( 0 )
2020-08-04 17:36:29 -04:00
, _ignore_preset ( false )
2020-07-22 20:58:59 -04:00
, _ignore_change ( false )
2020-07-19 18:29:56 -04:00
{
2021-04-11 19:32:00 -04:00
_preset = _lp [ 0 ] ;
if ( _first_time ) {
_first_time = false ;
_last_preset = _lp [ 0 ] ;
}
_preset = _last_preset ;
2020-11-18 10:26:36 -05:00
/* Dialog can be displayed from the mixer, override global transient_parent */
unset_transient_for ( ) ;
2020-07-25 02:14:04 -04:00
/* query initial gain */
2021-04-11 19:32:00 -04:00
_gain_out = accurate_coefficient_to_dB ( _session - > master_volume ( ) - > get_value ( ) ) ;
2020-07-25 02:14:04 -04:00
2020-08-04 15:22:05 -04:00
/* setup styles */
2020-07-20 22:45:46 -04:00
_start_analysis_button . set_name ( " generic button " ) ;
_rt_analysis_button . set_name ( " generic button " ) ;
_show_report_button . set_name ( " generic button " ) ;
2020-07-27 16:00:08 -04:00
_custom_pos_button . set_name ( " generic button " ) ;
2020-07-25 02:14:04 -04:00
2020-07-27 16:00:08 -04:00
_custom_pos_button . set_active ( ! _session - > master_out ( ) - > volume_applies_to_output ( ) ) ;
2020-07-20 22:45:46 -04:00
2020-07-22 21:56:49 -04:00
GtkRequisition req = _start_analysis_button . size_request ( ) ;
_start_analysis_button . set_size_request ( - 1 , req . height * 1.1 ) ;
_rt_analysis_button . set_size_request ( - 1 , req . height * 1.1 ) ;
2021-04-11 19:32:00 -04:00
_save_preset . set_name ( " generic button " ) ;
_remove_preset . set_name ( " generic button " ) ;
2020-07-21 21:26:19 -04:00
_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 ) ;
2021-04-11 19:32:00 -04:00
_preset_dropdown . set_can_focus ( true ) ;
2020-08-04 15:22:05 -04:00
_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 ) ;
2021-04-11 19:32:00 -04:00
_save_preset . set_can_focus ( true ) ;
_remove_preset . set_can_focus ( true ) ;
2020-08-04 15:22:05 -04:00
_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 ) ;
2021-04-11 19:32:00 -04:00
_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 ( ) ) ;
2020-07-21 21:26:19 -04:00
2021-04-11 19:32:00 -04:00
_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 ( ) ) ;
2020-07-21 21:26:19 -04:00
2021-04-11 19:32:00 -04:00
_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 ( ) ) ;
2020-07-21 21:26:19 -04:00
2020-08-04 15:22:05 -04:00
/* result display layout */
2021-04-11 19:32:00 -04:00
# define ROW row, row + 1
2020-07-22 21:56:49 -04:00
2021-04-11 19:32:00 -04:00
int row = 0 ;
2020-07-20 22:45:46 -04:00
Label * l ;
2021-04-11 19:32:00 -04:00
Table * t = manage ( new Table ( 11 , 8 , false ) ) ;
2020-07-19 18:29:56 -04:00
t - > set_spacings ( 4 ) ;
2020-07-20 22:45:46 -04:00
2022-01-26 16:19:32 -05:00
l = manage ( new Label ( _ ( " Preset: " ) , ALIGN_START ) ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 0 , 1 , ROW , SHRINK | FILL ) ;
t - > attach ( _preset_dropdown , 1 , 3 , ROW ) ;
2020-07-22 21:56:49 -04:00
2021-04-11 19:32:00 -04:00
t - > attach ( _save_preset , 3 , 4 , ROW , SHRINK | FILL ) ;
t - > attach ( _remove_preset , 4 , 5 , ROW , SHRINK | FILL ) ;
2020-07-20 22:45:46 -04:00
2021-04-11 19:32:00 -04:00
/* horiz space */
2022-01-26 16:19:32 -05:00
l = manage ( new Label ( " " , ALIGN_START ) ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 5 , 6 , ROW , SHRINK , SHRINK , 6 , 0 ) ;
2022-01-26 16:19:32 -05:00
l = manage ( new Label ( " " , ALIGN_START ) ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 6 , 7 , ROW ) ;
t - > attach ( _show_report_button , 7 , 8 , ROW , SHRINK | FILL ) ;
+ + row ;
2020-07-20 22:45:46 -04:00
l = manage ( new Label ( _ ( " <b>Target</b> " ) , ALIGN_CENTER ) ) ;
2020-07-19 23:26:23 -04:00
l - > set_use_markup ( true ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 2 , 3 , ROW ) ;
2020-07-22 21:56:49 -04:00
l = manage ( new Label ( _ ( " <b>Measured</b> " ) , ALIGN_CENTER ) ) ;
l - > set_use_markup ( true ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 3 , 4 , ROW ) ;
2020-07-20 22:45:46 -04:00
l = manage ( new Label ( _ ( " <b>Delta</b> " ) , ALIGN_CENTER ) ) ;
2020-07-19 23:26:23 -04:00
l - > set_use_markup ( true ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 4 , 5 , ROW ) ;
2020-07-19 23:26:23 -04:00
2021-04-11 19:32:00 -04:00
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 ;
2020-07-21 21:26:19 -04:00
2020-07-25 02:14:04 -04:00
+ + row ; // spacer
2022-01-26 16:19:32 -05:00
l = manage ( new Label ( _ ( " Gain to normalize: " ) , ALIGN_START ) ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 0 , 2 , ROW ) ; + + row ;
2022-01-26 16:19:32 -05:00
l = manage ( new Label ( _ ( " Previous output gain: " ) , ALIGN_START ) ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 0 , 2 , ROW ) ; + + row ;
2020-07-25 02:14:04 -04:00
2022-01-26 16:19:32 -05:00
l = manage ( new Label ( _ ( " Total gain: " ) , ALIGN_START ) ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 0 , 2 , 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 = 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 = 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 ;
2020-07-20 22:45:46 -04:00
ArdourHSpacer * spc = manage ( new ArdourHSpacer ( 1.0 ) ) ;
2021-04-11 19:32:00 -04:00
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 ) ;
2020-07-27 14:00:17 -04:00
2020-07-27 16:00:08 -04:00
set_tooltip ( _custom_pos_button ,
_ ( " <b>When enabled</b> an amplifier processor is used to apply the gain. "
2020-09-13 08:30:12 -04:00
" This allows for custom positioning of the gain-stage in the master-bus' signal flow, "
2020-08-01 04:14:38 -04:00
" potentially followed by a limiter to conform to both loudness and peak requirements. "
2020-07-25 02:14:04 -04:00
" Depending on limiter settings or DSP after the gain-stage, repeat loudness measurements may produce different results. \n "
2020-09-13 08:30:12 -04:00
" <b>When disabled</b>, the gain is applied directly to the output of the master-bus. This results in an efficient and reliable volume adjustment. "
2020-07-25 02:14:04 -04:00
) ) ;
2020-07-22 20:58:59 -04:00
2022-01-26 16:20:26 -05:00
_dbfs_label . set_alignment ( ALIGN_END ) ;
_dbtp_label . set_alignment ( ALIGN_END ) ;
_lufs_i_label . set_alignment ( ALIGN_END ) ;
_lufs_s_label . set_alignment ( ALIGN_END ) ;
_lufs_m_label . set_alignment ( ALIGN_END ) ;
_delta_dbfs_label . set_alignment ( ALIGN_END ) ;
_delta_dbtp_label . set_alignment ( ALIGN_END ) ;
_delta_lufs_i_label . set_alignment ( ALIGN_END ) ;
_delta_lufs_s_label . set_alignment ( ALIGN_END ) ;
_delta_lufs_m_label . set_alignment ( ALIGN_END ) ;
_gain_norm_label . set_alignment ( ALIGN_END ) ;
_gain_out_label . set_alignment ( ALIGN_END ) ;
_gain_total_label . set_alignment ( ALIGN_END ) ;
_gain_exceeds_label . set_alignment ( ALIGN_END ) ;
2020-07-19 18:29:56 -04:00
2021-04-11 19:32:00 -04:00
HBox * hb = manage ( new ( HBox ) ) ;
hb - > pack_start ( _loudness_graph , true , false ) ;
_result_box . pack_start ( * hb , false , false , 0 ) ;
2020-07-19 18:29:56 -04:00
_result_box . pack_start ( * t , false , false , 6 ) ;
2020-07-27 14:00:17 -04:00
2020-08-04 15:22:05 -04:00
/* analysis progress layout */
2020-07-19 18:29:56 -04:00
_progress_box . pack_start ( _progress_bar , false , false , 6 ) ;
2020-08-04 15:22:05 -04:00
/* setup and info layout */
2020-07-20 22:45:46 -04:00
t = manage ( new Table ( 2 , 3 , false ) ) ;
t - > set_spacings ( 4 ) ;
2020-08-04 15:22:05 -04:00
l = manage ( new Label ( ) ) ;
l - > set_markup ( _ ( " <b>Loudness Analysis</b> \n " ) ) ;
2022-01-26 18:04:44 -05:00
l - > set_alignment ( ALIGN_START , ALIGN_START ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , 0 , 1 , 0 , 1 , EXPAND | FILL , FILL , 8 , 2 ) ;
2020-08-04 15:22:05 -04:00
2020-07-20 22:45:46 -04:00
l = manage ( new Label ( ) ) ;
l - > set_line_wrap ( ) ;
2022-01-26 18:04:44 -05:00
l - > set_alignment ( ALIGN_START , ALIGN_START ) ;
2020-07-20 22:45:46 -04:00
l - > set_markup ( _ (
2021-04-11 19:32:00 -04:00
" 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 ) ;
2020-07-22 21:56:49 -04:00
l = manage ( new Label ( ) ) ;
l - > set_line_wrap ( ) ;
2022-01-26 18:04:44 -05:00
l - > set_alignment ( ALIGN_START , ALIGN_START ) ;
2020-07-22 21:56:49 -04:00
l - > set_markup ( _ (
2021-04-11 19:32:00 -04:00
" By default, a faster-than-realtime export is used to assess the loudness of the "
" session. If any outboard gear is used, a <i>realtime</i> export is available, to "
" play at normal speed. " ) ) ;
t - > attach ( * l , 0 , 1 , 2 , 3 , EXPAND | FILL , FILL , 8 , 2 ) ;
2020-08-04 15:22:05 -04:00
Alignment * align = manage ( new Alignment ( 0 , 0 , 1 , 0 ) ) ;
align - > add ( _start_analysis_button ) ;
t - > attach ( * align , 1 , 2 , 1 , 2 , FILL , FILL , 2 , 0 ) ;
2020-07-22 21:56:49 -04:00
2020-08-04 15:22:05 -04:00
align = manage ( new Alignment ( 0 , 0 , 1 , 0 ) ) ;
align - > add ( _rt_analysis_button ) ;
t - > attach ( * align , 1 , 2 , 2 , 3 , FILL , FILL , 2 , 0 ) ;
2020-07-22 21:56:49 -04:00
2020-07-20 22:45:46 -04:00
_setup_box . pack_start ( * t , false , false , 6 ) ;
2020-08-04 15:22:05 -04:00
/* global layout */
2021-04-11 19:32:00 -04:00
get_vbox ( ) - > pack_start ( _setup_box ) ;
get_vbox ( ) - > pack_start ( _progress_box ) ;
get_vbox ( ) - > pack_start ( _result_box ) ;
2020-07-21 21:26:19 -04:00
2021-04-11 19:32:00 -04:00
_progress_box . set_size_request ( 400 , - 1 ) ;
2020-07-19 18:29:56 -04:00
2020-07-20 22:45:46 -04:00
_ok_button = add_button ( Stock : : APPLY , RESPONSE_APPLY ) ;
_cancel_button = add_button ( Stock : : CANCEL , RESPONSE_CANCEL ) ;
2020-07-19 18:29:56 -04:00
2020-08-04 15:22:05 -04:00
/* fill in presets */
2021-04-11 19:32:00 -04:00
for ( size_t i = 0 ; i < _lp . n_presets ( ) ; + + i ) {
2020-07-22 20:58:59 -04:00
using namespace Gtkmm2ext ;
2021-04-11 19:32:00 -04:00
_preset_dropdown . AddMenuElem ( MenuElemNoMnemonic ( _lp [ i ] . label , sigc : : bind ( sigc : : mem_fun ( * this , & LoudnessDialog : : load_preset ) , i ) ) ) ;
2020-07-22 20:58:59 -04:00
}
apply_preset ( ) ;
2020-07-21 21:26:19 -04:00
2021-04-11 19:32:00 -04:00
if ( ! _lp . find_preset ( _preset ) ) {
_preset . label = _ ( " Custom " ) ;
}
check_preset ( ) ;
2020-07-25 02:14:04 -04:00
_gain_out_label . set_text ( string_compose ( _ ( " %1 dB " ) , std : : setprecision ( 2 ) , std : : showpos , std : : fixed , _gain_out ) ) ;
2021-04-11 19:32:00 -04:00
/* 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 ) ) ;
2020-08-04 15:22:05 -04:00
/* connect signals */
2021-04-11 19:32:00 -04:00
_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 ) ) ;
2020-07-20 22:45:46 -04:00
_show_report_button . signal_clicked . connect ( mem_fun ( * this , & LoudnessDialog : : display_report ) ) ;
_start_analysis_button . signal_clicked . connect ( mem_fun ( * this , & LoudnessDialog : : start_analysis ) ) ;
2020-07-22 20:58:59 -04:00
_dbfs_btn . signal_clicked . connect ( mem_fun ( * this , & LoudnessDialog : : update_settings ) ) ;
_dbtp_btn . signal_clicked . connect ( mem_fun ( * this , & LoudnessDialog : : update_settings ) ) ;
_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 ) ) ;
2020-07-27 14:00:17 -04:00
2020-07-19 18:29:56 -04:00
_ok_button - > set_sensitive ( false ) ;
2020-07-20 22:45:46 -04:00
_show_report_button . set_sensitive ( false ) ;
2020-07-22 20:58:59 -04:00
2020-07-19 18:29:56 -04:00
show_all_children ( ) ;
2020-07-20 22:45:46 -04:00
2020-07-19 18:29:56 -04:00
_result_box . hide ( ) ;
2020-07-20 22:45:46 -04:00
_progress_box . hide ( ) ;
2020-07-19 18:29:56 -04:00
}
void
LoudnessDialog : : cancel_analysis ( )
{
if ( _status - > running ( ) ) {
2021-04-11 19:32:00 -04:00
_status - > abort ( ) ;
2020-07-19 18:29:56 -04:00
}
}
2020-07-20 22:45:46 -04:00
void
LoudnessDialog : : start_analysis ( )
{
if ( 0 = = analyze ( ) ) {
display_results ( ) ;
} else {
_setup_box . show ( ) ;
}
}
2020-07-19 18:29:56 -04:00
bool
2020-07-21 18:00:29 -04:00
LoudnessDialog : : on_delete_event ( GdkEventAny * ev )
2020-07-19 18:29:56 -04:00
{
cancel_analysis ( ) ;
2020-07-21 18:00:29 -04:00
return ArdourDialog : : on_delete_event ( ev ) ;
2020-07-19 18:29:56 -04:00
}
int
LoudnessDialog : : run ( )
{
2020-07-20 22:45:46 -04:00
if ( _autostart ) {
show ( ) ;
if ( 0 = = analyze ( ) ) {
2020-07-19 18:29:56 -04:00
display_results ( ) ;
2020-07-20 22:45:46 -04:00
} else {
2020-07-19 18:29:56 -04:00
return RESPONSE_CANCEL ;
2020-07-20 22:45:46 -04:00
}
2020-07-19 18:29:56 -04:00
}
int const r = ArdourDialog : : run ( ) ;
cancel_analysis ( ) ;
2020-07-22 20:58:59 -04:00
if ( r = = RESPONSE_APPLY ) {
2020-07-27 16:00:08 -04:00
_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 ( ) ) ;
2020-07-25 02:14:04 -04:00
2021-04-11 19:32:00 -04:00
_last_preset = _preset ;
2020-07-22 20:58:59 -04:00
}
2020-07-19 18:29:56 -04:00
return r ;
}
gint
LoudnessDialog : : progress_timeout ( )
{
2021-04-11 19:32:00 -04:00
float progress = ( ( float ) _status - > processed_samples_current_timespan ) / _status - > total_samples_current_timespan ;
2020-07-19 18:29:56 -04:00
_progress_bar . set_text ( " Analyzing " ) ;
_progress_bar . set_fraction ( progress ) ;
return true ;
}
int
LoudnessDialog : : analyze ( )
{
2021-04-11 19:32:00 -04:00
/* These are ensured in Editor::measure_master_loudness () */
assert ( _session - > master_out ( ) ) ;
2020-07-25 02:14:04 -04:00
assert ( _session - > master_volume ( ) ) ;
2020-09-29 19:53:43 -04:00
assert ( _session - > master_out ( ) - > output ( ) ) ;
assert ( _session - > master_out ( ) - > output ( ) - > n_ports ( ) . n_audio ( ) = = 2 ) ;
assert ( _range . start ( ) < _range . end ( ) ) ;
2020-07-19 18:29:56 -04:00
2021-04-11 19:32:00 -04:00
ExportTimespanPtr tsp = _session - > get_export_handler ( ) - > add_timespan ( ) ;
2023-02-16 18:33:28 -05:00
std : : shared_ptr < ExportChannelConfiguration > ccp = _session - > get_export_handler ( ) - > add_channel_config ( ) ;
std : : shared_ptr < ARDOUR : : ExportFilename > fnp = _session - > get_export_handler ( ) - > add_filename ( ) ;
std : : shared_ptr < ExportFormatSpecification > fmp = _session - > get_export_handler ( ) - > add_format ( ) ;
2020-07-19 18:29:56 -04:00
/* setup format */
fmp - > set_sample_format ( ExportFormatBase : : SF_Float ) ;
fmp - > set_sample_rate ( ExportFormatBase : : SR_Session ) ;
fmp - > set_format_id ( ExportFormatBase : : F_None ) ;
fmp - > set_type ( ExportFormatBase : : T_None ) ;
fmp - > set_extension ( " wav " ) ;
fmp - > set_analyse ( true ) ;
/* setup range */
2020-09-29 19:53:43 -04:00
tsp - > set_range ( _range . start ( ) . samples ( ) , _range . end ( ) . samples ( ) ) ;
2020-07-19 18:29:56 -04:00
tsp - > set_range_id ( " selection " ) ;
2020-07-20 22:45:46 -04:00
tsp - > set_realtime ( _rt_analysis_button . get_active ( ) ) ;
tsp - > set_name ( " master " ) ;
2020-07-19 18:29:56 -04:00
/* setup channels, use master out */
2021-04-11 19:32:00 -04:00
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 ( ) ;
2020-07-19 18:29:56 -04:00
channel - > add_port ( master_out - > audio ( n ) ) ;
ExportChannelPtr chan_ptr ( channel ) ;
ccp - > register_channel ( chan_ptr ) ;
}
/* do audio export */
2023-02-16 18:33:28 -05:00
std : : shared_ptr < AudioGrapher : : BroadcastInfo > b ;
2021-04-11 19:32:00 -04:00
_session - > get_export_handler ( ) - > reset ( ) ;
_session - > get_export_handler ( ) - > add_export_config ( tsp , ccp , fmp , fnp , b ) ;
_session - > get_export_handler ( ) - > do_export ( ) ;
2020-07-19 18:29:56 -04:00
/* show progress */
2020-07-20 22:45:46 -04:00
_setup_box . hide ( ) ;
_progress_box . show_all ( ) ;
/* shrink window height (setup box) */
Gtk : : Requisition wr ;
get_size ( wr . width , wr . height ) ;
resize ( wr . width , 60 ) ;
2021-04-11 19:32:00 -04:00
sigc : : connection progress_connection = Glib : : signal_timeout ( ) . connect ( sigc : : mem_fun ( * this , & LoudnessDialog : : progress_timeout ) , 100 ) ;
2020-07-19 18:29:56 -04:00
while ( _status - > running ( ) ) {
2021-04-11 19:32:00 -04:00
if ( gtk_events_pending ( ) ) {
2020-07-19 18:29:56 -04:00
gtk_main_iteration ( ) ;
} else {
Glib : : usleep ( 10000 ) ;
}
}
2021-04-11 19:32:00 -04:00
progress_connection . disconnect ( ) ;
2020-07-19 18:29:56 -04:00
_progress_box . hide_all ( ) ;
/* done */
2021-04-11 19:32:00 -04:00
_status - > finish ( TRS_UI ) ;
2020-10-04 10:37:29 -04:00
2021-04-11 19:32:00 -04:00
if ( ! _status - > aborted ( ) & & _status - > result_map . size ( ) ! = 1 ) {
2020-10-04 10:37:29 -04:00
ArdourMessageDialog ( _ ( " Loudness measurement returned no results. Likely because the analyzed range is to short. " ) , false , MESSAGE_ERROR ) . run ( ) ;
return 1 ;
}
2021-04-11 19:32:00 -04:00
return _status - > aborted ( ) ? 1 : 0 ;
2020-07-19 18:29:56 -04:00
}
void
LoudnessDialog : : display_report ( )
{
2020-11-08 10:19:46 -05:00
ExportReport er ( _ ( " Export Loudness Report " ) , _status - > result_map ) ;
2020-07-21 18:00:29 -04:00
er . set_transient_for ( * this ) ;
2021-04-11 19:32:00 -04:00
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 < bool > 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 ( ) ;
}
2020-07-19 18:29:56 -04:00
}
2020-07-22 20:58:59 -04:00
void
LoudnessDialog : : load_preset ( size_t n )
{
2020-08-04 17:36:29 -04:00
if ( _ignore_preset ) {
return ;
}
2021-04-11 19:32:00 -04:00
_preset = _lp [ n ] ;
_save_preset . set_sensitive ( false ) ;
_remove_preset . set_sensitive ( _preset . user ) ;
2020-07-22 20:58:59 -04:00
apply_preset ( ) ;
calculate_gain ( ) ;
}
void
LoudnessDialog : : apply_preset ( )
{
PBD : : Unwinder < bool > uw ( _ignore_change , true ) ;
2021-04-11 19:32:00 -04:00
_preset_dropdown . set_text ( _preset . label ) ;
2020-07-22 20:58:59 -04:00
_dbfs_btn . set_active ( _preset . enable [ 0 ] ) ;
_dbtp_btn . set_active ( _preset . enable [ 1 ] ) ;
_lufs_i_btn . set_active ( _preset . enable [ 2 ] ) ;
_lufs_s_btn . set_active ( _preset . enable [ 3 ] ) ;
_lufs_m_btn . set_active ( _preset . enable [ 4 ] ) ;
_dbfs_spinbutton . set_value ( _preset . level [ 0 ] ) ;
_dbtp_spinbutton . set_value ( _preset . level [ 1 ] ) ;
_lufs_i_spinbutton . set_value ( _preset . level [ 2 ] ) ;
_lufs_s_spinbutton . set_value ( _preset . level [ 3 ] ) ;
_lufs_m_spinbutton . set_value ( _preset . level [ 4 ] ) ;
2020-07-23 09:59:17 -04:00
update_sensitivity ( ) ;
}
void
LoudnessDialog : : update_sensitivity ( )
{
2022-01-26 16:02:41 -05:00
_dbfs_spinbutton . set_sensitive ( _dbfs_btn . get_active ( ) & & _dbfs_btn . is_sensitive ( ) ) ;
_dbtp_spinbutton . set_sensitive ( _dbtp_btn . get_active ( ) & & _dbtp_btn . is_sensitive ( ) ) ;
_lufs_i_spinbutton . set_sensitive ( _lufs_i_btn . get_active ( ) & & _dbtp_btn . is_sensitive ( ) ) ;
_lufs_s_spinbutton . set_sensitive ( _lufs_s_btn . get_active ( ) & & _lufs_s_btn . is_sensitive ( ) ) ;
_lufs_m_spinbutton . set_sensitive ( _lufs_m_btn . get_active ( ) & & _lufs_m_btn . is_sensitive ( ) ) ;
2020-07-22 20:58:59 -04:00
}
2021-04-11 19:32:00 -04:00
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 ) ;
}
2020-07-22 20:58:59 -04:00
void
LoudnessDialog : : update_settings ( )
{
if ( _ignore_change ) {
return ;
}
2021-04-11 19:32:00 -04:00
/* 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 ( ) ;
2020-07-23 09:59:17 -04:00
update_sensitivity ( ) ;
2020-07-22 20:58:59 -04:00
calculate_gain ( ) ;
}
2020-07-26 03:06:15 -04:00
float
LoudnessDialog : : gain_db ( ) const
{
2020-07-27 16:00:08 -04:00
return _gain_norm + _gain_out ;
2020-07-26 03:06:15 -04:00
}
2020-07-19 18:29:56 -04:00
void
LoudnessDialog : : display_results ( )
{
AnalysisResults const & ar ( _status - > result_map ) ;
assert ( ar . size ( ) = = 1 ) ;
2021-04-11 19:32:00 -04:00
ExportAnalysisPtr p = ar . begin ( ) - > second ;
2020-07-19 18:29:56 -04:00
2021-04-11 19:32:00 -04:00
if ( ! p - > have_loudness | | ! p - > have_dbtp | | ! p - > have_lufs_graph ) {
2020-10-17 12:28:10 -04:00
ArdourMessageDialog (
2021-04-11 19:32:00 -04:00
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 ( ) ;
2020-10-04 10:37:29 -04:00
}
2021-04-11 19:32:00 -04:00
plot_graph ( p ) ;
2020-07-20 22:45:46 -04:00
_dbfs = accurate_coefficient_to_dB ( p - > peak ) ;
_dbtp = accurate_coefficient_to_dB ( p - > truepeak ) ;
2021-04-11 19:32:00 -04:00
_lufs_i = p - > integrated_loudness > - 200 ? p - > integrated_loudness : - std : : numeric_limits < float > : : infinity ( ) ;
_lufs_s = p - > max_loudness_short > - 200 ? p - > max_loudness_short : - std : : numeric_limits < float > : : infinity ( ) ;
_lufs_m = p - > max_loudness_momentary > - 200 ? p - > max_loudness_momentary : - std : : numeric_limits < float > : : infinity ( ) ;
2020-07-26 03:06:15 -04:00
_dbfs_btn . set_sensitive ( _dbfs > - 300 ) ;
_dbtp_btn . set_sensitive ( _dbtp > - 300 ) ;
_lufs_i_btn . set_sensitive ( p - > integrated_loudness > - 200 ) ;
_lufs_s_btn . set_sensitive ( p - > max_loudness_short > - 200 ) ;
_lufs_m_btn . set_sensitive ( p - > max_loudness_momentary > - 200 ) ;
2020-07-19 18:29:56 -04:00
_dbfs_label . set_text ( string_compose ( _ ( " %1 dBFS " ) , std : : setprecision ( 1 ) , std : : fixed , _dbfs ) ) ;
_dbtp_label . set_text ( string_compose ( _ ( " %1 dBTP " ) , std : : setprecision ( 1 ) , std : : fixed , _dbtp ) ) ;
2020-07-20 22:45:46 -04:00
_lufs_i_label . set_text ( string_compose ( _ ( " %1 LUFS " ) , std : : setprecision ( 1 ) , std : : fixed , _lufs_i ) ) ;
_lufs_s_label . set_text ( string_compose ( _ ( " %1 LUFS " ) , std : : setprecision ( 1 ) , std : : fixed , _lufs_s ) ) ;
_lufs_m_label . set_text ( string_compose ( _ ( " %1 LUFS " ) , std : : setprecision ( 1 ) , std : : fixed , _lufs_m ) ) ;
2020-07-19 18:29:56 -04:00
2020-07-26 03:06:15 -04:00
update_sensitivity ( ) ;
2020-07-19 18:29:56 -04:00
calculate_gain ( ) ;
_result_box . show_all ( ) ;
2020-07-20 22:45:46 -04:00
_show_report_button . set_sensitive ( true ) ;
2020-07-19 18:29:56 -04:00
}
void
LoudnessDialog : : calculate_gain ( )
{
2021-04-11 19:32:00 -04:00
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 ;
# define MIN_IF_SET(A, B) \
{ \
if ( set ) { \
gain = std : : min ( gain , ( A ) - ( B ) ) ; \
} else { \
gain = ( A ) - ( B ) ; \
} \
set = true ; \
}
2020-07-20 22:45:46 -04:00
2022-01-26 16:02:41 -05:00
if ( _dbfs_btn . get_active ( ) & & _dbfs_btn . is_sensitive ( ) ) {
2020-07-21 21:26:19 -04:00
MIN_IF_SET ( dbfs , _dbfs ) ;
}
2022-01-26 16:02:41 -05:00
if ( _dbtp_btn . get_active ( ) & & _dbtp_btn . is_sensitive ( ) ) {
2020-07-21 21:26:19 -04:00
MIN_IF_SET ( dbtp , _dbtp ) ;
}
2022-01-26 16:02:41 -05:00
if ( _lufs_i_btn . get_active ( ) & & _lufs_i_btn . is_sensitive ( ) ) {
2020-07-21 21:26:19 -04:00
MIN_IF_SET ( lufs_i , _lufs_i ) ;
}
2022-01-26 16:02:41 -05:00
if ( _lufs_s_btn . get_active ( ) & & _lufs_s_btn . is_sensitive ( ) ) {
2020-07-21 21:26:19 -04:00
MIN_IF_SET ( lufs_s , _lufs_s ) ;
}
2022-01-26 16:02:41 -05:00
if ( _lufs_m_btn . get_active ( ) & & _lufs_m_btn . is_sensitive ( ) ) {
2020-07-21 21:26:19 -04:00
MIN_IF_SET ( lufs_m , _lufs_m ) ;
}
2020-07-19 18:29:56 -04:00
2020-07-21 21:26:19 -04:00
_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 ( ) ) ;
2021-04-11 19:32:00 -04:00
_gain_norm = gain ;
2020-07-27 14:00:17 -04:00
bool in_range = gain_db ( ) > = - 40 & & gain_db ( ) < = 40 ;
2020-07-26 03:06:15 -04:00
2020-07-21 21:26:19 -04:00
_gain_norm_label . set_text ( string_compose ( _ ( " %1 dB " ) , std : : setprecision ( 2 ) , std : : showpos , std : : fixed , _gain_norm ) ) ;
2020-07-26 03:06:15 -04:00
if ( ! in_range ) {
2020-07-27 14:00:17 -04:00
_gain_exceeds_label . set_text ( _ ( " exceeds " ) ) ;
2023-01-16 15:41:22 -05:00
_gain_total_label . set_markup ( _ ( u8 " <b> \u00B1 40 dB</b> " ) ) ;
2020-07-26 03:06:15 -04:00
} else {
2020-07-27 14:00:17 -04:00
_gain_exceeds_label . set_text ( X_ ( " " ) ) ;
2021-04-11 19:32:00 -04:00
_gain_total_label . set_markup ( string_compose ( _ ( " <b>%1 dB</b> " ) , std : : setw ( 7 ) , std : : setprecision ( 2 ) , std : : showpos , std : : fixed , gain_db ( ) ) ) ;
2020-07-26 03:06:15 -04:00
}
2020-07-27 14:00:17 -04:00
test_conformity ( ) ;
2020-07-26 03:06:15 -04:00
_ok_button - > set_sensitive ( in_range ) ;
2020-07-19 18:29:56 -04:00
}
2020-07-27 14:00:17 -04:00
void
LoudnessDialog : : test_conformity ( )
{
2021-04-11 19:32:00 -04:00
if ( _conformity_frame . get_child ( ) ) {
_conformity_frame . remove ( ) ;
2020-07-27 14:00:17 -04:00
}
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 ;
2021-04-11 19:32:00 -04:00
Table * t = manage ( new Table ( ) ) ;
size_t n_pset = _lp . n_presets ( ) ;
2020-07-27 14:00:17 -04:00
size_t n_rows = ceil ( n_pset / 3.0 ) ;
size_t row = 0 ;
size_t col = 0 ;
2021-04-11 19:32:00 -04:00
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
2020-07-27 14:00:17 -04:00
2022-08-10 23:11:52 -04:00
Gdk : : Color color_good = Gtkmm2ext : : gdk_color_from_rgba ( c_good ) ;
Gdk : : Color color_warn = Gtkmm2ext : : gdk_color_from_rgba ( c_warn ) ;
Gdk : : Color color_fail = Gtkmm2ext : : gdk_color_from_rgba ( c_fail ) ;
2020-07-27 14:00:17 -04:00
2020-08-04 17:36:29 -04:00
for ( size_t i = 1 ; i < n_pset ; + + i ) {
2021-04-11 19:32:00 -04:00
CLoudnessPreset const & preset = _lp [ i ] ;
2022-01-26 16:19:32 -05:00
Label * l = manage ( new Label ( preset . label + " : " , ALIGN_START ) ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * l , col , col + 1 , row , row + 1 , EXPAND | FILL , SHRINK , 2 , 0 ) ;
2020-07-27 14:00:17 -04:00
2021-04-11 19:32:00 -04:00
if ( lufs_i > preset . LUFS_range [ 0 ]
| | ( preset . enable [ 0 ] & & dbfs > preset . level [ 0 ] )
| | ( preset . enable [ 1 ] & & dbtp > preset . level [ 1 ] )
2020-07-27 14:00:17 -04:00
) {
2023-01-16 15:41:22 -05:00
l = manage ( new Label ( u8 " \u274C " , ALIGN_CENTER ) ) ; // cross mark
2022-11-07 05:56:21 -05:00
l - > modify_font ( UIConfiguration : : instance ( ) . get_ArdourBigFont ( ) ) ;
2020-07-27 14:00:17 -04:00
l - > modify_fg ( Gtk : : STATE_NORMAL , color_fail ) ;
set_tooltip ( * l , " The signal is too loud. " ) ;
2021-04-11 19:32:00 -04:00
} else if ( lufs_i < preset . LUFS_range [ 1 ] ) {
2023-01-16 15:41:22 -05:00
l = manage ( new Label ( u8 " \U0001F509 " , ALIGN_CENTER ) ) ; // speaker icon w/1 bar
2022-11-07 05:56:21 -05:00
l - > modify_font ( UIConfiguration : : instance ( ) . get_ArdourBigFont ( ) ) ;
2020-07-27 14:00:17 -04:00
l - > modify_fg ( Gtk : : STATE_NORMAL , color_warn ) ;
set_tooltip ( * l , " The signal is too quiet, but satisfies the max. loudness spec. " ) ;
} else {
2023-01-16 15:41:22 -05:00
l = manage ( new Label ( u8 " \u2714 " , ALIGN_CENTER ) ) ; // heavy check mark
2022-11-07 05:56:21 -05:00
l - > modify_font ( UIConfiguration : : instance ( ) . get_ArdourBigFont ( ) ) ;
2020-07-27 14:00:17 -04:00
l - > modify_fg ( Gtk : : STATE_NORMAL , color_good ) ;
set_tooltip ( * l , " Signal loudness is within the spec. " ) ;
2023-01-16 15:41:22 -05:00
Gtkmm2ext : : set_size_request_to_display_given_text ( * l , u8 " \u274C \u2713 " , 0 , 0 ) ;
2020-07-27 14:00:17 -04:00
}
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 ) ) ;
2021-04-11 19:32:00 -04:00
t - > attach ( * spc , col + 2 , col + 3 , 0 , n_rows , FILL , EXPAND | FILL , 8 , 0 ) ;
2020-07-27 14:00:17 -04:00
row = 0 ;
col + = 3 ;
}
}
2021-04-11 19:32:00 -04:00
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 < Cairo : : Context > 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 ( ) ;
2020-07-27 14:00:17 -04:00
}