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