summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2019-11-03 15:18:04 +0100
committerRobin Gareus <robin@gareus.org>2019-11-03 15:19:37 +0100
commit2fde6a5777694c454d102c7fa1bd9ea594d4db2b (patch)
treee0d774c36fe9dc1ce23f23a7cbd2497be51cccfd
parent98224a264ec53c5c3488e3507ed3ce7b138820c1 (diff)
Correctly flush MIDI buffers on cycle-split
-rw-r--r--libs/ardour/audioengine.cc28
-rw-r--r--libs/ardour/midi_port.cc3
-rw-r--r--libs/ardour/port_manager.cc4
3 files changed, 33 insertions, 2 deletions
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 69418c1911..c7e4efa1d1 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -146,11 +146,37 @@ AudioEngine::split_cycle (pframes_t offset)
{
/* caller must hold process lock */
+ boost::shared_ptr<Ports> p = ports.reader();
+
+ /* This is mainly for the benefit of rt-control ports (MTC, MClk)
+ *
+ * Normally ports are flushed by the route:
+ * ARDOUR::MidiPort::flush_buffers(unsigned int)
+ * ARDOUR::Delivery::flush_buffers(long)
+ * ARDOUR::Route::flush_processor_buffers_locked(long)
+ * ARDOUR::Route::run_route(long, long, unsigned int, bool, bool)
+ * ...
+ *
+ * This is required so that route -> route connections work during
+ * normal processing.
+ *
+ * However some non-route ports may contain MIDI events
+ * from current Port::port_offset() .. Port::port_offset() + offset.
+ * If those events are not pushed to ports before the cycle split,
+ * MidiPort::flush_buffers will drop them (event time is out of bounds).
+ *
+ * TODO: for optimized builds MidiPort::flush_buffers() could
+ * be relaxed, ignore ev->time() checks, and simply send
+ * all events as-is.
+ */
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
+ i->second->flush_buffers (offset);
+ }
+
Port::increment_global_port_buffer_offset (offset);
/* tell all Ports that we're going to start a new (split) cycle */
- boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
i->second->cycle_split ();
diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc
index d22673fe72..7eed2ef468 100644
--- a/libs/ardour/midi_port.cc
+++ b/libs/ardour/midi_port.cc
@@ -308,6 +308,9 @@ MidiPort::flush_buffers (pframes_t nframes)
}
#endif
+ // XXX consider removing this check for optimized builds
+ // and just send 'em all, at cycle_end
+ // see AudioEngine::split_cycle (), PortManager::cycle_end()
if ( ev.time() >= _global_port_buffer_offset
&& ev.time() < _global_port_buffer_offset + nframes) {
pframes_t tme = floor (ev.time() / _speed_ratio);
diff --git a/libs/ardour/port_manager.cc b/libs/ardour/port_manager.cc
index 24c693c431..8be1f7f7e9 100644
--- a/libs/ardour/port_manager.cc
+++ b/libs/ardour/port_manager.cc
@@ -845,7 +845,9 @@ PortManager::cycle_end (pframes_t nframes, Session* s)
}
for (Ports::iterator p = _cycle_ports->begin(); p != _cycle_ports->end(); ++p) {
- p->second->flush_buffers (nframes);
+ /* AudioEngine::split_cycle flushes buffers until Port::port_offset.
+ * Now only flush remaining events (after Port::port_offset) */
+ p->second->flush_buffers (nframes - Port::port_offset ());
}
_cycle_ports.reset ();