Add support for Datasat AP2x and USL sound processors when converting
authorCarl Hetherington <cth@carlh.net>
Tue, 2 Jul 2019 00:32:54 +0000 (01:32 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 2 Jul 2019 00:32:54 +0000 (01:32 +0100)
fader position to gain.   Stop storing a chosen processor in config;
instead, get the user to choose the processor when calculating gains.

16 files changed:
src/lib/cinema_sound_processor.cc
src/lib/cinema_sound_processor.h
src/lib/config.cc
src/lib/config.h
src/lib/datasat_ap2x.cc [new file with mode: 0644]
src/lib/datasat_ap2x.h [new file with mode: 0644]
src/lib/dolby_cp750.cc
src/lib/dolby_cp750.h
src/lib/usl.cc [new file with mode: 0644]
src/lib/usl.h [new file with mode: 0644]
src/lib/wscript
src/wx/audio_panel.cc
src/wx/gain_calculator_dialog.cc
src/wx/gain_calculator_dialog.h
test/cinema_sound_processor_test.cc [new file with mode: 0644]
test/wscript

index 0b00ee2..1a3ba5a 100644 (file)
@@ -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 <iostream>
 #include <cassert>
@@ -35,9 +37,12 @@ vector<CinemaSoundProcessor const *> 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;
+}
index c19c6ca..25c5760 100644 (file)
 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<CinemaSoundProcessor const *> _cinema_sound_processors;
index fdd0516..a7a4570 100644 (file)
@@ -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<string> ();
@@ -293,19 +291,9 @@ try
        _tms_user = f.string_child ("TMSUser");
        _tms_password = f.string_child ("TMSPassword");
 
-       optional<string> 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<string> 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 <code>dolby_cp750</code>.
-               */
-               root->add_child("CinemaSoundProcessor")->add_child_text (_cinema_sound_processor->id ());
-       }
        if (_language) {
                /* [XML:opt] Language Language to use in the GUI e.g. <code>fr_FR</code>. */
                root->add_child("Language")->add_child_text (_language.get());
index 29511b1..9a57b1b 100644 (file)
@@ -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<boost::shared_ptr<Cinema> > 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<int> _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 (file)
index 0000000..ade750c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+    Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+
+    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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#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 (file)
index 0000000..4bbe395
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+    Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+
+    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 <http://www.gnu.org/licenses/>.
+
+*/
+
+/** @file  src/lib/datasat_ap2x.h
+ *  @brief DatasatAP2x class.
+ */
+
+#include "cinema_sound_processor.h"
+
+class DatasatAP2x : public CinemaSoundProcessor
+{
+public:
+       DatasatAP2x ();
+};
index 3e2bb43..380ab05 100644 (file)
 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;
-}
index 3a8fcf6..3162a96 100644 (file)
@@ -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 (file)
index 0000000..b8a9a71
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+    Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+
+    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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#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 (file)
index 0000000..260eb3c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+    Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+
+    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 <http://www.gnu.org/licenses/>.
+
+*/
+
+/** @file  src/lib/usl.h
+ *  @brief USL class.
+ */
+
+#include "cinema_sound_processor.h"
+
+class USL : public CinemaSoundProcessor
+{
+public:
+       USL ();
+};
index c5a270f..177a58b 100644 (file)
@@ -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
index ccdb579..0cb062e 100644 (file)
@@ -251,18 +251,14 @@ AudioPanel::gain_calculate_button_clicked ()
 {
        GainCalculatorDialog* d = new GainCalculatorDialog (this);
        int const r = d->ShowModal ();
+       optional<float> 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.
index 8818aee..7018566 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 #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<float>
+GainCalculatorDialog::db_change () const
 {
-       if (_actual->GetValue().IsEmpty()) {
-               return 0;
+       if (_wanted->GetValue().IsEmpty() || _actual->GetValue().IsEmpty()) {
+               return optional<float>();
        }
 
-       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()))
+                       );
 }
index e1ed026..addc072 100644 (file)
 
 */
 
-#include <wx/wx.h>
 #include "table_dialog.h"
+#include <wx/wx.h>
+#include <boost/optional.hpp>
 
 class GainCalculatorDialog : public TableDialog
 {
 public:
        explicit GainCalculatorDialog (wxWindow* parent);
 
-       float actual_fader () const;
-       float wanted_fader () const;
+       boost::optional<float> 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 (file)
index 0000000..b17fd19
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+    Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+
+    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 <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "lib/dolby_cp750.h"
+#include "lib/usl.h"
+#include "lib/datasat_ap2x.h"
+#include <boost/test/unit_test.hpp>
+
+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);
+}
index d3f4a53..06687cd 100644 (file)
@@ -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