From b413837ae91f4db1c2936f092b4327bbc0418f42 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 19 Apr 2021 23:13:29 +0200 Subject: [PATCH] Analyse audio (if required) when making hints (#1924). Otherwise if you haven't run a whole-project audio analysis you don't get the hints about audio levels being too high. --- src/lib/hints.cc | 89 +++++++++++++++++++++++++++++++----------------- src/lib/hints.h | 6 +++- 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/src/lib/hints.cc b/src/lib/hints.cc index cfd8a29dd..e767c07fe 100644 --- a/src/lib/hints.cc +++ b/src/lib/hints.cc @@ -73,9 +73,10 @@ using namespace boost::placeholders; */ -Hints::Hints (weak_ptr film) - : WeakConstFilm (film) - , _writer (new Writer(film, weak_ptr(), true)) +Hints::Hints (weak_ptr weak_film) + : WeakConstFilm (weak_film) + , _writer (new Writer(weak_film, weak_ptr(), true)) + , _analyser (film(), film()->playlist(), true, [](float) {}) , _stop (false) { @@ -302,42 +303,46 @@ Hints::check_3d_in_2d () } -void +/** @return true if the loudness could be checked, false if it could not because no analysis was available */ +bool Hints::check_loudness () { auto path = film()->audio_analysis_path(film()->playlist()); - if (boost::filesystem::exists (path)) { - try { - auto an = make_shared(path); + if (!boost::filesystem::exists(path)) { + return false; + } - string ch; + try { + auto an = make_shared(path); - auto sample_peak = an->sample_peak (); - auto true_peak = an->true_peak (); + string ch; - for (size_t i = 0; i < sample_peak.size(); ++i) { - float const peak = max (sample_peak[i].peak, true_peak.empty() ? 0 : true_peak[i]); - float const peak_dB = linear_to_db(peak) + an->gain_correction(film()->playlist()); - if (peak_dB > -3) { - ch += dcp::raw_convert (short_audio_channel_name (i)) + ", "; - } + auto sample_peak = an->sample_peak (); + auto true_peak = an->true_peak (); + + for (size_t i = 0; i < sample_peak.size(); ++i) { + float const peak = max (sample_peak[i].peak, true_peak.empty() ? 0 : true_peak[i]); + float const peak_dB = linear_to_db(peak) + an->gain_correction(film()->playlist()); + if (peak_dB > -3) { + ch += dcp::raw_convert(short_audio_channel_name(i)) + ", "; } + } - ch = ch.substr (0, ch.length() - 2); + ch = ch.substr (0, ch.length() - 2); - if (!ch.empty ()) { - hint (String::compose ( - _("Your audio level is very high (on %1). You should reduce the gain of your audio content."), - ch - ) - ); - } - } catch (OldFormatError& e) { - /* The audio analysis is too old to load in; just skip this hint as if - it had never been run. - */ + if (!ch.empty ()) { + hint (String::compose ( + _("Your audio level is very high (on %1). You should reduce the gain of your audio content."), + ch + ) + ); } + } catch (OldFormatError& e) { + /* The audio analysis is too old to load in */ + return false; } + + return true; } @@ -383,16 +388,24 @@ Hints::thread () check_speed_up (); check_vob (); check_3d_in_2d (); - check_loudness (); + auto const check_loudness_done = check_loudness (); check_ffec_and_ffmc_in_smpte_feature (); check_out_of_range_markers (); check_text_languages (); - emit (bind(boost::ref(Progress), _("Examining subtitles and closed captions"))); + if (check_loudness_done) { + emit (bind(boost::ref(Progress), _("Examining subtitles and closed captions"))); + } else { + emit (bind(boost::ref(Progress), _("Examining audio, subtitles and closed captions"))); + } auto player = make_shared(film); player->set_ignore_video (); - player->set_ignore_audio (); + if (check_loudness_done) { + /* We don't need to analyse audio because we already loaded a suitable analysis */ + player->set_ignore_audio (); + } + player->Audio.connect (bind(&Hints::audio, this, _1, _2)); player->Text.connect (bind(&Hints::text, this, _1, _2, _3, _4)); struct timeval last_pulse; @@ -415,6 +428,12 @@ Hints::thread () store_current (); } + if (!check_loudness_done) { + _analyser.finish (); + _analyser.get().write(film->audio_analysis_path(film->playlist())); + check_loudness (); + } + _writer->write (player->get_subtitle_fonts()); if (_long_subtitle && !_very_long_subtitle) { @@ -477,6 +496,14 @@ Hints::hint (string h) emit(bind(boost::ref(Hint), h)); } + +void +Hints::audio (shared_ptr audio, DCPTime time) +{ + _analyser.analyse (audio, time); +} + + void Hints::text (PlayerText text, TextType type, optional track, DCPTimePeriod period) { diff --git a/src/lib/hints.h b/src/lib/hints.h index c692f6fca..06155f434 100644 --- a/src/lib/hints.h +++ b/src/lib/hints.h @@ -18,6 +18,7 @@ */ +#include "audio_analyser.h" #include "signaller.h" #include "player_text.h" #include "types.h" @@ -55,6 +56,7 @@ private: void thread (); void hint (std::string h); + void audio (std::shared_ptr audio, dcpomatic::DCPTime time); void text (PlayerText text, TextType type, boost::optional track, dcpomatic::DCPTimePeriod period); void closed_caption (PlayerText text, dcpomatic::DCPTimePeriod period); void open_subtitle (PlayerText text, dcpomatic::DCPTimePeriod period); @@ -71,7 +73,7 @@ private: void check_speed_up (); void check_vob (); void check_3d_in_2d (); - void check_loudness (); + bool check_loudness (); void check_ffec_and_ffmc_in_smpte_feature (); void check_out_of_range_markers (); void check_text_languages (); @@ -83,6 +85,8 @@ private: */ std::shared_ptr _writer; + AudioAnalyser _analyser; + bool _long_ccap = false; bool _overlap_ccap = false; bool _too_many_ccap_lines = false; -- 2.30.2