From e6c828cbd577239e7c8e4c532161084a33843a0f Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 2 Jul 2019 01:32:54 +0100 Subject: [PATCH] Add support for Datasat AP2x and USL sound processors when converting fader position to gain. Stop storing a chosen processor in config; instead, get the user to choose the processor when calculating gains. --- src/lib/cinema_sound_processor.cc | 39 +++++++++++++- src/lib/cinema_sound_processor.h | 7 ++- src/lib/config.cc | 20 +------ src/lib/config.h | 7 --- src/lib/datasat_ap2x.cc | 29 ++++++++++ src/lib/datasat_ap2x.h | 31 +++++++++++ src/lib/dolby_cp750.cc | 32 +---------- src/lib/dolby_cp750.h | 2 - src/lib/usl.cc | 29 ++++++++++ src/lib/usl.h | 31 +++++++++++ src/lib/wscript | 2 + src/wx/audio_panel.cc | 10 ++-- src/wx/gain_calculator_dialog.cc | 36 +++++++------ src/wx/gain_calculator_dialog.h | 7 +-- test/cinema_sound_processor_test.cc | 84 +++++++++++++++++++++++++++++ test/wscript | 1 + 16 files changed, 280 insertions(+), 87 deletions(-) create mode 100644 src/lib/datasat_ap2x.cc create mode 100644 src/lib/datasat_ap2x.h create mode 100644 src/lib/usl.cc create mode 100644 src/lib/usl.h create mode 100644 test/cinema_sound_processor_test.cc diff --git a/src/lib/cinema_sound_processor.cc b/src/lib/cinema_sound_processor.cc index 0b00ee2ee..1a3ba5a0f 100644 --- a/src/lib/cinema_sound_processor.cc +++ b/src/lib/cinema_sound_processor.cc @@ -24,6 +24,8 @@ #include "cinema_sound_processor.h" #include "dolby_cp750.h" +#include "usl.h" +#include "datasat_ap2x.h" #include "dcpomatic_assert.h" #include #include @@ -35,9 +37,12 @@ vector CinemaSoundProcessor::_cinema_sound_process /** @param i Our id. * @param n User-visible name. */ -CinemaSoundProcessor::CinemaSoundProcessor (string i, string n) +CinemaSoundProcessor::CinemaSoundProcessor (string i, string n, float knee, float below, float above) : _id (i) , _name (n) + , _knee (knee) + , _below (below) + , _above (above) { } @@ -56,6 +61,8 @@ void CinemaSoundProcessor::setup_cinema_sound_processors () { _cinema_sound_processors.push_back (new DolbyCP750); + _cinema_sound_processors.push_back (new USL); + _cinema_sound_processors.push_back (new DatasatAP2x); } /** @param id One of our ids. @@ -103,3 +110,33 @@ CinemaSoundProcessor::from_index (int i) DCPOMATIC_ASSERT (i <= int(_cinema_sound_processors.size ())); return _cinema_sound_processors[i]; } + +float +CinemaSoundProcessor::db_for_fader_change (float from, float to) const +{ + float db = 0; + + if (from < to) { + if (from <= _knee) { + float const t = min (to, _knee); + db += (t - from) * _below; + } + + if (to > 4) { + float const t = max (from, _knee); + db += (to - t) * _above; + } + } else { + if (from >= _knee) { + float const t = max (to, _knee); + db -= (from - t) * _above; + } + + if (to < _knee) { + float const t = min (from, _knee); + db -= (t - to) * _below; + } + } + + return db; +} diff --git a/src/lib/cinema_sound_processor.h b/src/lib/cinema_sound_processor.h index c19c6ca22..25c576003 100644 --- a/src/lib/cinema_sound_processor.h +++ b/src/lib/cinema_sound_processor.h @@ -38,10 +38,10 @@ class CinemaSoundProcessor : public boost::noncopyable { public: - CinemaSoundProcessor (std::string i, std::string n); + CinemaSoundProcessor (std::string i, std::string n, float knee, float below, float above); virtual ~CinemaSoundProcessor () {} - virtual float db_for_fader_change (float from, float to) const = 0; + float db_for_fader_change (float from, float to) const; /** @return id for our use */ std::string id () const { @@ -64,6 +64,9 @@ private: std::string _id; /** user-visible name for this sound processor */ std::string _name; + float _knee; + float _below; + float _above; /** sll available cinema sound processors */ static std::vector _cinema_sound_processors; diff --git a/src/lib/config.cc b/src/lib/config.cc index fdd051662..a7a457081 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -24,7 +24,6 @@ #include "types.h" #include "log.h" #include "dcp_content_type.h" -#include "cinema_sound_processor.h" #include "colour_conversion.h" #include "cinema.h" #include "util.h" @@ -93,7 +92,6 @@ Config::set_defaults () _tms_path = "."; _tms_user = ""; _tms_password = ""; - _cinema_sound_processor = CinemaSoundProcessor::from_id (N_("dolby_cp750")); _allow_any_dcp_frame_rate = false; _allow_any_container = false; _language = optional (); @@ -293,19 +291,9 @@ try _tms_user = f.string_child ("TMSUser"); _tms_password = f.string_child ("TMSPassword"); - optional c; - c = f.optional_string_child ("SoundProcessor"); - if (c) { - _cinema_sound_processor = CinemaSoundProcessor::from_id (c.get ()); - } - c = f.optional_string_child ("CinemaSoundProcessor"); - if (c) { - _cinema_sound_processor = CinemaSoundProcessor::from_id (c.get ()); - } - _language = f.optional_string_child ("Language"); - c = f.optional_string_child ("DefaultContainer"); + optional c = f.optional_string_child ("DefaultContainer"); if (c) { _default_container = Ratio::from_id (c.get ()); } @@ -698,12 +686,6 @@ Config::write_config () const root->add_child("TMSUser")->add_child_text (_tms_user); /* [XML] TMSPassword Password to log into the TMS with. */ root->add_child("TMSPassword")->add_child_text (_tms_password); - if (_cinema_sound_processor) { - /* [XML:opt] CinemaSoundProcessor Identifier of the type of cinema sound processor to use when calculating - gain changes from fader positions. Currently can only be dolby_cp750. - */ - root->add_child("CinemaSoundProcessor")->add_child_text (_cinema_sound_processor->id ()); - } if (_language) { /* [XML:opt] Language Language to use in the GUI e.g. fr_FR. */ root->add_child("Language")->add_child_text (_language.get()); diff --git a/src/lib/config.h b/src/lib/config.h index 29511b1fe..9a57b1b48 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -141,11 +141,6 @@ public: return _tms_password; } - /** @return The cinema sound processor that we are using */ - CinemaSoundProcessor const * cinema_sound_processor () const { - return _cinema_sound_processor; - } - std::list > cinemas () const { return _cinemas; } @@ -1173,8 +1168,6 @@ private: std::string _tms_user; /** Password to log into the TMS with */ std::string _tms_password; - /** Our cinema sound processor */ - CinemaSoundProcessor const * _cinema_sound_processor; /** The list of possible DCP frame rates that DCP-o-matic will use */ std::list _allowed_dcp_frame_rates; /** Allow any video frame rate for the DCP; if true, overrides _allowed_dcp_frame_rates */ diff --git a/src/lib/datasat_ap2x.cc b/src/lib/datasat_ap2x.cc new file mode 100644 index 000000000..ade750ce1 --- /dev/null +++ b/src/lib/datasat_ap2x.cc @@ -0,0 +1,29 @@ +/* + Copyright (C) 2019 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic 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. + + DCP-o-matic 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 DCP-o-matic. If not, see . + +*/ + +#include "datasat_ap2x.h" + +#include "i18n.h" + +DatasatAP2x::DatasatAP2x () + : CinemaSoundProcessor ("dataset_ap2x", _("Datasat AP20 or AP25"), 3.2f, 20, 5) +{ + +} diff --git a/src/lib/datasat_ap2x.h b/src/lib/datasat_ap2x.h new file mode 100644 index 000000000..4bbe39521 --- /dev/null +++ b/src/lib/datasat_ap2x.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2019 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic 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. + + DCP-o-matic 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 DCP-o-matic. If not, see . + +*/ + +/** @file src/lib/datasat_ap2x.h + * @brief DatasatAP2x class. + */ + +#include "cinema_sound_processor.h" + +class DatasatAP2x : public CinemaSoundProcessor +{ +public: + DatasatAP2x (); +}; diff --git a/src/lib/dolby_cp750.cc b/src/lib/dolby_cp750.cc index 3e2bb4346..380ab0564 100644 --- a/src/lib/dolby_cp750.cc +++ b/src/lib/dolby_cp750.cc @@ -25,37 +25,7 @@ using namespace std; DolbyCP750::DolbyCP750 () - : CinemaSoundProcessor ("dolby_cp750", _("Dolby CP650 and CP750")) + : CinemaSoundProcessor ("dolby_cp750", _("Dolby CP650 or CP750"), 4.0f, 20, 3.33333333333333333) { } - -float -DolbyCP750::db_for_fader_change (float from, float to) const -{ - float db = 0; - - if (from < to) { - if (from <= 4) { - float const t = min (to, 4.0f); - db += (t - from) * 20; - } - - if (to > 4) { - float const t = max (from, 4.0f); - db += (to - t) * 3.33333333333333333; - } - } else { - if (from >= 4) { - float const t = max (to, 4.0f); - db -= (from - t) * 3.33333333333333333; - } - - if (to < 4) { - float const t = min (from, 4.0f); - db -= (t - to) * 20; - } - } - - return db; -} diff --git a/src/lib/dolby_cp750.h b/src/lib/dolby_cp750.h index 3a8fcf6c7..3162a962d 100644 --- a/src/lib/dolby_cp750.h +++ b/src/lib/dolby_cp750.h @@ -28,6 +28,4 @@ class DolbyCP750 : public CinemaSoundProcessor { public: DolbyCP750 (); - - float db_for_fader_change (float from, float to) const; }; diff --git a/src/lib/usl.cc b/src/lib/usl.cc new file mode 100644 index 000000000..b8a9a71f0 --- /dev/null +++ b/src/lib/usl.cc @@ -0,0 +1,29 @@ +/* + Copyright (C) 2019 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic 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. + + DCP-o-matic 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 DCP-o-matic. If not, see . + +*/ + +#include "usl.h" + +#include "i18n.h" + +USL::USL () + : CinemaSoundProcessor ("usl", _("USL"), 5.5f, 10, 3.33333333333333333) +{ + +} diff --git a/src/lib/usl.h b/src/lib/usl.h new file mode 100644 index 000000000..260eb3c80 --- /dev/null +++ b/src/lib/usl.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2019 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic 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. + + DCP-o-matic 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 DCP-o-matic. If not, see . + +*/ + +/** @file src/lib/usl.h + * @brief USL class. + */ + +#include "cinema_sound_processor.h" + +class USL : public CinemaSoundProcessor +{ +public: + USL (); +}; diff --git a/src/lib/wscript b/src/lib/wscript index c5a270f65..177a58b64 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -56,6 +56,7 @@ sources = """ cross.cc crypto.cc curl_uploader.cc + datasat_ap2x.cc dcp.cc dcp_content.cc dcp_content_type.cc @@ -164,6 +165,7 @@ sources = """ uploader.cc upmixer_a.cc upmixer_b.cc + usl.cc util.cc verify_dcp_job.cc video_content.cc diff --git a/src/wx/audio_panel.cc b/src/wx/audio_panel.cc index ccdb57907..0cb062efd 100644 --- a/src/wx/audio_panel.cc +++ b/src/wx/audio_panel.cc @@ -251,18 +251,14 @@ AudioPanel::gain_calculate_button_clicked () { GainCalculatorDialog* d = new GainCalculatorDialog (this); int const r = d->ShowModal (); + optional c = d->db_change(); - if (r == wxID_CANCEL || d->wanted_fader() == 0 || d->actual_fader() == 0) { + if (r == wxID_CANCEL || !c) { d->Destroy (); return; } - _gain->wrapped()->SetValue ( - Config::instance()->cinema_sound_processor()->db_for_fader_change ( - d->wanted_fader (), - d->actual_fader () - ) - ); + _gain->wrapped()->SetValue (*c); /* This appears to be necessary, as the change is not signalled, I think. diff --git a/src/wx/gain_calculator_dialog.cc b/src/wx/gain_calculator_dialog.cc index 8818aee9e..701856610 100644 --- a/src/wx/gain_calculator_dialog.cc +++ b/src/wx/gain_calculator_dialog.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington + Copyright (C) 2012-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -21,35 +21,41 @@ #include "gain_calculator_dialog.h" #include "wx_util.h" #include "lib/util.h" +#include "lib/cinema_sound_processor.h" + +using boost::optional; GainCalculatorDialog::GainCalculatorDialog (wxWindow* parent) : TableDialog (parent, _("Gain Calculator"), 2, 1, true) { + add (_("Sound processor"), true); + _processor = add (new wxChoice(this, wxID_ANY)); + add (_("I want to play this back at fader"), true); _wanted = add (new wxTextCtrl (this, wxID_ANY, wxT (""), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator (wxFILTER_NUMERIC))); add (_("But I have to use fader"), true); _actual = add (new wxTextCtrl (this, wxID_ANY, wxT (""), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator (wxFILTER_NUMERIC))); - layout (); -} - -float -GainCalculatorDialog::wanted_fader () const -{ - if (_wanted->GetValue().IsEmpty()) { - return 0; + BOOST_FOREACH (CinemaSoundProcessor const * i, CinemaSoundProcessor::all()) { + _processor->Append (std_to_wx(i->name())); } - return relaxed_string_to_float (wx_to_std (_wanted->GetValue ())); + _processor->SetSelection (0); + + layout (); } -float -GainCalculatorDialog::actual_fader () const +optional +GainCalculatorDialog::db_change () const { - if (_actual->GetValue().IsEmpty()) { - return 0; + if (_wanted->GetValue().IsEmpty() || _actual->GetValue().IsEmpty()) { + return optional(); } - return relaxed_string_to_float (wx_to_std (_actual->GetValue ())); + return CinemaSoundProcessor::from_index( + _processor->GetSelection())->db_for_fader_change( + relaxed_string_to_float(wx_to_std(_wanted->GetValue())), + relaxed_string_to_float(wx_to_std(_actual->GetValue())) + ); } diff --git a/src/wx/gain_calculator_dialog.h b/src/wx/gain_calculator_dialog.h index e1ed026b8..addc07288 100644 --- a/src/wx/gain_calculator_dialog.h +++ b/src/wx/gain_calculator_dialog.h @@ -18,18 +18,19 @@ */ -#include #include "table_dialog.h" +#include +#include class GainCalculatorDialog : public TableDialog { public: explicit GainCalculatorDialog (wxWindow* parent); - float actual_fader () const; - float wanted_fader () const; + boost::optional db_change () const; private: + wxChoice* _processor; wxTextCtrl* _wanted; wxTextCtrl* _actual; }; diff --git a/test/cinema_sound_processor_test.cc b/test/cinema_sound_processor_test.cc new file mode 100644 index 000000000..b17fd19f9 --- /dev/null +++ b/test/cinema_sound_processor_test.cc @@ -0,0 +1,84 @@ +/* + Copyright (C) 2019 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic 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. + + DCP-o-matic 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 DCP-o-matic. If not, see . + +*/ + +#include "lib/dolby_cp750.h" +#include "lib/usl.h" +#include "lib/datasat_ap2x.h" +#include + +BOOST_AUTO_TEST_CASE (dolby_cp750_test) +{ + DolbyCP750 ap; + + /* No change */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(7, 7), 0, 0.1); + /* Within 0->4 range, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(1, 3), 40, 0.1); + /* Within 0->4 range, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(3, 1), -40, 0.1); + /* Within 4->10 range, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(5, 8), 10, 0.1); + /* Within 4->10 range, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(8, 5), -10, 0.1); + /* Crossing knee, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(3, 6), 20 + 6.66666666666666666, 0.1); + /* Crossing knee, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(6, 3), -(20 + 6.66666666666666666), 0.1); +} + +BOOST_AUTO_TEST_CASE (usl_test) +{ + USL ap; + + /* No change */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(7, 7), 0, 0.1); + /* Within 0->5.5 range, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(1, 3), 20, 0.1); + /* Within 0->5.5 range, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(3, 1), -20, 0.1); + /* Within 5.5->10 range, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(6, 9), 10, 0.1); + /* Within 5.5->10 range, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(9, 6), -10, 0.1); + /* Crossing knee, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(3, 6), (2.5 * 10 + 0.5 * 3.333333333333333333), 0.1); + /* Crossing knee, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(6, 3), -(2.5 * 10 + 0.5 * 3.333333333333333333), 0.1); +} + +BOOST_AUTO_TEST_CASE (datasat_ap2x_test) +{ + DatasatAP2x ap; + + /* No change */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(7, 7), 0, 0.1); + /* Within 0->3.2 range, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(0, 2), 40, 0.1); + /* Within 0->3.2 range, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(2, 0), -40, 0.1); + /* Within 3.2->10 range, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(6, 9), 15, 0.1); + /* Within 3.2->10 range, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(9, 6), -15, 0.1); + /* Crossing knee, up */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(3, 6), (0.2 * 20 + 2.8 * 5), 0.1); + /* Crossing knee, down */ + BOOST_CHECK_CLOSE (ap.db_for_fader_change(6, 3), -(0.2 * 20 + 2.8 * 5), 0.1); +} diff --git a/test/wscript b/test/wscript index d3f4a5382..06687cd17 100644 --- a/test/wscript +++ b/test/wscript @@ -52,6 +52,7 @@ def build(bld): audio_processor_delay_test.cc audio_ring_buffers_test.cc butler_test.cc + cinema_sound_processor_test.cc client_server_test.cc closed_caption_test.cc colour_conversion_test.cc -- 2.30.2