1 /* 2 * Copyright (C) 2009-2012 Sakari Bergen <sakari.bergen@beatwaves.net> 3 * Copyright (C) 2010-2012 David Robillard <d@drobilla.net> 4 * Copyright (C) 2013-2017 Paul Davis <paul@linuxaudiosystems.com> 5 * Copyright (C) 2016-2019 Robin Gareus <robin@gareus.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 */ 21 22 #ifndef __ardour_export_graph_builder_h__ 23 #define __ardour_export_graph_builder_h__ 24 25 #include "ardour/export_handler.h" 26 #include "ardour/export_analysis.h" 27 28 #include "audiographer/utils/identity_vertex.h" 29 30 #include <boost/ptr_container/ptr_list.hpp> 31 #include <glibmm/threadpool.h> 32 33 namespace AudioGrapher { 34 class SampleRateConverter; 35 class PeakReader; 36 class LoudnessReader; 37 class Normalizer; 38 class Limiter; 39 class Analyser; 40 class DemoNoiseAdder; 41 template <typename T> class Chunker; 42 template <typename T> class SampleFormatConverter; 43 template <typename T> class Interleaver; 44 template <typename T> class SndfileWriter; 45 template <typename T> class CmdPipeWriter; 46 template <typename T> class SilenceTrimmer; 47 template <typename T> class TmpFile; 48 template <typename T> class Threader; 49 template <typename T> class AllocatingProcessContext; 50 } 51 52 namespace ARDOUR 53 { 54 55 class ExportTimespan; 56 class Session; 57 58 class LIBARDOUR_API ExportGraphBuilder 59 { 60 private: 61 typedef ExportHandler::FileSpec FileSpec; 62 63 typedef boost::shared_ptr<AudioGrapher::Sink<Sample> > FloatSinkPtr; 64 typedef boost::shared_ptr<AudioGrapher::IdentityVertex<Sample> > IdentityVertexPtr; 65 typedef boost::shared_ptr<AudioGrapher::Analyser> AnalysisPtr; 66 typedef std::map<ExportChannelPtr, IdentityVertexPtr> ChannelMap; 67 typedef std::map<std::string, AnalysisPtr> AnalysisMap; 68 69 public: 70 71 ExportGraphBuilder (Session const & session); 72 ~ExportGraphBuilder (); 73 74 samplecnt_t process (samplecnt_t samples, bool last_cycle); 75 bool post_process (); // returns true when finished need_postprocessing()76 bool need_postprocessing () const { return !intermediates.empty(); } realtime()77 bool realtime() const { return _realtime; } 78 unsigned get_postprocessing_cycle_count() const; 79 80 void reset (); 81 void cleanup (bool remove_out_files = false); 82 void set_current_timespan (boost::shared_ptr<ExportTimespan> span); 83 void add_config (FileSpec const & config, bool rt); 84 void get_analysis_results (AnalysisResults& results); 85 86 private: 87 add_analyser(const std::string & fn,AnalysisPtr ap)88 void add_analyser (const std::string& fn, AnalysisPtr ap) { 89 analysis_map.insert (std::make_pair (fn, ap)); 90 } 91 92 void add_split_config (FileSpec const & config); 93 94 class Encoder { 95 public: 96 template <typename T> boost::shared_ptr<AudioGrapher::Sink<T> > init (FileSpec const & new_config); 97 void add_child (FileSpec const & new_config); 98 void remove_children (); 99 void destroy_writer (bool delete_out_file); 100 bool operator== (FileSpec const & other_config) const; 101 102 static int get_real_format (FileSpec const & config); 103 104 private: 105 typedef boost::shared_ptr<AudioGrapher::SndfileWriter<Sample> > FloatWriterPtr; 106 typedef boost::shared_ptr<AudioGrapher::SndfileWriter<int> > IntWriterPtr; 107 typedef boost::shared_ptr<AudioGrapher::SndfileWriter<short> > ShortWriterPtr; 108 109 typedef boost::shared_ptr<AudioGrapher::CmdPipeWriter<Sample> > FloatPipePtr; 110 111 template<typename T> void init_writer (boost::shared_ptr<AudioGrapher::SndfileWriter<T> > & writer); 112 template<typename T> void init_writer (boost::shared_ptr<AudioGrapher::CmdPipeWriter<T> > & writer); 113 114 void copy_files (std::string orig_path); 115 116 FileSpec config; 117 std::list<ExportFilenamePtr> filenames; 118 PBD::ScopedConnection copy_files_connection; 119 120 std::string writer_filename; 121 122 // Only one of these should be available at a time 123 FloatWriterPtr float_writer; 124 IntWriterPtr int_writer; 125 ShortWriterPtr short_writer; 126 FloatPipePtr pipe_writer; 127 }; 128 129 // sample format converter 130 class SFC { 131 public: 132 // This constructor so that this can be constructed like a Normalizer 133 SFC (ExportGraphBuilder &, FileSpec const & new_config, samplecnt_t max_samples); 134 FloatSinkPtr sink (); 135 void add_child (FileSpec const & new_config); 136 void remove_children (bool remove_out_files); 137 bool operator== (FileSpec const & other_config) const; 138 139 void set_duration (samplecnt_t); 140 void set_peak_dbfs (float, bool force = false); 141 void set_peak_lufs (AudioGrapher::LoudnessReader const&); 142 143 private: 144 typedef boost::shared_ptr<AudioGrapher::Chunker<float> > ChunkerPtr; 145 typedef boost::shared_ptr<AudioGrapher::DemoNoiseAdder> DemoNoisePtr; 146 typedef boost::shared_ptr<AudioGrapher::Normalizer> NormalizerPtr; 147 typedef boost::shared_ptr<AudioGrapher::Limiter> LimiterPtr; 148 typedef boost::shared_ptr<AudioGrapher::SampleFormatConverter<Sample> > FloatConverterPtr; 149 typedef boost::shared_ptr<AudioGrapher::SampleFormatConverter<int> > IntConverterPtr; 150 typedef boost::shared_ptr<AudioGrapher::SampleFormatConverter<short> > ShortConverterPtr; 151 152 FileSpec config; 153 int data_width; 154 boost::ptr_list<Encoder> children; 155 156 NormalizerPtr normalizer; 157 LimiterPtr limiter; 158 DemoNoisePtr demo_noise_adder; 159 ChunkerPtr chunker; 160 AnalysisPtr analyser; 161 bool _analyse; 162 // Only one of these should be available at a time 163 FloatConverterPtr float_converter; 164 IntConverterPtr int_converter; 165 ShortConverterPtr short_converter; 166 }; 167 168 class Intermediate { 169 public: 170 Intermediate (ExportGraphBuilder & parent, FileSpec const & new_config, samplecnt_t max_samples); 171 FloatSinkPtr sink (); 172 void add_child (FileSpec const & new_config); 173 void remove_children (bool remove_out_files); 174 bool operator== (FileSpec const & other_config) const; 175 176 unsigned get_postprocessing_cycle_count() const; 177 178 /// Returns true when finished 179 bool process (); 180 181 private: 182 typedef boost::shared_ptr<AudioGrapher::PeakReader> PeakReaderPtr; 183 typedef boost::shared_ptr<AudioGrapher::LoudnessReader> LoudnessReaderPtr; 184 typedef boost::shared_ptr<AudioGrapher::TmpFile<Sample> > TmpFilePtr; 185 typedef boost::shared_ptr<AudioGrapher::Threader<Sample> > ThreaderPtr; 186 typedef boost::shared_ptr<AudioGrapher::AllocatingProcessContext<Sample> > BufferPtr; 187 188 void prepare_post_processing (); 189 void start_post_processing (); 190 191 ExportGraphBuilder & parent; 192 193 FileSpec config; 194 samplecnt_t max_samples_out; 195 bool use_loudness; 196 bool use_peak; 197 BufferPtr buffer; 198 PeakReaderPtr peak_reader; 199 TmpFilePtr tmp_file; 200 ThreaderPtr threader; 201 202 LoudnessReaderPtr loudness_reader; 203 boost::ptr_list<SFC> children; 204 205 PBD::ScopedConnectionList post_processing_connection; 206 }; 207 208 // sample rate converter 209 class SRC { 210 public: 211 SRC (ExportGraphBuilder & parent, FileSpec const & new_config, samplecnt_t max_samples); 212 FloatSinkPtr sink (); 213 void add_child (FileSpec const & new_config); 214 void remove_children (bool remove_out_files); 215 216 bool operator== (FileSpec const & other_config) const; 217 218 private: 219 typedef boost::shared_ptr<AudioGrapher::SampleRateConverter> SRConverterPtr; 220 221 template<typename T> 222 void add_child_to_list (FileSpec const & new_config, boost::ptr_list<T> & list); 223 224 ExportGraphBuilder & parent; 225 FileSpec config; 226 boost::ptr_list<SFC> children; 227 boost::ptr_list<Intermediate> intermediate_children; 228 SRConverterPtr converter; 229 samplecnt_t max_samples_out; 230 }; 231 232 // Silence trimmer + adder 233 class SilenceHandler { 234 public: 235 SilenceHandler (ExportGraphBuilder & parent, FileSpec const & new_config, samplecnt_t max_samples); 236 FloatSinkPtr sink (); 237 void add_child (FileSpec const & new_config); 238 void remove_children (bool remove_out_files); 239 bool operator== (FileSpec const & other_config) const; 240 241 private: 242 typedef boost::shared_ptr<AudioGrapher::SilenceTrimmer<Sample> > SilenceTrimmerPtr; 243 244 ExportGraphBuilder & parent; 245 FileSpec config; 246 boost::ptr_list<SRC> children; 247 SilenceTrimmerPtr silence_trimmer; 248 samplecnt_t max_samples_in; 249 }; 250 251 // channel configuration 252 class ChannelConfig { 253 public: 254 ChannelConfig (ExportGraphBuilder & parent, FileSpec const & new_config, ChannelMap & channel_map); 255 void add_child (FileSpec const & new_config); 256 void remove_children (bool remove_out_files); 257 bool operator== (FileSpec const & other_config) const; 258 259 private: 260 typedef boost::shared_ptr<AudioGrapher::Interleaver<Sample> > InterleaverPtr; 261 typedef boost::shared_ptr<AudioGrapher::Chunker<Sample> > ChunkerPtr; 262 263 ExportGraphBuilder & parent; 264 FileSpec config; 265 boost::ptr_list<SilenceHandler> children; 266 InterleaverPtr interleaver; 267 ChunkerPtr chunker; 268 samplecnt_t max_samples_out; 269 }; 270 271 Session const & session; 272 boost::shared_ptr<ExportTimespan> timespan; 273 274 // Roots for export processor trees 275 typedef boost::ptr_list<ChannelConfig> ChannelConfigList; 276 ChannelConfigList channel_configs; 277 278 // The sources of all data, each channel is read only once 279 ChannelMap channels; 280 281 samplecnt_t process_buffer_samples; 282 283 std::list<Intermediate *> intermediates; 284 285 AnalysisMap analysis_map; 286 287 bool _realtime; 288 samplecnt_t _master_align; 289 290 Glib::ThreadPool thread_pool; 291 Glib::Threads::Mutex engine_request_lock; 292 }; 293 294 } // namespace ARDOUR 295 296 #endif /* __ardour_export_graph_builder_h__ */ 297