diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index e907971319..440944446a 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -170,6 +170,10 @@ class LIBARDOUR_API AudioRegion : public Region, public AudioReadable return _automatable.control(id); } + /* export */ + + bool do_export (std::string const&) const; + /* xfade/fade interactions */ void suspend_fade_in (); diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index 747b5608ba..1f8156a493 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -59,8 +59,6 @@ class LIBARDOUR_API MidiRegion : public Region public: ~MidiRegion(); - bool do_export (std::string path) const; - boost::shared_ptr clone (std::string path = std::string()) const; boost::shared_ptr clone (boost::shared_ptr, ThawList* tl = 0) const; @@ -97,6 +95,8 @@ class LIBARDOUR_API MidiRegion : public Region /* export */ + bool do_export (std::string const& path) const; + boost::shared_ptr model(); boost::shared_ptr model() const; diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 0b5b5ba593..9e6de37a53 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -349,6 +349,8 @@ public: XMLNode& get_state (); virtual int set_state (const XMLNode&, int version); + virtual bool do_export (std::string const&) const = 0; + virtual boost::shared_ptr get_parent() const; uint64_t layering_index () const { return _layering_index; } diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index d84c3eabef..61856a084a 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -32,6 +32,7 @@ #include #include +#include #include #include "pbd/basename.h" @@ -41,6 +42,7 @@ #include "evoral/Curve.h" +#include "ardour/audioengine.h" #include "ardour/analysis_graph.h" #include "ardour/audioregion.h" #include "ardour/session.h" @@ -51,11 +53,14 @@ #include "ardour/audiofilesource.h" #include "ardour/region_factory.h" #include "ardour/runtime_functions.h" +#include "ardour/sndfilesource.h" #include "ardour/transient_detector.h" #include "ardour/parameter_descriptor.h" #include "ardour/progress.h" -#include "ardour/sndfilesource.h" +#include "audiographer/general/interleaver.h" +#include "audiographer/general/sample_format_converter.h" +#include "audiographer/sndfile/sndfile_writer.h" #include "pbd/i18n.h" #include @@ -64,7 +69,6 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -#include "ardour/audioengine.h" #define S2SC(s) Temporal::samples_to_superclock (s, AudioEngine::instance()->sample_rate()) #define SC2S(s) Temporal::superclock_to_samples (s, AudioEngine::instance()->sample_rate()) @@ -2042,3 +2046,52 @@ AudioRegion::verify_xfade_bounds (samplecnt_t len, bool start) return min (length_samples(), min (maxlen, len)); } + +bool +AudioRegion::do_export (std::string const& path) const +{ + const uint32_t n_chn = n_channels (); + const samplepos_t chunk_size = 8192; + Sample buf[chunk_size]; + gain_t gain_buffer[chunk_size]; + + const int format = SF_FORMAT_FLAC | SF_FORMAT_PCM_24; // TODO preference or option + + assert (!path.empty ()); + assert (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)); + + typedef boost::shared_ptr> FloatWriterPtr; + FloatWriterPtr sfw; + try { + sfw.reset (new AudioGrapher::SndfileWriter (path, format, n_chn, audio_source ()->sample_rate (), 0)); + } catch (...) { + return false; + } + + AudioGrapher::Interleaver interleaver; + interleaver.init (n_channels (), chunk_size); + interleaver.add_output (sfw); + + samplepos_t to_read = length_samples (); + samplepos_t pos = position_sample (); + + while (to_read) { + samplepos_t this_time = min (to_read, chunk_size); + + for (uint32_t chn = 0; chn < n_chn; ++chn) { + if (read_at (buf, buf, gain_buffer, pos, this_time, chn) != this_time) { + break; + } + + AudioGrapher::ConstProcessContext context (buf, this_time, 1); + if (to_read == this_time) { + context ().set_flag (AudioGrapher::ProcessContext::EndOfInput); + } + interleaver.input (chn)->process (context); + } + + to_read -= this_time; + pos += this_time; + } + return to_read == 0; +} diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index 9bedeefe31..fe1418603e 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -98,7 +98,7 @@ MidiRegion::~MidiRegion () /** Export the MIDI data of the MidiRegion to a new MIDI file (SMF). */ bool -MidiRegion::do_export (string path) const +MidiRegion::do_export (string const& path) const { boost::shared_ptr newsrc;