326 lines
10 KiB
C++
326 lines
10 KiB
C++
/*
|
|
* Copyright (C) 2009-2012 Sakari Bergen <sakari.bergen@beatwaves.net>
|
|
* Copyright (C) 2010-2012 David Robillard <d@drobilla.net>
|
|
* Copyright (C) 2013-2017 Paul Davis <paul@linuxaudiosystems.com>
|
|
* Copyright (C) 2016-2019 Robin Gareus <robin@gareus.org>
|
|
*
|
|
* 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.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifndef __ardour_export_graph_builder_h__
|
|
#define __ardour_export_graph_builder_h__
|
|
|
|
#include "ardour/export_handler.h"
|
|
#include "ardour/export_analysis.h"
|
|
#include "ardour/export_smf_writer.h"
|
|
|
|
#include "audiographer/utils/identity_vertex.h"
|
|
|
|
#include <boost/ptr_container/ptr_list.hpp>
|
|
#include <glibmm/threadpool.h>
|
|
|
|
namespace AudioGrapher {
|
|
class SampleRateConverter;
|
|
class PeakReader;
|
|
class LoudnessReader;
|
|
class Normalizer;
|
|
class Limiter;
|
|
class Analyser;
|
|
class DemoNoiseAdder;
|
|
template <typename T> class Chunker;
|
|
template <typename T> class SampleFormatConverter;
|
|
template <typename T> class Interleaver;
|
|
template <typename T> class SndfileWriter;
|
|
template <typename T> class CmdPipeWriter;
|
|
template <typename T> class SilenceTrimmer;
|
|
template <typename T> class TmpFile;
|
|
template <typename T> class Threader;
|
|
template <typename T> class AllocatingProcessContext;
|
|
}
|
|
|
|
namespace ARDOUR
|
|
{
|
|
|
|
class ExportTimespan;
|
|
class MidiBuffer;
|
|
class Session;
|
|
|
|
class LIBARDOUR_API ExportGraphBuilder
|
|
{
|
|
private:
|
|
typedef ExportHandler::FileSpec FileSpec;
|
|
|
|
typedef std::shared_ptr<AudioGrapher::Sink<Sample> > FloatSinkPtr;
|
|
typedef std::shared_ptr<AudioGrapher::Analyser> AnalysisPtr;
|
|
typedef std::map<std::string, AnalysisPtr> AnalysisMap;
|
|
|
|
struct AnyExport {
|
|
/* Audio export */
|
|
AudioGrapher::IdentityVertex<Sample> audio;
|
|
void add_output (AudioGrapher::Source<Sample>::SinkPtr output) {
|
|
audio.add_output (output);
|
|
}
|
|
void process (AudioGrapher::ProcessContext<Sample> const& c) {
|
|
audio.process (c);
|
|
}
|
|
/* MIDI Export */
|
|
ExportSMFWriter midi;
|
|
void process (MidiBuffer const& buf, sampleoffset_t off, samplecnt_t cnt, bool last_cycle) {
|
|
midi.process (buf, off, cnt, last_cycle);
|
|
}
|
|
};
|
|
|
|
typedef std::shared_ptr<AnyExport> AnyExportPtr;
|
|
typedef std::map<ExportChannelPtr, AnyExportPtr> ChannelMap;
|
|
|
|
public:
|
|
|
|
ExportGraphBuilder (Session const & session);
|
|
~ExportGraphBuilder ();
|
|
|
|
samplecnt_t process (samplecnt_t samples, bool last_cycle);
|
|
bool post_process (); // returns true when finished
|
|
bool need_postprocessing () const { return !intermediates.empty(); }
|
|
bool realtime() const { return _realtime; }
|
|
unsigned get_postprocessing_cycle_count() const;
|
|
|
|
void reset ();
|
|
void cleanup (bool remove_out_files = false);
|
|
void set_current_timespan (std::shared_ptr<ExportTimespan> span);
|
|
void add_config (FileSpec const & config, bool rt);
|
|
void get_analysis_results (AnalysisResults& results);
|
|
|
|
std::vector<std::string> exported_files () const {
|
|
return _exported_files;
|
|
}
|
|
|
|
private:
|
|
|
|
void add_analyser (const std::string& fn, AnalysisPtr ap) {
|
|
analysis_map.insert (std::make_pair (fn, ap));
|
|
}
|
|
|
|
void add_export_fn (std::string const& fn) {
|
|
_exported_files.push_back (fn);
|
|
}
|
|
|
|
std::vector<std::string> _exported_files;
|
|
|
|
void add_split_config (FileSpec const & config);
|
|
|
|
class Encoder {
|
|
public:
|
|
template <typename T> std::shared_ptr<AudioGrapher::Sink<T> > init (FileSpec const & new_config);
|
|
void add_child (FileSpec const & new_config);
|
|
void remove_children ();
|
|
void destroy_writer (bool delete_out_file);
|
|
bool operator== (FileSpec const & other_config) const;
|
|
|
|
static int get_real_format (FileSpec const & config);
|
|
|
|
private:
|
|
typedef std::shared_ptr<AudioGrapher::SndfileWriter<Sample> > FloatWriterPtr;
|
|
typedef std::shared_ptr<AudioGrapher::SndfileWriter<int> > IntWriterPtr;
|
|
typedef std::shared_ptr<AudioGrapher::SndfileWriter<short> > ShortWriterPtr;
|
|
|
|
typedef std::shared_ptr<AudioGrapher::CmdPipeWriter<Sample> > FloatPipePtr;
|
|
|
|
template<typename T> void init_writer (std::shared_ptr<AudioGrapher::SndfileWriter<T> > & writer);
|
|
template<typename T> void init_writer (std::shared_ptr<AudioGrapher::CmdPipeWriter<T> > & writer);
|
|
|
|
void copy_files (std::string orig_path);
|
|
|
|
FileSpec config;
|
|
std::list<ExportFilenamePtr> filenames;
|
|
PBD::ScopedConnection copy_files_connection;
|
|
|
|
std::string writer_filename;
|
|
|
|
// Only one of these should be available at a time
|
|
FloatWriterPtr float_writer;
|
|
IntWriterPtr int_writer;
|
|
ShortWriterPtr short_writer;
|
|
FloatPipePtr pipe_writer;
|
|
};
|
|
|
|
// sample format converter
|
|
class SFC {
|
|
public:
|
|
// This constructor so that this can be constructed like a Normalizer
|
|
SFC (ExportGraphBuilder &, FileSpec const & new_config, samplecnt_t max_samples);
|
|
FloatSinkPtr sink ();
|
|
void add_child (FileSpec const & new_config);
|
|
void remove_children (bool remove_out_files);
|
|
bool operator== (FileSpec const & other_config) const;
|
|
|
|
void set_duration (samplecnt_t);
|
|
void set_peak_dbfs (float, bool force = false);
|
|
void set_peak_lufs (AudioGrapher::LoudnessReader const&);
|
|
|
|
private:
|
|
typedef std::shared_ptr<AudioGrapher::Chunker<float> > ChunkerPtr;
|
|
typedef std::shared_ptr<AudioGrapher::DemoNoiseAdder> DemoNoisePtr;
|
|
typedef std::shared_ptr<AudioGrapher::Normalizer> NormalizerPtr;
|
|
typedef std::shared_ptr<AudioGrapher::Limiter> LimiterPtr;
|
|
typedef std::shared_ptr<AudioGrapher::SampleFormatConverter<Sample> > FloatConverterPtr;
|
|
typedef std::shared_ptr<AudioGrapher::SampleFormatConverter<int> > IntConverterPtr;
|
|
typedef std::shared_ptr<AudioGrapher::SampleFormatConverter<short> > ShortConverterPtr;
|
|
|
|
FileSpec config;
|
|
int data_width;
|
|
boost::ptr_list<Encoder> children;
|
|
|
|
NormalizerPtr normalizer;
|
|
LimiterPtr limiter;
|
|
DemoNoisePtr demo_noise_adder;
|
|
ChunkerPtr chunker;
|
|
AnalysisPtr analyser;
|
|
bool _analyse;
|
|
// Only one of these should be available at a time
|
|
FloatConverterPtr float_converter;
|
|
IntConverterPtr int_converter;
|
|
ShortConverterPtr short_converter;
|
|
};
|
|
|
|
class Intermediate {
|
|
public:
|
|
Intermediate (ExportGraphBuilder & parent, FileSpec const & new_config, samplecnt_t max_samples);
|
|
FloatSinkPtr sink ();
|
|
void add_child (FileSpec const & new_config);
|
|
void remove_children (bool remove_out_files);
|
|
bool operator== (FileSpec const & other_config) const;
|
|
|
|
unsigned get_postprocessing_cycle_count() const;
|
|
|
|
/// Returns true when finished
|
|
bool process ();
|
|
|
|
private:
|
|
typedef std::shared_ptr<AudioGrapher::PeakReader> PeakReaderPtr;
|
|
typedef std::shared_ptr<AudioGrapher::LoudnessReader> LoudnessReaderPtr;
|
|
typedef std::shared_ptr<AudioGrapher::TmpFile<Sample> > TmpFilePtr;
|
|
typedef std::shared_ptr<AudioGrapher::Threader<Sample> > ThreaderPtr;
|
|
typedef std::shared_ptr<AudioGrapher::AllocatingProcessContext<Sample> > BufferPtr;
|
|
|
|
void prepare_post_processing ();
|
|
void start_post_processing ();
|
|
|
|
ExportGraphBuilder & parent;
|
|
|
|
FileSpec config;
|
|
samplecnt_t max_samples_out;
|
|
bool use_loudness;
|
|
bool use_peak;
|
|
BufferPtr buffer;
|
|
PeakReaderPtr peak_reader;
|
|
TmpFilePtr tmp_file;
|
|
ThreaderPtr threader;
|
|
|
|
LoudnessReaderPtr loudness_reader;
|
|
boost::ptr_list<SFC> children;
|
|
|
|
PBD::ScopedConnectionList post_processing_connection;
|
|
};
|
|
|
|
// sample rate converter
|
|
class SRC {
|
|
public:
|
|
SRC (ExportGraphBuilder & parent, FileSpec const & new_config, samplecnt_t max_samples);
|
|
FloatSinkPtr sink ();
|
|
void add_child (FileSpec const & new_config);
|
|
void remove_children (bool remove_out_files);
|
|
|
|
bool operator== (FileSpec const & other_config) const;
|
|
|
|
private:
|
|
typedef std::shared_ptr<AudioGrapher::SampleRateConverter> SRConverterPtr;
|
|
|
|
template<typename T>
|
|
void add_child_to_list (FileSpec const & new_config, boost::ptr_list<T> & list);
|
|
|
|
ExportGraphBuilder & parent;
|
|
FileSpec config;
|
|
boost::ptr_list<SFC> children;
|
|
boost::ptr_list<Intermediate> intermediate_children;
|
|
SRConverterPtr converter;
|
|
samplecnt_t max_samples_out;
|
|
};
|
|
|
|
// Silence trimmer + adder
|
|
class SilenceHandler {
|
|
public:
|
|
SilenceHandler (ExportGraphBuilder & parent, FileSpec const & new_config, samplecnt_t max_samples);
|
|
FloatSinkPtr sink ();
|
|
void add_child (FileSpec const & new_config);
|
|
void remove_children (bool remove_out_files);
|
|
bool operator== (FileSpec const & other_config) const;
|
|
|
|
private:
|
|
typedef std::shared_ptr<AudioGrapher::SilenceTrimmer<Sample> > SilenceTrimmerPtr;
|
|
|
|
ExportGraphBuilder & parent;
|
|
FileSpec config;
|
|
boost::ptr_list<SRC> children;
|
|
SilenceTrimmerPtr silence_trimmer;
|
|
samplecnt_t max_samples_in;
|
|
};
|
|
|
|
// channel configuration
|
|
class ChannelConfig {
|
|
public:
|
|
ChannelConfig (ExportGraphBuilder & parent, FileSpec const & new_config, ChannelMap & channel_map);
|
|
void add_child (FileSpec const & new_config);
|
|
void remove_children (bool remove_out_files);
|
|
bool operator== (FileSpec const & other_config) const;
|
|
|
|
private:
|
|
typedef std::shared_ptr<AudioGrapher::Interleaver<Sample> > InterleaverPtr;
|
|
typedef std::shared_ptr<AudioGrapher::Chunker<Sample> > ChunkerPtr;
|
|
|
|
ExportGraphBuilder & parent;
|
|
FileSpec config;
|
|
boost::ptr_list<SilenceHandler> children;
|
|
InterleaverPtr interleaver;
|
|
ChunkerPtr chunker;
|
|
samplecnt_t max_samples_out;
|
|
};
|
|
|
|
Session const & session;
|
|
std::shared_ptr<ExportTimespan> timespan;
|
|
|
|
// Roots for export processor trees
|
|
typedef boost::ptr_list<ChannelConfig> ChannelConfigList;
|
|
ChannelConfigList channel_configs;
|
|
|
|
// The sources of all data, each channel is read only once
|
|
ChannelMap channels;
|
|
|
|
samplecnt_t process_buffer_samples;
|
|
|
|
std::list<Intermediate *> intermediates;
|
|
|
|
AnalysisMap analysis_map;
|
|
|
|
bool _realtime;
|
|
samplecnt_t _master_align;
|
|
|
|
Glib::ThreadPool thread_pool;
|
|
Glib::Threads::Mutex engine_request_lock;
|
|
};
|
|
|
|
} // namespace ARDOUR
|
|
|
|
#endif /* __ardour_export_graph_builder_h__ */
|