From e6915e01de2e2167c3384c6c8f2408f763971616 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 18 Sep 2018 18:51:59 -0400 Subject: new transport slave/master implementation, libs/ edition --- libs/ardour/midi_port.cc | 189 ++++++++++++++++++++++++----------------------- 1 file changed, 98 insertions(+), 91 deletions(-) (limited to 'libs/ardour/midi_port.cc') diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index dfc1c37e87..f8259c8917 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -37,11 +37,10 @@ using namespace PBD; MidiPort::MidiPort (const std::string& name, PortFlags flags) : Port (name, DataType::MIDI, flags) - , _has_been_mixed_down (false) , _resolve_required (false) , _input_active (true) - , _always_parse (false) - , _trace_on (false) + , _trace_parser (0) + , _data_fetched_for_cycle (false) { _buffer = new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)); } @@ -57,10 +56,13 @@ MidiPort::~MidiPort() } void -MidiPort::cycle_start (pframes_t nframes) +MidiPort::parse_input (pframes_t nframes, MIDI::Parser& parser) { - samplepos_t now = AudioEngine::instance()->sample_time_at_cycle_start(); +} +void +MidiPort::cycle_start (pframes_t nframes) +{ Port::cycle_start (nframes); _buffer->clear (); @@ -69,22 +71,8 @@ MidiPort::cycle_start (pframes_t nframes) port_engine.midi_clear (port_engine.get_buffer (_port_handle, nframes)); } - if (_always_parse || (receives_input() && _trace_on)) { - MidiBuffer& mb (get_midi_buffer (nframes)); - - /* dump incoming MIDI to parser */ - - for (MidiBuffer::iterator b = mb.begin(); b != mb.end(); ++b) { - uint8_t* buf = (*b).buffer(); - - _self_parser.set_timestamp (now + (*b).time()); - - uint32_t limit = (*b).size(); - - for (size_t n = 0; n < limit; ++n) { - _self_parser.scanner (buf[n]); - } - } + if (receives_input() && _trace_parser) { + read_and_parse_entire_midi_buffer_with_no_speed_adjustment (nframes, *_trace_parser, AudioEngine::instance()->sample_time_at_cycle_start()); } if (inbound_midi_filter) { @@ -101,80 +89,64 @@ MidiPort::cycle_start (pframes_t nframes) } -Buffer& -MidiPort::get_buffer (pframes_t nframes) -{ - return get_midi_buffer (nframes); -} - MidiBuffer & MidiPort::get_midi_buffer (pframes_t nframes) { - if (_has_been_mixed_down) { + if (_data_fetched_for_cycle) { return *_buffer; } - if (receives_input ()) { - - if (_input_active) { + if (receives_input () && _input_active) { - void* buffer = port_engine.get_buffer (_port_handle, nframes); - const pframes_t event_count = port_engine.get_midi_event_count (buffer); + void* buffer = port_engine.get_buffer (_port_handle, nframes); + const pframes_t event_count = port_engine.get_midi_event_count (buffer); - /* suck all relevant MIDI events from the MIDI port buffer - into our MidiBuffer - */ + /* suck all MIDI events for this cycle of nframes from + the MIDI port buffer into our MidiBuffer. + */ - for (pframes_t i = 0; i < event_count; ++i) { + for (pframes_t i = 0; i < event_count; ++i) { - pframes_t timestamp; - size_t size; - uint8_t const* buf; + pframes_t timestamp; + size_t size; + uint8_t const* buf; - port_engine.midi_event_get (timestamp, size, &buf, buffer, i); + port_engine.midi_event_get (timestamp, size, &buf, buffer, i); - if (buf[0] == 0xfe) { - /* throw away active sensing */ - continue; - } + if (buf[0] == 0xfe) { + /* throw away active sensing */ + continue; + } - timestamp = floor (timestamp * _speed_ratio); + timestamp = floor (timestamp * _speed_ratio); - /* check that the event is in the acceptable time range */ - if ((timestamp < (_global_port_buffer_offset)) || - (timestamp >= (_global_port_buffer_offset + nframes))) { - // XXX this is normal after a split cycles: - // The engine buffer contains the data for the complete cycle, but - // only the part after _global_port_buffer_offset is needed. + /* check that the event is in the acceptable time range */ + if ((timestamp < (_global_port_buffer_offset)) || + (timestamp >= (_global_port_buffer_offset + nframes))) { + // XXX this is normal after a split cycles: + // The engine buffer contains the data for the complete cycle, but + // only the part after _global_port_buffer_offset is needed. #ifndef NDEBUG - cerr << "Dropping incoming MIDI at time " << timestamp << "; offset=" - << _global_port_buffer_offset << " limit=" - << (_global_port_buffer_offset + nframes) - << " = (" << _global_port_buffer_offset - << " + " << nframes - << ")\n"; + cerr << "Dropping incoming MIDI at time " << timestamp << "; offset=" + << _global_port_buffer_offset << " limit=" + << (_global_port_buffer_offset + nframes) + << " = (" << _global_port_buffer_offset + << " + " << nframes + << ")\n"; #endif - continue; - } - - /* adjust timestamp to match current cycle */ - timestamp -= _global_port_buffer_offset; - assert (timestamp < nframes); - - if ((buf[0] & 0xF0) == 0x90 && buf[2] == 0) { - /* normalize note on with velocity 0 to proper note off */ - uint8_t ev[3]; - ev[0] = 0x80 | (buf[0] & 0x0F); /* note off */ - ev[1] = buf[1]; - ev[2] = 0x40; /* default velocity */ - _buffer->push_back (timestamp, size, ev); - } else { - _buffer->push_back (timestamp, size, buf); - } + continue; } - } else { - _buffer->silence (nframes); + if ((buf[0] & 0xF0) == 0x90 && buf[2] == 0) { + /* normalize note on with velocity 0 to proper note off */ + uint8_t ev[3]; + ev[0] = 0x80 | (buf[0] & 0x0F); /* note off */ + ev[1] = buf[1]; + ev[2] = 0x40; /* default velocity */ + _buffer->push_back (timestamp, size, ev); + } else { + _buffer->push_back (timestamp, size, buf); + } } } else { @@ -182,22 +154,63 @@ MidiPort::get_midi_buffer (pframes_t nframes) } if (nframes) { - _has_been_mixed_down = true; + _data_fetched_for_cycle = true; } return *_buffer; } +void +MidiPort::read_and_parse_entire_midi_buffer_with_no_speed_adjustment (pframes_t nframes, MIDI::Parser& parser, samplepos_t now) +{ + 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) { + + 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; + } + + parser.set_timestamp (now + timestamp); + + /* During this parsing stage, signals will be emitted from the + * Parser, which will update anything connected to it. + * + * As of July 2018, this is only used by TransportMasters which + * read MIDI before the process() cycle really gets started. + */ + + if ((buf[0] & 0xF0) == 0x90 && buf[2] == 0) { + /* normalize note on with velocity 0 to proper note off */ + parser.scanner (0x80 | (buf[0] & 0x0F)); /* note off */ + parser.scanner (buf[1]); + parser.scanner (0x40); /* default (off) velocity */ + } else { + for (size_t n = 0; n < size; ++n) { + parser.scanner (buf[n]); + } + } + } +} + void MidiPort::cycle_end (pframes_t /*nframes*/) { - _has_been_mixed_down = false; + _data_fetched_for_cycle = false; } void MidiPort::cycle_split () { - _has_been_mixed_down = false; + _data_fetched_for_cycle = false; } void @@ -253,16 +266,16 @@ MidiPort::flush_buffers (pframes_t nframes) const Evoral::Event ev (*i, false); - if (sends_output() && _trace_on) { + if (sends_output() && _trace_parser) { uint8_t const * const buf = ev.buffer(); const samplepos_t now = AudioEngine::instance()->sample_time_at_cycle_start(); - _self_parser.set_timestamp (now + ev.time()); + _trace_parser->set_timestamp (now + ev.time()); uint32_t limit = ev.size(); for (size_t n = 0; n < limit; ++n) { - _self_parser.scanner (buf[n]); + _trace_parser->scanner (buf[n]); } } @@ -347,15 +360,9 @@ MidiPort::set_input_active (bool yn) } void -MidiPort::set_always_parse (bool yn) -{ - _always_parse = yn; -} - -void -MidiPort::set_trace_on (bool yn) +MidiPort::set_trace (MIDI::Parser * p) { - _trace_on = yn; + _trace_parser = p; } int -- cgit v1.2.3