add a MidiStateTracker to DiskReader and use to handle transport stop note resolving
This commit is contained in:
parent
67beff22ce
commit
e87e0ec028
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "ardour/disk_io.h"
|
||||
#include "ardour/midi_buffer.h"
|
||||
#include "ardour/midi_state_tracker.h"
|
||||
|
||||
namespace ARDOUR
|
||||
{
|
||||
|
@ -160,6 +161,7 @@ private:
|
|||
|
||||
DeclickAmp _declick_amp;
|
||||
sampleoffset_t _declick_offs;
|
||||
MidiStateTracker _tracker;
|
||||
|
||||
int _do_refill_with_alloc (bool partial_fill);
|
||||
|
||||
|
|
|
@ -135,6 +135,8 @@ public:
|
|||
bool input_active () const;
|
||||
PBD::Signal0<void> InputActiveChanged;
|
||||
|
||||
void realtime_handle_transport_stopped ();
|
||||
|
||||
protected:
|
||||
|
||||
XMLNode& state (bool save_template);
|
||||
|
|
|
@ -157,7 +157,7 @@ public:
|
|||
virtual bool can_record() { return false; }
|
||||
|
||||
void non_realtime_transport_stop (samplepos_t now, bool flush);
|
||||
void realtime_handle_transport_stopped ();
|
||||
virtual void realtime_handle_transport_stopped ();
|
||||
|
||||
virtual void realtime_locate () {}
|
||||
virtual void non_realtime_locate (samplepos_t);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
namespace ARDOUR {
|
||||
|
||||
class MidiBuffer;
|
||||
class MidiStateTracker;
|
||||
|
||||
/** */
|
||||
class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
|
||||
|
@ -47,7 +48,9 @@ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
|
|||
size_t size() const { return _size; }
|
||||
|
||||
uint32_t write (TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf);
|
||||
uint32_t read (MidiBuffer& dst, samplepos_t start, samplepos_t end, samplecnt_t offset = 0);
|
||||
uint32_t read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiStateTracker& tracker, samplecnt_t offset = 0);
|
||||
|
||||
void dump (uint32_t);
|
||||
|
||||
private:
|
||||
size_t _size;
|
||||
|
|
|
@ -142,7 +142,6 @@ public:
|
|||
bool can_internal_playback_seek (samplecnt_t);
|
||||
void internal_playback_seek (samplecnt_t);
|
||||
void non_realtime_locate (samplepos_t);
|
||||
void realtime_handle_transport_stopped ();
|
||||
bool overwrite_existing_buffers ();
|
||||
samplecnt_t get_captured_samples (uint32_t n = 0) const;
|
||||
void transport_looped (samplepos_t);
|
||||
|
|
|
@ -157,6 +157,11 @@ DiskReader::set_state (const XMLNode& node, int version)
|
|||
void
|
||||
DiskReader::realtime_handle_transport_stopped ()
|
||||
{
|
||||
/* can't do the resolve here because we don't have a place to put the
|
||||
* note resolving data. Defer to
|
||||
* MidiTrack::realtime_handle_transport_stopped() which will call
|
||||
* ::resolve_tracker() and put the output in its _immediate_events store.
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -389,7 +394,7 @@ DiskReader::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
|
|||
dst = &bufs.get_midi (0);
|
||||
}
|
||||
|
||||
if ((ms & MonitoringDisk) && !still_locating) {
|
||||
if ((ms & MonitoringDisk) && !still_locating && speed) {
|
||||
get_midi_playback (*dst, start_sample, end_sample, ms, scratch_bufs, speed, disk_samples_to_consume);
|
||||
}
|
||||
}
|
||||
|
@ -511,20 +516,9 @@ DiskReader::overwrite_existing_buffers ()
|
|||
|
||||
if (_playlists[DataType::MIDI]) {
|
||||
|
||||
minsert.reset();minsert.start();
|
||||
minsert.reset(); minsert.start();
|
||||
_mbuf.clear(); midi_playlist()->dump (_mbuf, 0);
|
||||
minsert.update(); cerr << "Reading " << name() << " took " << minsert.elapsed() << " microseconds, final size = " << _mbuf.size() << endl;
|
||||
|
||||
#if 0
|
||||
/* Resolve all currently active notes in the playlist. This is more
|
||||
aggressive than it needs to be: ideally we would only resolve what is
|
||||
absolutely necessary, but this seems difficult and/or impossible without
|
||||
having the old data or knowing what change caused the overwrite.
|
||||
*/
|
||||
midi_playlist()->resolve_note_trackers (*_midi_buf, overwrite_sample);
|
||||
#endif
|
||||
|
||||
file_sample[DataType::MIDI] = overwrite_sample; // overwrite_sample was adjusted by ::midi_read() to the new position
|
||||
}
|
||||
|
||||
g_atomic_int_set (&_pending_overwrite, 0);
|
||||
|
@ -1051,33 +1045,13 @@ DiskReader::move_processor_automation (boost::weak_ptr<Processor> p, list< Evora
|
|||
void
|
||||
DiskReader::reset_tracker ()
|
||||
{
|
||||
#if 0
|
||||
if (_midi_buf) {
|
||||
_midi_buf->reset_tracker ();
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<MidiPlaylist> mp (midi_playlist());
|
||||
|
||||
if (mp) {
|
||||
mp->reset_note_trackers ();
|
||||
}
|
||||
_tracker.reset ();
|
||||
}
|
||||
|
||||
void
|
||||
DiskReader::resolve_tracker (Evoral::EventSink<samplepos_t>& buffer, samplepos_t time)
|
||||
{
|
||||
#if 0
|
||||
if (_midi_buf) {
|
||||
_midi_buf->resolve_tracker(buffer, time);
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<MidiPlaylist> mp (midi_playlist());
|
||||
|
||||
if (mp) {
|
||||
mp->reset_note_trackers ();
|
||||
}
|
||||
_tracker.resolve_notes (buffer, time);
|
||||
}
|
||||
|
||||
/** Writes playback events from playback_sample for nframes to dst, translating time stamps
|
||||
|
@ -1120,7 +1094,7 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample
|
|||
beyond the loop end.
|
||||
*/
|
||||
|
||||
// _midi_buf->resolve_tracker (*target, 0);
|
||||
_tracker.resolve_notes (*target, 0);
|
||||
}
|
||||
|
||||
/* for split-cycles we need to offset the events */
|
||||
|
@ -1143,23 +1117,23 @@ DiskReader::get_midi_playback (MidiBuffer& dst, samplepos_t start_sample, sample
|
|||
if (first) {
|
||||
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("loop read #1, from %1 for %2\n",
|
||||
effective_start, first));
|
||||
events_read = _mbuf.read (*target, effective_start, effective_start + first);
|
||||
events_read = _mbuf.read (*target, effective_start, effective_start + first, _tracker);
|
||||
}
|
||||
|
||||
if (second) {
|
||||
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("loop read #2, from %1 for %2\n",
|
||||
loc->start(), second));
|
||||
events_read += _mbuf.read (*target, loc->start(), loc->start() + second);
|
||||
events_read += _mbuf.read (*target, loc->start(), loc->start() + second, _tracker);
|
||||
}
|
||||
|
||||
} else {
|
||||
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("loop read #3, adjusted start as %1 for %2\n",
|
||||
effective_start, nframes));
|
||||
events_read = _mbuf.read (*target, effective_start, effective_start + nframes);
|
||||
events_read = _mbuf.read (*target, effective_start, effective_start + nframes, _tracker);
|
||||
}
|
||||
} else {
|
||||
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("playback buffer read, from %1 to %2 (%3)", start_sample, end_sample, nframes));
|
||||
events_read = _mbuf.read (*target, start_sample, end_sample, Port::port_offset ());
|
||||
events_read = _mbuf.read (*target, start_sample, end_sample, _tracker, Port::port_offset ());
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::MidiDiskIO, string_compose ("%1 MDS events read %2 range %3 .. %4\n", _name, events_read, playback_sample, playback_sample + nframes));
|
||||
|
|
|
@ -288,20 +288,6 @@ MidiBuffer::write(TimeType time, Evoral::EventType type, uint32_t size, const ui
|
|||
return size;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MidiBuffer::append(TimeType time, Evoral::EventType type, uint32_t size, const uint8_t* buf)
|
||||
{
|
||||
const size_t bytes_to_merge = sizeof(TimeType) + size;
|
||||
|
||||
if (_size + bytes_to_merge >= _capacity) {
|
||||
resize (_capacity + 8192);
|
||||
}
|
||||
|
||||
return push_back (time, size, buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Reserve space for a new event in the buffer.
|
||||
*
|
||||
* This call is for copying MIDI directly into the buffer, the data location
|
||||
|
|
|
@ -360,7 +360,7 @@ MidiTrack::realtime_locate ()
|
|||
(*i)->realtime_locate ();
|
||||
}
|
||||
|
||||
_disk_reader->reset_tracker ();
|
||||
_disk_reader->resolve_tracker (_immediate_events, Port::port_offset());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -864,3 +864,10 @@ MidiTrack::filter_input (BufferSet& bufs)
|
|||
{
|
||||
_capture_filter.filter (bufs);
|
||||
}
|
||||
|
||||
void
|
||||
MidiTrack::realtime_handle_transport_stopped ()
|
||||
{
|
||||
Route::realtime_handle_transport_stopped ();
|
||||
_disk_reader->resolve_tracker (_immediate_events, Port::port_offset());
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include "ardour/debug.h"
|
||||
#include "ardour/midi_buffer.h"
|
||||
#include "ardour/midi_state_tracker.h"
|
||||
#include "ardour/rt_midibuffer.h"
|
||||
|
||||
using namespace std;
|
||||
|
@ -74,6 +75,26 @@ RTMidiBuffer::resize (size_t size)
|
|||
assert(_data);
|
||||
}
|
||||
|
||||
void
|
||||
RTMidiBuffer::dump (uint32_t cnt)
|
||||
{
|
||||
for (Map::iterator iter = _map.begin(); iter != _map.end() && cnt; ++iter, --cnt) {
|
||||
|
||||
uint8_t* addr = &_data[iter->second];
|
||||
TimeType evtime = iter->first;
|
||||
uint32_t size = *(reinterpret_cast<Evoral::EventType*>(addr));
|
||||
addr += sizeof (size);
|
||||
|
||||
cerr << "@ " << evtime << " sz=" << size << '\t';
|
||||
|
||||
cerr << hex;
|
||||
for (size_t i =0 ; i < size; ++i) {
|
||||
cerr << "0x" << hex << (int)addr[i] << dec << '/' << (int)addr[i] << ' ';
|
||||
}
|
||||
cerr << dec << endl;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RTMidiBuffer::write (TimeType time, Evoral::EventType /*type*/, uint32_t size, const uint8_t* buf)
|
||||
{
|
||||
|
@ -99,7 +120,7 @@ RTMidiBuffer::write (TimeType time, Evoral::EventType /*type*/, uint32_t size, c
|
|||
}
|
||||
|
||||
uint32_t
|
||||
RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, samplecnt_t offset)
|
||||
RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiStateTracker& tracker, samplecnt_t offset)
|
||||
{
|
||||
Map::iterator iter = _map.lower_bound (start);
|
||||
uint32_t count = 0;
|
||||
|
@ -142,6 +163,7 @@ RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, samplec
|
|||
DEBUG_TRACE (DEBUG::MidiRingBuffer, string_compose ("read event sz %1 @ %2\n", size, unadjusted_time));
|
||||
|
||||
memcpy (write_loc, addr, size);
|
||||
tracker.track (addr);
|
||||
|
||||
++iter;
|
||||
++count;
|
||||
|
|
Loading…
Reference in New Issue