diff options
author | David Robillard <d@drobilla.net> | 2014-12-17 21:48:09 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2014-12-17 21:48:09 -0500 |
commit | 0f759e9a936e3ea00a1196ab8b55e415240f5f5f (patch) | |
tree | 4a872ab6ff7dad79d1442d219fdc867522a16f25 /libs/ardour | |
parent | 5f6630034919bde73ffa603e7420c8af2c3c16f7 (diff) |
MIDI bounce.
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/midi_buffer.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 2 | ||||
-rw-r--r-- | libs/ardour/midi_buffer.cc | 7 | ||||
-rw-r--r-- | libs/ardour/midi_track.cc | 52 | ||||
-rw-r--r-- | libs/ardour/session.cc | 41 |
5 files changed, 79 insertions, 31 deletions
diff --git a/libs/ardour/ardour/midi_buffer.h b/libs/ardour/ardour/midi_buffer.h index 2923b784a9..8593a4ebb2 100644 --- a/libs/ardour/ardour/midi_buffer.h +++ b/libs/ardour/ardour/midi_buffer.h @@ -21,7 +21,10 @@ #define __ardour_midi_buffer_h__ #include "evoral/midi_util.h" +#include "evoral/EventSink.hpp" + #include "midi++/event.h" + #include "ardour/buffer.h" #include "ardour/parameter_types.h" @@ -29,7 +32,7 @@ namespace ARDOUR { /** Buffer containing 8-bit unsigned char (MIDI) data. */ -class LIBARDOUR_API MidiBuffer : public Buffer +class LIBARDOUR_API MidiBuffer : public Buffer, public Evoral::EventSink<framepos_t> { public: typedef framepos_t TimeType; @@ -55,6 +58,9 @@ public: bool insert_event(const Evoral::MIDIEvent<TimeType>& event); bool merge_in_place(const MidiBuffer &other); + /** EventSink interface for non-RT use (export, bounce). */ + uint32_t write(TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf); + template<typename BufferType, typename EventType> class iterator_base { diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 9af744e2ec..c2e2808762 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -632,7 +632,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop /* flattening stuff */ - boost::shared_ptr<Region> write_one_track (AudioTrack&, framepos_t start, framepos_t end, + boost::shared_ptr<Region> write_one_track (Track&, framepos_t start, framepos_t end, bool overwrite, std::vector<boost::shared_ptr<Source> >&, InterThreadInfo& wot, boost::shared_ptr<Processor> endpoint, bool include_endpoint, bool for_export, bool for_freeze); diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc index 7f79262b2f..ee6bd13d51 100644 --- a/libs/ardour/midi_buffer.cc +++ b/libs/ardour/midi_buffer.cc @@ -250,6 +250,13 @@ MidiBuffer::insert_event(const Evoral::MIDIEvent<TimeType>& ev) return true; } +uint32_t +MidiBuffer::write(TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf) +{ + insert_event(Evoral::MIDIEvent<TimeType>(type, time, size, const_cast<uint8_t*>(buf))); + return size; +} + /** Reserve space for a new event in the buffer. * * This call is for copying MIDI directly into the buffer, the data location diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index b8fe7ada4c..ce07fa8f24 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -560,26 +560,52 @@ MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framep } int -MidiTrack::export_stuff (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framecnt_t /*nframes*/, - boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/, bool /*for_export*/, bool /*for_freeze*/) -{ - return -1; +MidiTrack::export_stuff (BufferSet& buffers, + framepos_t start, + framecnt_t nframes, + boost::shared_ptr<Processor> endpoint, + bool include_endpoint, + bool for_export, + bool for_freeze) +{ + if (buffers.count().n_midi() == 0) { + return -1; + } + + boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream(); + + Glib::Threads::RWLock::ReaderLock rlock (_processor_lock); + + boost::shared_ptr<MidiPlaylist> mpl = boost::dynamic_pointer_cast<MidiPlaylist>(diskstream->playlist()); + if (!mpl) { + return -2; + } + + buffers.get_midi(0).clear(); + if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) { + return -1; + } + + //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze); + + return 0; } boost::shared_ptr<Region> -MidiTrack::bounce (InterThreadInfo& /*itt*/) +MidiTrack::bounce (InterThreadInfo& itt) { - std::cerr << "MIDI bounce currently unsupported" << std::endl; - return boost::shared_ptr<Region> (); + return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false); } - boost::shared_ptr<Region> -MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/, - boost::shared_ptr<Processor> /*endpoint*/, bool /*include_endpoint*/) -{ - std::cerr << "MIDI bounce range currently unsupported" << std::endl; - return boost::shared_ptr<Region> (); +MidiTrack::bounce_range (framepos_t start, + framepos_t end, + InterThreadInfo& itt, + boost::shared_ptr<Processor> endpoint, + bool include_endpoint) +{ + vector<boost::shared_ptr<Source> > srcs; + return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false); } void diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 4710ea1534..5c6331c138 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -4386,7 +4386,7 @@ Session::freeze_all (InterThreadInfo& itt) } boost::shared_ptr<Region> -Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, +Session::write_one_track (Track& track, framepos_t start, framepos_t end, bool /*overwrite*/, vector<boost::shared_ptr<Source> >& srcs, InterThreadInfo& itt, boost::shared_ptr<Processor> endpoint, bool include_endpoint, @@ -4394,7 +4394,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, { boost::shared_ptr<Region> result; boost::shared_ptr<Playlist> playlist; - boost::shared_ptr<AudioFileSource> fsource; + boost::shared_ptr<Source> source; ChanCount diskstream_channels (track.n_channels()); framepos_t position; framecnt_t this_chunk; @@ -4416,8 +4416,8 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, diskstream_channels = track.bounce_get_output_streams (diskstream_channels, endpoint, include_endpoint, for_export, for_freeze); - if (diskstream_channels.n_audio() < 1) { - error << _("Cannot write a range with no audio.") << endmsg; + if (diskstream_channels.n(track.data_type()) < 1) { + error << _("Cannot write a range with no data.") << endmsg; return result; } @@ -4443,26 +4443,27 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, legal_playlist_name = legalize_for_path (playlist->name()); - for (uint32_t chan_n = 0; chan_n < diskstream_channels.n_audio(); ++chan_n) { + for (uint32_t chan_n = 0; chan_n < diskstream_channels.n(track.data_type()); ++chan_n) { string base_name = string_compose ("%1-%2-bounce", playlist->name(), chan_n); - string path = new_audio_source_path (legal_playlist_name, diskstream_channels.n_audio(), chan_n, false, true); + string path = ((track.data_type() == DataType::AUDIO) + ? new_audio_source_path (legal_playlist_name, diskstream_channels.n_audio(), chan_n, false, true) + : new_midi_source_path (legal_playlist_name)); if (path.empty()) { goto out; } try { - fsource = boost::dynamic_pointer_cast<AudioFileSource> ( - SourceFactory::createWritable (DataType::AUDIO, *this, path, false, frame_rate())); + source = SourceFactory::createWritable (track.data_type(), *this, path, false, frame_rate()); } catch (failed_constructor& err) { - error << string_compose (_("cannot create new audio file \"%1\" for %2"), path, track.name()) << endmsg; + error << string_compose (_("cannot create new file \"%1\" for %2"), path, track.name()) << endmsg; goto out; } - srcs.push_back (fsource); + srcs.push_back (source); } /* tell redirects that care that we are about to use a much larger @@ -4512,11 +4513,20 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, uint32_t n = 0; for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) { boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src); + boost::shared_ptr<MidiSource> ms; if (afs) { if (afs->write (buffers.get_audio(n).data(latency_skip), current_chunk) != current_chunk) { goto out; } + } else if ((ms = boost::dynamic_pointer_cast<MidiSource>(*src))) { + Source::Lock lock(ms->mutex()); + ms->mark_streaming_write_started(lock); + + const MidiBuffer& buf = buffers.get_midi(0); + for (MidiBuffer::const_iterator i = buf.begin(); i != buf.end(); ++i) { + ms->append_event_frames(lock, *i, ms->timeline_position()); + } } } latency_skip = 0; @@ -4553,10 +4563,14 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) { boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src); + boost::shared_ptr<MidiSource> ms; if (afs) { afs->update_header (position, *xnow, now); afs->flush_header (); + } else if ((ms = boost::dynamic_pointer_cast<MidiSource>(*src))) { + Source::Lock lock(ms->mutex()); + ms->mark_streaming_write_completed(lock); } } @@ -4575,12 +4589,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end, out: if (!result) { for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) { - boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src); - - if (afs) { - afs->mark_for_remove (); - } - + (*src)->mark_for_remove (); (*src)->drop_references (); } |