Basic support for calculating audio gains based on the sound processor's gain curve.
authorCarl Hetherington <cth@carlh.net>
Tue, 31 Jul 2012 18:38:28 +0000 (19:38 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 31 Jul 2012 18:38:28 +0000 (19:38 +0100)
14 files changed:
src/lib/config.cc
src/lib/config.h
src/lib/dolby_cp750.cc [new file with mode: 0644]
src/lib/dolby_cp750.h [new file with mode: 0644]
src/lib/scaler.h
src/lib/sound_processor.cc [new file with mode: 0644]
src/lib/sound_processor.h [new file with mode: 0644]
src/lib/util.cc
src/lib/wscript
src/wx/film_editor.cc
src/wx/film_editor.h
src/wx/gain_calculator_dialog.cc [new file with mode: 0644]
src/wx/gain_calculator_dialog.h [new file with mode: 0644]
src/wx/wscript

index 92044d81a57764b9072691ca00a6ef9e54739296..53674645d864abea3a988852c7ccce84707a29f3 100644 (file)
@@ -27,6 +27,7 @@
 #include "scaler.h"
 #include "screen.h"
 #include "filter.h"
+#include "sound_processor.h"
 
 using namespace std;
 using namespace boost;
@@ -41,6 +42,7 @@ Config::Config ()
        , _j2k_bandwidth (250000000)
        , _reference_scaler (Scaler::from_id ("bicubic"))
        , _tms_path (".")
+       , _sound_processor (SoundProcessor::from_id ("dolby_cp750"))
 {
        ifstream f (file().c_str ());
        string line;
@@ -85,6 +87,8 @@ Config::Config ()
                        _tms_user = v;
                } else if (k == "tms_password") {
                        _tms_password = v;
+               } else if (k == "sound_processor") {
+                       _sound_processor = SoundProcessor::from_id (v);
                }
        }
 
@@ -139,4 +143,5 @@ Config::write () const
        f << "tms_path " << _tms_path << "\n";
        f << "tms_user " << _tms_user << "\n";
        f << "tms_password " << _tms_password << "\n";
+       f << "sound_processor " << _sound_processor->id ();
 }
index cbb83ad868c18bb32f84194e43e78b6b1ca45ef1..64bcf4d86d9ca0c7d7155f5c79af60832692c3fb 100644 (file)
@@ -32,6 +32,7 @@ class Server;
 class Screen;
 class Scaler;
 class Filter;
+class SoundProcessor;
 
 /** @class Config
  *  @brief A singleton class holding configuration.
@@ -97,6 +98,10 @@ public:
                return _tms_password;
        }
 
+       SoundProcessor const * sound_processor () const {
+               return _sound_processor;
+       }
+
        /** @param n New number of local encoding threads */
        void set_num_local_encoding_threads (int n) {
                _num_local_encoding_threads = n;
@@ -200,6 +205,8 @@ private:
        std::string _tms_user;
        std::string _tms_password;
 
+       SoundProcessor const * _sound_processor;
+
        /** Singleton instance, or 0 */
        static Config* _instance;
 };
diff --git a/src/lib/dolby_cp750.cc b/src/lib/dolby_cp750.cc
new file mode 100644 (file)
index 0000000..262e57b
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "dolby_cp750.h"
+
+using namespace std;
+
+DolbyCP750::DolbyCP750 ()
+       : SoundProcessor ("dolby_cp750", "Dolby CP750")
+{
+
+}
+
+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
new file mode 100644 (file)
index 0000000..b6c0e7d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "sound_processor.h"
+
+class DolbyCP750 : public SoundProcessor
+{
+public:
+       DolbyCP750 ();
+
+       float db_for_fader_change (float from, float to) const;
+};
index 8ededfe2a124d37406525d6e8df3169102c80ff4..d5a83f732b12d6dd7f7322037e464e380886c99f 100644 (file)
@@ -71,7 +71,7 @@ private:
        /** user-visible name for this scaler */
        std::string _name;
 
-       /** sll available scalers */
+       /** all available scalers */
        static std::vector<Scaler const *> _scalers;
 };
 
diff --git a/src/lib/sound_processor.cc b/src/lib/sound_processor.cc
new file mode 100644 (file)
index 0000000..9be6621
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/sound_processor.cc
+ *  @brief A class to describe a sound processor.
+ */
+
+#include <iostream>
+#include <cassert>
+#include "sound_processor.h"
+#include "dolby_cp750.h"
+
+using namespace std;
+
+vector<SoundProcessor const *> SoundProcessor::_sound_processors;
+
+/** @param i Our id.
+ *  @param n User-visible name.
+ */
+SoundProcessor::SoundProcessor (string i, string n)
+       : _id (i)
+       , _name (n)
+{
+
+}
+
+/** @return All available sound processors */
+vector<SoundProcessor const *>
+SoundProcessor::all ()
+{
+       return _sound_processors;
+}
+
+/** Set up the static _sound_processors vector; must be called before from_*
+ *  methods are used.
+ */
+void
+SoundProcessor::setup_sound_processors ()
+{
+       _sound_processors.push_back (new DolbyCP750);
+}
+
+/** @param id One of our ids.
+ *  @return Corresponding sound processor, or 0.
+ */
+SoundProcessor const *
+SoundProcessor::from_id (string id)
+{
+       vector<SoundProcessor const *>::iterator i = _sound_processors.begin ();
+       while (i != _sound_processors.end() && (*i)->id() != id) {
+               ++i;
+       }
+
+       if (i == _sound_processors.end ()) {
+               return 0;
+       }
+
+       return *i;
+}
+
+/** @param s A sound processor from our static list.
+ *  @return Index of the sound processor with the list, or -1.
+ */
+int
+SoundProcessor::as_index (SoundProcessor const * s)
+{
+       vector<SoundProcessor*>::size_type i = 0;
+       while (i < _sound_processors.size() && _sound_processors[i] != s) {
+               ++i;
+       }
+
+       if (i == _sound_processors.size ()) {
+               return -1;
+       }
+
+       return i;
+}
+
+/** @param i An index returned from as_index().
+ *  @return Corresponding sound processor.
+ */
+SoundProcessor const *
+SoundProcessor::from_index (int i)
+{
+       assert (i <= int(_sound_processors.size ()));
+       return _sound_processors[i];
+}
diff --git a/src/lib/sound_processor.h b/src/lib/sound_processor.h
new file mode 100644 (file)
index 0000000..2edf388
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/sound_processor.h
+ *  @brief A class to describe a sound processor.
+ */
+
+#ifndef DVDOMATIC_SOUND_PROCESSOR_H
+#define DVDOMATIC_SOUND_PROCESSOR_H
+
+#include <string>
+#include <vector>
+
+/** @class SoundProcessor
+ *  @brief Class to describe a sound processor.
+ */
+class SoundProcessor
+{
+public:
+       SoundProcessor (std::string i, std::string n);
+
+       virtual float db_for_fader_change (float from, float to) const = 0;
+
+       /** @return id for our use */
+       std::string id () const {
+               return _id;
+       }
+
+       /** @return user-visible name for this sound processor */
+       std::string name () const {
+               return _name;
+       }
+       
+       static std::vector<SoundProcessor const *> all ();
+       static void setup_sound_processors ();
+       static SoundProcessor const * from_id (std::string id);
+       static SoundProcessor const * from_index (int);
+       static int as_index (SoundProcessor const *);
+
+private:
+       /** id for our use */
+       std::string _id;
+       /** user-visible name for this sound processor */
+       std::string _name;
+
+       /** sll available sound processors */
+       static std::vector<SoundProcessor const *> _sound_processors;
+};
+
+#endif
index 5106f3182e7cc74e67a8cdaf5a3fae3653153a19..1ab8c1e65b53fd82946a5868d9d5ddc8f84d532f 100644 (file)
@@ -54,6 +54,7 @@ extern "C" {
 #include "filter.h"
 #include "screen.h"
 #include "film_state.h"
+#include "sound_processor.h"
 #ifndef DVDOMATIC_DISABLE_PLAYER
 #include "player_manager.h"
 #endif
@@ -386,6 +387,7 @@ dvdomatic_setup ()
        DCPContentType::setup_dcp_content_types ();
        Scaler::setup_scalers ();
        Filter::setup_filters ();
+       SoundProcessor::setup_sound_processors ();
 
 #ifdef DVDOMATIC_POSIX 
        struct sigaction sa;
index afc91660560e289c32e7a297ad4ee287bd4493ae..71a2b23f41be508c893b0c250ee1137e389b93f2 100644 (file)
@@ -23,6 +23,7 @@ def build(bld):
                  decoder.cc
                  decoder_factory.cc
                  delay_line.cc
+                 dolby_cp750.cc
                  dvd.cc
                 encoder.cc
                  encoder_factory.cc
@@ -46,6 +47,7 @@ def build(bld):
                 scaler.cc
                  screen.cc
                 server.cc
+                 sound_processor.cc
                 thumbs_job.cc
                  tiff_decoder.cc
                 tiff_encoder.cc
index f0fc4f68f3db51e769520f7c9eca6f38e65c0e19..4240bc05c303cfa3eb72a704ee9f7e6d3ef51876 100644 (file)
@@ -41,6 +41,8 @@
 #include "wx_util.h"
 #include "film_editor.h"
 #include "dcp_range_dialog.h"
+#include "gain_calculator_dialog.h"
+#include "sound_processor.h"
 
 using namespace std;
 using namespace boost;
@@ -113,6 +115,8 @@ FilmEditor::FilmEditor (Film* f, wxWindow* parent)
                _audio_gain = new wxSpinCtrl (this);
                s->Add (video_control (_audio_gain), 1);
                video_control (add_label_to_sizer (s, this, "dB"));
+               _audio_gain_calculate_button = new wxButton (this, wxID_ANY, _("Calculate..."));
+               s->Add (_audio_gain_calculate_button, 1, wxEXPAND);
                _sizer->Add (s);
        }
 
@@ -209,6 +213,9 @@ FilmEditor::FilmEditor (Film* f, wxWindow* parent)
        _dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
        _dcp_ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::dcp_ab_toggled), 0, this);
        _audio_gain->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_gain_changed), 0, this);
+       _audio_gain_calculate_button->Connect (
+               wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::audio_gain_calculate_button_clicked), 0, this
+               );
        _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this);
        _still_duration->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this);
        _change_dcp_range_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::change_dcp_range_clicked), 0, this);
@@ -520,6 +527,7 @@ FilmEditor::set_things_sensitive (bool s)
        _change_dcp_range_button->Enable (s);
        _dcp_ab->Enable (s);
        _audio_gain->Enable (s);
+       _audio_gain_calculate_button->Enable (s);
        _audio_delay->Enable (s);
        _still_duration->Enable (s);
 }
@@ -647,3 +655,17 @@ FilmEditor::dcp_range_changed (int frames, TrimAction action)
        _film->set_dcp_frames (frames);
        _film->set_dcp_trim_action (action);
 }
+
+void
+FilmEditor::audio_gain_calculate_button_clicked (wxCommandEvent &)
+{
+       GainCalculatorDialog* d = new GainCalculatorDialog (this);
+       d->ShowModal ();
+       _audio_gain->SetValue (
+               Config::instance()->sound_processor()->db_for_fader_change (
+                       d->wanted_fader (),
+                       d->actual_fader ()
+                       )
+               );
+       d->Destroy ();
+}
index d5157acc6df9a8656a538afa7f1f50b67a45d5aa..0b4c1e7c1dc09884e4bbad538484989a5ee7665e 100644 (file)
@@ -57,6 +57,7 @@ private:
        void dcp_ab_toggled (wxCommandEvent &);
        void scaler_changed (wxCommandEvent &);
        void audio_gain_changed (wxCommandEvent &);
+       void audio_gain_calculate_button_clicked (wxCommandEvent &);
        void audio_delay_changed (wxCommandEvent &);
        void still_duration_changed (wxCommandEvent &);
 
@@ -100,6 +101,7 @@ private:
        wxComboBox* _scaler;
        /** The Film's audio gain */
        wxSpinCtrl* _audio_gain;
+       wxButton* _audio_gain_calculate_button;
        /** The Film's audio delay */
        wxSpinCtrl* _audio_delay;
        /** The Film's DCP content type */
diff --git a/src/wx/gain_calculator_dialog.cc b/src/wx/gain_calculator_dialog.cc
new file mode 100644 (file)
index 0000000..9b6c7b0
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/lexical_cast.hpp>
+#include "gain_calculator_dialog.h"
+#include "wx_util.h"
+
+using namespace boost;
+
+GainCalculatorDialog::GainCalculatorDialog (wxWindow* parent)
+       : wxDialog (parent, wxID_ANY, _("Gain Calculator"))
+{
+       wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
+       table->AddGrowableCol (1, 1);
+
+       add_label_to_sizer (table, this, "I want to play this back at fader");
+       _wanted = new wxTextCtrl (this, wxID_ANY, wxT (""), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator (wxFILTER_NUMERIC));
+       table->Add (_wanted, 1, wxEXPAND);
+
+       add_label_to_sizer (table, this, "But I have to use fader");
+       _actual = new wxTextCtrl (this, wxID_ANY, wxT (""), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator (wxFILTER_NUMERIC));
+       table->Add (_actual, 1, wxEXPAND);
+
+       wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+       overall_sizer->Add (table, 1, wxEXPAND);
+
+       wxSizer* buttons = CreateSeparatedButtonSizer (wxOK);
+       if (buttons) {
+               overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+       }
+       
+       SetSizer (overall_sizer);
+       overall_sizer->SetSizeHints (this);
+}
+
+float
+GainCalculatorDialog::wanted_fader () const
+{
+       return lexical_cast<float> (wx_to_std (_wanted->GetValue ()));
+}
+
+float
+GainCalculatorDialog::actual_fader () const
+{
+       return lexical_cast<float> (wx_to_std (_actual->GetValue ()));
+}
diff --git a/src/wx/gain_calculator_dialog.h b/src/wx/gain_calculator_dialog.h
new file mode 100644 (file)
index 0000000..363a91a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <wx/wx.h>
+
+class GainCalculatorDialog : public wxDialog
+{
+public:
+       GainCalculatorDialog (wxWindow* parent);
+
+       float actual_fader () const;
+       float wanted_fader () const;
+
+private:
+       wxTextCtrl* _wanted;
+       wxTextCtrl* _actual;
+};
index f59dbe983a3eb1289da0e9098f15db695e5b73e6..348a9cb0ad085a3eb0072241151a50f4c58e4434 100644 (file)
@@ -14,6 +14,7 @@ def build(bld):
                  film_viewer.cc
                  job_manager_view.cc
                  job_wrapper.cc
+                 gain_calculator_dialog.cc
                  config_dialog.cc
                  filter_dialog.cc
                  filter_view.cc