Pad silence for things that already have at least some audio.
authorCarl Hetherington <cth@carlh.net>
Thu, 4 Jul 2013 21:29:47 +0000 (22:29 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 4 Jul 2013 21:29:47 +0000 (22:29 +0100)
src/lib/encoder.cc
src/lib/film.cc
src/lib/film.h
src/lib/transcoder.cc
src/lib/util.cc
src/lib/util.h
src/lib/writer.cc
src/tools/dvdomatic.cc
src/wx/audio_dialog.cc
src/wx/film_editor.cc
src/wx/film_editor.h

index 2c989452d012b7773cda11f97c91ee5341e3e0d4..6a99132fdfffc614233b4b8611fc37f768785438 100644 (file)
@@ -433,10 +433,10 @@ Encoder::encoder_thread (ServerDescription* server)
 void
 Encoder::write_audio (shared_ptr<const AudioBuffers> data)
 {
-       AudioMapping m (_film->audio_channels ());
+       AudioMapping m (_film);
        if (m.dcp_channels() != _film->audio_channels()) {
 
-               /* Remap (currently just for mono -> 5.1) */
+               /* Remap and pad with silence */
 
                shared_ptr<AudioBuffers> b (new AudioBuffers (m.dcp_channels(), data->frames ()));
                for (int i = 0; i < m.dcp_channels(); ++i) {
index d92d7a9777a477dad28644a2a2274b0ec298b3fa..ce555ac8b29b3ac33d17e906ec05a3699620da7e 100644 (file)
@@ -108,6 +108,7 @@ Film::Film (string d, bool must_exist)
        , _j2k_bandwidth (200000000)
        , _dci_metadata (Config::instance()->default_dci_metadata ())
        , _dcp_frame_rate (0)
+       , _minimum_audio_channels (0)
        , _source_frame_rate (0)
        , _dirty (false)
 {
@@ -185,6 +186,7 @@ Film::Film (Film const & o)
        , _dci_metadata      (o._dci_metadata)
        , _dci_date          (o._dci_date)
        , _dcp_frame_rate    (o._dcp_frame_rate)
+       , _minimum_audio_channels (o._minimum_audio_channels)
        , _size              (o._size)
        , _length            (o._length)
        , _content_digest    (o._content_digest)
@@ -506,6 +508,7 @@ Film::write_metadata () const
        _dci_metadata.write (f);
        f << "dci_date " << boost::gregorian::to_iso_string (_dci_date) << endl;
        f << "dcp_frame_rate " << _dcp_frame_rate << endl;
+       f << "minimum_audio_channels " << _minimum_audio_channels << endl;
        f << "width " << _size.width << endl;
        f << "height " << _size.height << endl;
        f << "length " << _length.get_value_or(0) << endl;
@@ -642,6 +645,8 @@ Film::read_metadata ()
                        _dci_date = boost::gregorian::from_undelimited_string (v);
                } else if (k == "dcp_frame_rate") {
                        _dcp_frame_rate = atoi (v.c_str ());
+               } else if (k == "minimum_audio_channels") {
+                       _minimum_audio_channels = atoi (v.c_str ());
                }
 
                _dci_metadata.read (k, v);
@@ -1323,6 +1328,16 @@ Film::set_dcp_frame_rate (int f)
        signal_changed (DCP_FRAME_RATE);
 }
 
+void
+Film::set_minimum_audio_channels (int c)
+{
+       {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               _minimum_audio_channels = c;
+       }
+       signal_changed (MINIMUM_AUDIO_CHANNELS);
+}
+                       
 void
 Film::set_size (libdcp::Size s)
 {
index dd0a83d94e473f5da6d5b9e98d1378e247c0c3eb..ca9bd57f43a0fbd4439d5db12247b3b2e194ea3f 100644 (file)
@@ -153,7 +153,8 @@ public:
                CONTENT_AUDIO_STREAMS,
                SUBTITLE_STREAMS,
                SOURCE_FRAME_RATE,
-               DCP_FRAME_RATE
+               DCP_FRAME_RATE,
+               MINIMUM_AUDIO_CHANNELS
        };
 
 
@@ -335,6 +336,11 @@ public:
                return _source_frame_rate;
        }
 
+       int minimum_audio_channels () const {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               return _minimum_audio_channels;
+       }
+
        boost::shared_ptr<AudioStream> audio_stream () const;
        bool has_audio () const;
        
@@ -379,6 +385,7 @@ public:
        void set_content_audio_streams (std::vector<boost::shared_ptr<AudioStream> >);
        void set_subtitle_streams (std::vector<boost::shared_ptr<SubtitleStream> >);
        void set_source_frame_rate (float);
+       void set_minimum_audio_channels (int);
 
        /** Emitted when some property has changed */
        mutable boost::signals2::signal<void (Property)> Changed;
@@ -481,6 +488,7 @@ private:
        boost::gregorian::date _dci_date;
        /** Frames per second to run our DCP at */
        int _dcp_frame_rate;
+       int _minimum_audio_channels;
 
        /* Data which are cached to speed things up */
 
index 48cf402d77bac4f36ababbac36adff4fb880d5e9..a202d440c0c736cd63d0c24521a2e1ab28984f73 100644 (file)
@@ -73,7 +73,7 @@ Transcoder::Transcoder (shared_ptr<Film> f, DecodeOptions o, Job* j, shared_ptr<
        /* Set up the decoder to use the film's set streams */
        _decoders.video->set_subtitle_stream (f->subtitle_stream ());
        if (f->audio_stream ()) {
-           _decoders.audio->set_audio_stream (f->audio_stream ());
+               _decoders.audio->set_audio_stream (f->audio_stream ());
        }
 
        _decoders.video->connect_video (_delay_line);
index 4cf57368a7aea6718302c21441e719cdeeb7eb96..83980f82829ac3b7c5e00001dbfd4cd863f877af 100644 (file)
@@ -61,6 +61,7 @@ extern "C" {
 #include "filter.h"
 #include "sound_processor.h"
 #include "config.h"
+#include "film.h"
 #ifdef DVDOMATIC_WINDOWS
 #include "stack.hpp"
 #endif
@@ -962,8 +963,9 @@ audio_channel_name (int c)
        return channels[c];
 }
 
-AudioMapping::AudioMapping (int c)
-       : _source_channels (c)
+AudioMapping::AudioMapping (shared_ptr<const Film> f)
+       : _source_channels (f->audio_stream() ? f->audio_stream()->channels() : 0)
+       , _minimum_channels (f->minimum_audio_channels ())
 {
 
 }
@@ -1001,8 +1003,11 @@ AudioMapping::dcp_to_source (libdcp::Channel c) const
        return static_cast<int> (c);
 }
 
+/** @return minimum number of DCP channels that we can allow in this
+    DCP, given the nature of the source.
+*/
 int
-AudioMapping::dcp_channels () const
+AudioMapping::minimum_dcp_channels () const
 {
        if (_source_channels == 1) {
                /* The source is mono, so to put the mono channel into
@@ -1014,6 +1019,15 @@ AudioMapping::dcp_channels () const
        return _source_channels;
 }
 
+/** @return number of channels that there should be in the DCP, including
+ *  any silent padded ones.
+ */
+int
+AudioMapping::dcp_channels () const
+{
+       return max (_source_channels, _minimum_channels);
+}
+
 FrameRateConversion::FrameRateConversion (float source, int dcp)
        : skip (false)
        , repeat (false)
index 0d745e50c5f3152c3984758c2260d0acf65a7fd1..c9e5bef16c0388c34ecbf50182b6ce4d90ac44c9 100644 (file)
@@ -50,6 +50,7 @@ extern "C" {
 #define MAX_AUDIO_CHANNELS 6
 
 class Scaler;
+class Film;
 
 extern std::string seconds_to_hms (int);
 extern std::string seconds_to_approximate_hms (int);
@@ -287,14 +288,17 @@ private:
 class AudioMapping
 {
 public:
-       AudioMapping (int);
+       AudioMapping (boost::shared_ptr<const Film>);
 
        boost::optional<libdcp::Channel> source_to_dcp (int c) const;
        boost::optional<int> dcp_to_source (libdcp::Channel c) const;
+
+       int minimum_dcp_channels () const;
        int dcp_channels () const;
 
 private:
        int _source_channels;
+       int _minimum_channels;
 };
 
 extern int64_t video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second);
index 1a6daa1db35156343bc15399863e26224b84243f..cff0b5be23925ea09592b03dbcc27410f6e64e9c 100644 (file)
@@ -77,7 +77,7 @@ Writer::Writer (shared_ptr<Film> f)
 
        _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
 
-       AudioMapping m (_film->audio_channels ());
+       AudioMapping m (_film);
        
        if (m.dcp_channels() > 0) {
                _sound_asset.reset (
index de94d0a2fdbaab0acc9c14e64696af169aeae701..e0629bb9883c7bcbcd493252043c208cb7a01990 100644 (file)
@@ -166,7 +166,7 @@ setup_menu (wxMenuBar* m)
        add_item (file, _("&Properties..."), ID_file_properties, NEEDS_FILM);
 #ifndef __WXOSX__      
        file->AppendSeparator ();
-#endif 
+#endif
        add_item (file, _("&Exit"), wxID_EXIT, ALWAYS);
 
 #ifdef __WXOSX__       
index d12b5516fc8f72023c67bdd7801a18dfad937d3a..21e4e5940e4b100c089ec1e8f1175371c434aa17 100644 (file)
@@ -108,7 +108,7 @@ AudioDialog::setup_channels ()
                return;
        }
 
-       AudioMapping m (_film->audio_stream()->channels ());
+       AudioMapping m (_film);
        
        for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
                if (m.dcp_to_source(static_cast<libdcp::Channel>(i))) {
@@ -134,7 +134,7 @@ AudioDialog::try_to_load_analysis ()
                
        _plot->set_analysis (a);
 
-       AudioMapping m (_film->audio_stream()->channels ());
+       AudioMapping m (_film);
        optional<libdcp::Channel> c = m.source_to_dcp (0);
        if (c) {
                _channel_checkbox[c.get()]->SetValue (true);
@@ -157,7 +157,7 @@ AudioDialog::channel_clicked (wxCommandEvent& ev)
 
        assert (c < MAX_AUDIO_CHANNELS);
 
-       AudioMapping m (_film->audio_stream()->channels ());
+       AudioMapping m (_film);
        optional<int> s = m.dcp_to_source (static_cast<libdcp::Channel> (c));
        if (s) {
                _plot->set_channel_visible (s.get(), _channel_checkbox[c]->GetValue ());
index dd952e22a9817dd81c5adbe24bc655301d441381..13bef5a240390e7f156e71f67dec328ab6159926 100644 (file)
@@ -232,6 +232,8 @@ FilmEditor::connect_to_widgets ()
        _dcp_content_type->Connect     (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
        _dcp_frame_rate->Connect       (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED,      wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
        _best_dcp_frame_rate->Connect  (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED,       wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
+       _pad_with_silence->Connect     (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED,     wxCommandEventHandler (FilmEditor::pad_with_silence_toggled), 0, this);
+       _minimum_audio_channels->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,   wxCommandEventHandler (FilmEditor::minimum_audio_channels_changed), 0, this);
        _dcp_ab->Connect               (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED,     wxCommandEventHandler (FilmEditor::dcp_ab_toggled), 0, this);
        _still_duration->Connect       (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this);
        _trim_start->Connect           (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED,     wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
@@ -392,6 +394,16 @@ FilmEditor::make_audio_panel ()
                grid->Add (s);
        }
 
+       {
+               _pad_with_silence = new wxCheckBox (_audio_panel, wxID_ANY, _("Pad with silence to"));
+               grid->Add (_pad_with_silence);
+               wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+               _minimum_audio_channels = new wxSpinCtrl (_audio_panel);
+               s->Add (_minimum_audio_channels, 1);
+               add_label_to_sizer (s, _audio_panel, _("channels"));
+               grid->Add (s);
+       }
+
        {
                _use_content_audio = new wxRadioButton (_audio_panel, wxID_ANY, _("Use content's audio"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
                grid->Add (video_control (_use_content_audio));
@@ -415,6 +427,7 @@ FilmEditor::make_audio_panel ()
 
        _audio_gain->SetRange (-60, 60);
        _audio_delay->SetRange (-1000, 1000);
+       _minimum_audio_channels->SetRange (0, MAX_AUDIO_CHANNELS);
 }
 
 void
@@ -628,6 +641,7 @@ FilmEditor::film_changed (Film::Property p)
                setup_streams ();
                setup_show_audio_sensitivity ();
                setup_frame_rate_description ();
+               setup_minimum_audio_channels ();
                break;
        case Film::TRUST_CONTENT_HEADER:
                checked_set (_trust_content_header, _film->trust_content_header ());
@@ -640,6 +654,7 @@ FilmEditor::film_changed (Film::Property p)
                setup_streams ();
                setup_show_audio_sensitivity ();
                setup_frame_rate_description ();
+               setup_minimum_audio_channels ();
                break;
        case Film::FORMAT:
        {
@@ -764,6 +779,7 @@ FilmEditor::film_changed (Film::Property p)
                setup_audio_control_sensitivity ();
                setup_show_audio_sensitivity ();
                setup_frame_rate_description ();
+               setup_minimum_audio_channels ();
                break;
        case Film::USE_CONTENT_AUDIO:
                _film->log()->log (String::compose ("Film::USE_CONTENT_AUDIO changed; setting GUI using %1", _film->use_content_audio ()));
@@ -774,6 +790,7 @@ FilmEditor::film_changed (Film::Property p)
                setup_audio_control_sensitivity ();
                setup_show_audio_sensitivity ();
                setup_frame_rate_description ();
+               setup_minimum_audio_channels ();
                break;
        case Film::SUBTITLE_STREAM:
                if (_film->subtitle_stream()) {
@@ -789,6 +806,7 @@ FilmEditor::film_changed (Film::Property p)
                setup_audio_details ();
                setup_show_audio_sensitivity ();
                setup_frame_rate_description ();
+               setup_minimum_audio_channels ();
                break;
        }
        case Film::DCP_FRAME_RATE:
@@ -808,6 +826,10 @@ FilmEditor::film_changed (Film::Property p)
                }
 
                setup_frame_rate_description ();
+       case Film::MINIMUM_AUDIO_CHANNELS:
+               checked_set (_minimum_audio_channels, _film->minimum_audio_channels ());
+               setup_minimum_audio_channels ();
+               break;
        }
 }
 
@@ -1185,6 +1207,9 @@ FilmEditor::setup_audio_control_sensitivity ()
        for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
                _external_audio[i]->Enable (external);
        }
+
+       _pad_with_silence->Enable (_generally_sensitive && _film && _film->audio_stream() && _film->audio_stream()->channels() < MAX_AUDIO_CHANNELS);
+       _minimum_audio_channels->Enable (_generally_sensitive && _pad_with_silence->GetValue ());
 }
 
 void
@@ -1411,3 +1436,33 @@ FilmEditor::trim_type_changed (wxCommandEvent &)
 {
        _film->set_trim_type (_trim_type->GetSelection () == 0 ? Film::CPL : Film::ENCODE);
 }
+
+void
+FilmEditor::setup_minimum_audio_channels ()
+{
+       if (!_film || !_film->audio_stream ()) {
+               _pad_with_silence->SetValue (false);
+               return;
+       }
+
+       _pad_with_silence->SetValue (_film->audio_stream()->channels() < _film->minimum_audio_channels());
+
+       AudioMapping m (_film);
+       _minimum_audio_channels->SetRange (m.minimum_dcp_channels(), MAX_AUDIO_CHANNELS);
+}
+
+void
+FilmEditor::pad_with_silence_toggled (wxCommandEvent &)
+{
+       setup_audio_control_sensitivity ();
+}
+
+void
+FilmEditor::minimum_audio_channels_changed (wxCommandEvent &)
+{
+       if (!_film) {
+               return;
+       }
+
+       _film->set_minimum_audio_channels (_minimum_audio_channels->GetValue ());
+}
index e2a4d583641eb9ae23ea5d76afc0262b602be20e..c2d064ca202bc1d3305c52182b35092ecaa088e1 100644 (file)
@@ -85,6 +85,8 @@ private:
        void external_audio_changed (wxCommandEvent &);
        void dcp_frame_rate_changed (wxCommandEvent &);
        void best_dcp_frame_rate_clicked (wxCommandEvent &);
+       void pad_with_silence_toggled (wxCommandEvent &);
+       void minimum_audio_channels_changed (wxCommandEvent &);
 
        /* Handle changes to the model */
        void film_changed (Film::Property);
@@ -103,6 +105,7 @@ private:
        void setup_scaling_description ();
        void setup_notebook_size ();
        void setup_frame_rate_description ();
+       void setup_minimum_audio_channels ();
        
        wxControl* video_control (wxControl *);
        wxControl* still_control (wxControl *);
@@ -169,6 +172,8 @@ private:
        wxStaticText* _source_frame_rate;
        wxChoice* _dcp_frame_rate;
        wxButton* _best_dcp_frame_rate;
+       wxCheckBox* _pad_with_silence;
+       wxSpinCtrl* _minimum_audio_channels;
        wxStaticText* _frame_rate_description;
        /** The Film's length */
        wxStaticText* _length;