libardour support for timespan realtime export
authorRobin Gareus <robin@gareus.org>
Fri, 15 Jul 2016 15:04:34 +0000 (17:04 +0200)
committerRobin Gareus <robin@gareus.org>
Sat, 16 Jul 2016 00:14:18 +0000 (02:14 +0200)
libs/ardour/ardour/export_graph_builder.h
libs/ardour/ardour/export_status.h
libs/ardour/ardour/export_timespan.h
libs/ardour/export_graph_builder.cc
libs/ardour/export_handler.cc
libs/ardour/export_timespan.cc

index cee98ed7be961b7d805cda97ba96e521b5d14da9..b692b03b3231f2e09b91ee1cabfce48e562f9870 100644 (file)
@@ -69,13 +69,14 @@ class LIBARDOUR_API ExportGraphBuilder
 
        int process (framecnt_t frames, bool last_cycle);
        bool process_normalize (); // returns true when finished
-       bool will_normalize() { return !normalizers.empty(); }
+       bool will_normalize() const { return !normalizers.empty(); }
+       bool realtime() const { return _realtime; }
        unsigned get_normalize_cycle_count() const;
 
        void reset ();
        void cleanup (bool remove_out_files = false);
        void set_current_timespan (boost::shared_ptr<ExportTimespan> span);
-       void add_config (FileSpec const & config);
+       void add_config (FileSpec const & config, bool rt);
        void get_analysis_results (AnalysisResults& results);
 
   private:
@@ -175,6 +176,7 @@ class LIBARDOUR_API ExportGraphBuilder
                FileSpec        config;
                framecnt_t      max_frames_out;
                bool            use_loudness;
+               bool            use_peak;
                BufferPtr       buffer;
                PeakReaderPtr   peak_reader;
                TmpFilePtr      tmp_file;
@@ -265,6 +267,8 @@ class LIBARDOUR_API ExportGraphBuilder
 
        AnalysisMap analysis_map;
 
+       bool _realtime;
+
        Glib::ThreadPool thread_pool;
 };
 
index f250ae0dc6b062a04b69bf05e06ba646ba374acd..4782f49cb4917ba82ee4d17bf6627b9051cb0702 100644 (file)
@@ -62,6 +62,7 @@ class LIBARDOUR_API ExportStatus {
        volatile enum Progress {
                Exporting,
                Normalizing,
+               Encoding,
                Tagging,
                Uploading,
                Command }
index 754335ba48f0a552971a5c2f8ba0a143060ab159..d4631cbccc00731ba634191673c9ac94c5fc6874 100644 (file)
@@ -53,6 +53,9 @@ class LIBARDOUR_API ExportTimespan
        std::string range_id () const { return _range_id; }
        void set_range_id (std::string range_id) { _range_id = range_id; }
 
+       bool realtime () const { return _realtime; }
+       void set_realtime (bool rt) { _realtime = rt; }
+
        void set_range (framepos_t start, framepos_t end);
        framecnt_t get_length () const { return end_frame - start_frame; }
        framepos_t get_start () const { return start_frame; }
@@ -76,6 +79,7 @@ class LIBARDOUR_API ExportTimespan
 
        std::string _name;
        std::string _range_id;
+       bool        _realtime;
 
 };
 
index 9065aea1303ef3d62e18a5cd37cde6d1e9e8b116..96b0853122b807efcbbd92995cc31f1445a169e4 100644 (file)
@@ -115,6 +115,7 @@ ExportGraphBuilder::reset ()
        channels.clear ();
        normalizers.clear ();
        analysis_map.clear();
+       _realtime = false;
 }
 
 void
@@ -135,7 +136,7 @@ ExportGraphBuilder::set_current_timespan (boost::shared_ptr<ExportTimespan> span
 }
 
 void
-ExportGraphBuilder::add_config (FileSpec const & config)
+ExportGraphBuilder::add_config (FileSpec const & config, bool rt)
 {
        ExportChannelConfiguration::ChannelList const & channels =
                config.channel_config->get_channels();
@@ -144,6 +145,8 @@ ExportGraphBuilder::add_config (FileSpec const & config)
                (*it)->set_max_buffer_size(process_buffer_frames);
        }
 
+       _realtime = rt;
+
        // If the sample rate is "session rate", change it to the real value.
        // However, we need to copy it to not change the config which is saved...
        FileSpec new_config (config);
@@ -413,6 +416,7 @@ ExportGraphBuilder::SFC::operator== (FileSpec const & other_config) const
 ExportGraphBuilder::Normalizer::Normalizer (ExportGraphBuilder & parent, FileSpec const & new_config, framecnt_t max_frames)
        : parent (parent)
        , use_loudness (false)
+       , use_peak (false)
 {
        std::string tmpfile_path = parent.session.session_directory().export_path();
        tmpfile_path = Glib::build_filename(tmpfile_path, "XXXXXX");
@@ -424,18 +428,30 @@ ExportGraphBuilder::Normalizer::Normalizer (ExportGraphBuilder & parent, FileSpe
        uint32_t const channels = config.channel_config->get_n_chans();
        max_frames_out = 4086 - (4086 % channels); // TODO good chunk size
        use_loudness = config.format->normalize_loudness ();
+       use_peak = config.format->normalize ();
 
        buffer.reset (new AllocatingProcessContext<Sample> (max_frames_out, channels));
-       peak_reader.reset (new PeakReader ());
-       loudness_reader.reset (new LoudnessReader (config.format->sample_rate(), channels, max_frames));
+
+       if (use_peak) {
+               peak_reader.reset (new PeakReader ());
+       }
+       if (use_loudness) {
+               loudness_reader.reset (new LoudnessReader (config.format->sample_rate(), channels, max_frames));
+       }
+
        normalizer.reset (new AudioGrapher::Normalizer (use_loudness ? 0.0 : config.format->normalize_dbfs()));
        threader.reset (new Threader<Sample> (parent.thread_pool));
-
        normalizer->alloc_buffer (max_frames_out);
        normalizer->add_output (threader);
 
        int format = ExportFormatBase::F_RAW | ExportFormatBase::SF_Float;
-       tmp_file.reset (new TmpFileSync<float> (&tmpfile_path_buf[0], format, channels, config.format->sample_rate()));
+
+       if (parent._realtime) {
+               tmp_file.reset (new TmpFileRt<float> (&tmpfile_path_buf[0], format, channels, config.format->sample_rate()));
+       } else {
+               tmp_file.reset (new TmpFileSync<float> (&tmpfile_path_buf[0], format, channels, config.format->sample_rate()));
+       }
+
        tmp_file->FileWritten.connect_same_thread (post_processing_connection,
                                                   boost::bind (&Normalizer::prepare_post_processing, this));
        tmp_file->FileFlushed.connect_same_thread (post_processing_connection,
@@ -445,7 +461,7 @@ ExportGraphBuilder::Normalizer::Normalizer (ExportGraphBuilder & parent, FileSpe
 
        if (use_loudness) {
                loudness_reader->add_output (tmp_file);
-       } else {
+       } else if (use_peak) {
                peak_reader->add_output (tmp_file);
        }
 }
@@ -455,8 +471,10 @@ ExportGraphBuilder::Normalizer::sink ()
 {
        if (use_loudness) {
                return loudness_reader;
+       } else if (use_peak) {
+               return peak_reader;
        }
-       return peak_reader;
+       return tmp_file;
 }
 
 void
@@ -518,11 +536,16 @@ ExportGraphBuilder::Normalizer::prepare_post_processing()
        float gain;
        if (use_loudness) {
                gain = normalizer->set_peak (loudness_reader->get_peak (config.format->normalize_lufs (), config.format->normalize_dbtp ()));
-       } else {
+       } else if (use_peak) {
                gain = normalizer->set_peak (peak_reader->get_peak());
+       } else {
+               gain = normalizer->set_peak (0.0);
        }
-       for (boost::ptr_list<SFC>::iterator i = children.begin(); i != children.end(); ++i) {
-               (*i).set_peak (gain);
+       if (use_loudness || use_peak) {
+               // push info to analyzers
+               for (boost::ptr_list<SFC>::iterator i = children.begin(); i != children.end(); ++i) {
+                       (*i).set_peak (gain);
+               }
        }
        tmp_file->add_output (normalizer);
        parent.normalizers.push_back (this);
@@ -561,7 +584,7 @@ ExportGraphBuilder::SRC::sink ()
 void
 ExportGraphBuilder::SRC::add_child (FileSpec const & new_config)
 {
-       if (new_config.format->normalize()) {
+       if (new_config.format->normalize() || parent._realtime) {
                add_child_to_list (new_config, normalized_children);
        } else {
                add_child_to_list (new_config, children);
index d83e2beebba8189917cebbe966962730cf2375c6..9d5e9848e624b607c1e98d8d8fe8cd5b506f421e 100644 (file)
@@ -190,11 +190,12 @@ ExportHandler::start_timespan ()
        graph_builder->reset ();
        graph_builder->set_current_timespan (current_timespan);
        handle_duplicate_format_extensions();
+       bool realtime = current_timespan->realtime ();
        for (ConfigMap::iterator it = timespan_bounds.first; it != timespan_bounds.second; ++it) {
                // Filenames can be shared across timespans
                FileSpec & spec = it->second;
                spec.filename->set_timespan (it->first);
-               graph_builder->add_config (spec);
+               graph_builder->add_config (spec, realtime);
        }
 
        /* start export */
@@ -202,7 +203,7 @@ ExportHandler::start_timespan ()
        normalizing = false;
        session.ProcessExport.connect_same_thread (process_connection, boost::bind (&ExportHandler::process, this, _1));
        process_position = current_timespan->get_start();
-       session.start_audio_export (process_position);
+       session.start_audio_export (process_position, realtime);
 }
 
 void
@@ -272,7 +273,7 @@ ExportHandler::process_timespan (framecnt_t frames)
 
        /* Start normalizing if necessary */
        if (last_cycle) {
-               normalizing = graph_builder->will_normalize();
+               normalizing = graph_builder->will_normalize ();
                if (normalizing) {
                        export_status->total_normalize_cycles = graph_builder->get_normalize_cycle_count();
                        export_status->current_normalize_cycle = 0;
@@ -292,7 +293,11 @@ ExportHandler::process_normalize ()
                finish_timespan ();
                export_status->active_job = ExportStatus::Exporting;
        } else {
-               export_status->active_job = ExportStatus::Normalizing;
+               if (graph_builder->realtime ()) {
+                       export_status->active_job = ExportStatus::Encoding;
+               } else {
+                       export_status->active_job = ExportStatus::Normalizing;
+               }
        }
 
        export_status->current_normalize_cycle++;
index 3b2021355e1f9ecf7ce8c1a4ccad70709a25c9fd..f8a06769e409e4c18137dcb62e4338a624395d27 100644 (file)
@@ -28,7 +28,8 @@ ExportTimespan::ExportTimespan (ExportStatusPtr status, framecnt_t frame_rate) :
        start_frame (0),
        end_frame (0),
        position (0),
-       frame_rate (frame_rate)
+       frame_rate (frame_rate),
+       _realtime (false)
 {
 
 }