From 4749fcef86ac572960ea5ecd1ce502ecd5b7e846 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 24 Feb 2020 18:44:45 -0700 Subject: fix incorrect handling of MIDI data by AsyncMIDIPort This type of MIDI port fetches all of its data from inside ::cycle_start(), and delivers it to a FIFO connected to another thread (typically a control surface). Unlike regular MidiPorts, which will be read from inside a Session::process() call, these ports will read their data once per AudioEngine::process() cycle. They therefore cannot use MidiPort::get_midi_buffer() which scales and adjusts event timestamps as if the data is being accessed from within Session::process(). It is still an open question whether or not AsyncMIDIPort::cycle_start() should still scale event timestamps by speed. In some respects it seems more appropriate to do so, and the reading thread (e.g. a control surface) doesn't care about the "nframes" limit on timestamps that exists for calls within a Session::process() tree. For now, leave the timestamps unscaled by speed. --- libs/ardour/async_midi_port.cc | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/libs/ardour/async_midi_port.cc b/libs/ardour/async_midi_port.cc index 1e898764d2..06a51279fe 100644 --- a/libs/ardour/async_midi_port.cc +++ b/libs/ardour/async_midi_port.cc @@ -131,23 +131,35 @@ AsyncMIDIPort::cycle_start (MIDI::pframes_t nframes) */ if (ARDOUR::Port::receives_input()) { - MidiBuffer& mb (get_midi_buffer (nframes)); - samplecnt_t when; - if (have_timer) { - when = timer (); - } else { - when = AudioEngine::instance()->sample_time_at_cycle_start(); - } + void* buffer = port_engine.get_buffer (_port_handle, nframes); + const pframes_t event_count = port_engine.get_midi_event_count (buffer); + + for (pframes_t i = 0; i < event_count; ++i) { - for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) { - if (!have_timer) { - when += (*b).time(); + pframes_t timestamp; + size_t size; + uint8_t const* buf; + + port_engine.midi_event_get (timestamp, size, &buf, buffer, i); + + if (buf[0] == 0xfe) { + /* throw away active sensing */ + continue; } - input_fifo.write (when, Evoral::NO_EVENT, (*b).size(), (*b).buffer()); + + samplecnt_t when; + + if (have_timer) { + when = timer (); + } else { + when = AudioEngine::instance()->sample_time_at_cycle_start() + timestamp; + } + + input_fifo.write (when, Evoral::NO_EVENT, size, buf); } - if (!mb.empty()) { + if (event_count) { _xthread.wakeup (); } @@ -346,4 +358,3 @@ AsyncMIDIPort::is_process_thread() { return pthread_equal (pthread_self(), _process_thread); } - -- cgit v1.2.3