mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 19:56:31 +01:00
libardour support for timespan realtime export
This commit is contained in:
parent
77687519b6
commit
f8a6213454
6 changed files with 56 additions and 18 deletions
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ class LIBARDOUR_API ExportStatus {
|
|||
volatile enum Progress {
|
||||
Exporting,
|
||||
Normalizing,
|
||||
Encoding,
|
||||
Tagging,
|
||||
Uploading,
|
||||
Command }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
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;
|
||||
|
||||
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,9 +471,11 @@ ExportGraphBuilder::Normalizer::sink ()
|
|||
{
|
||||
if (use_loudness) {
|
||||
return loudness_reader;
|
||||
}
|
||||
} else if (use_peak) {
|
||||
return peak_reader;
|
||||
}
|
||||
return tmp_file;
|
||||
}
|
||||
|
||||
void
|
||||
ExportGraphBuilder::Normalizer::add_child (FileSpec const & new_config)
|
||||
|
|
@ -518,12 +536,17 @@ 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);
|
||||
}
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -291,9 +292,13 @@ ExportHandler::process_normalize ()
|
|||
if (graph_builder->process_normalize ()) {
|
||||
finish_timespan ();
|
||||
export_status->active_job = ExportStatus::Exporting;
|
||||
} else {
|
||||
if (graph_builder->realtime ()) {
|
||||
export_status->active_job = ExportStatus::Encoding;
|
||||
} else {
|
||||
export_status->active_job = ExportStatus::Normalizing;
|
||||
}
|
||||
}
|
||||
|
||||
export_status->current_normalize_cycle++;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue