mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-17 04:06:26 +01:00
Fix lost MIDI note offs and controllers.
Fix initial read of discrete MIDI controllers. Fix spurious note offs when starting to play in the middle of a note. Faster search for initial event when cached iterator is invalid. So much for dropping the cached iterator. The iterator is responsible for handling note offs, so that doesn't work. This design means we have some stuck note issues at the source read level, but they should be taken care of by the state tracker anyway.
This commit is contained in:
parent
8bba63282a
commit
4bc0d1c475
6 changed files with 59 additions and 13 deletions
|
|
@ -56,7 +56,9 @@ PBD::Signal1<void,MidiSource*> MidiSource::MidiSourceCreated;
|
|||
MidiSource::MidiSource (Session& s, string name, Source::Flag flags)
|
||||
: Source(s, DataType::MIDI, name, flags)
|
||||
, _writing(false)
|
||||
, _model_iter_valid(false)
|
||||
, _length_beats(0.0)
|
||||
, _last_read_end(0)
|
||||
, _capture_length(0)
|
||||
, _capture_loop_length(0)
|
||||
{
|
||||
|
|
@ -65,7 +67,9 @@ MidiSource::MidiSource (Session& s, string name, Source::Flag flags)
|
|||
MidiSource::MidiSource (Session& s, const XMLNode& node)
|
||||
: Source(s, node)
|
||||
, _writing(false)
|
||||
, _model_iter_valid(false)
|
||||
, _length_beats(0.0)
|
||||
, _last_read_end(0)
|
||||
, _capture_length(0)
|
||||
, _capture_loop_length(0)
|
||||
{
|
||||
|
|
@ -169,6 +173,13 @@ MidiSource::update_length (framecnt_t)
|
|||
// You're not the boss of me!
|
||||
}
|
||||
|
||||
void
|
||||
MidiSource::invalidate ()
|
||||
{
|
||||
_model_iter_valid = false;
|
||||
_model_iter.invalidate();
|
||||
}
|
||||
|
||||
framecnt_t
|
||||
MidiSource::midi_read (Evoral::EventSink<framepos_t>& dst,
|
||||
framepos_t source_start,
|
||||
|
|
@ -186,11 +197,18 @@ MidiSource::midi_read (Evoral::EventSink<framepos_t>& dst,
|
|||
source_start, start, cnt, tracker, name()));
|
||||
|
||||
if (_model) {
|
||||
// Read events up to end
|
||||
const double start_beats = converter.from(start);
|
||||
for (Evoral::Sequence<double>::const_iterator i = _model->begin(start_beats, false, filtered);
|
||||
i != _model->end();
|
||||
++i) {
|
||||
// Find appropriate model iterator
|
||||
Evoral::Sequence<double>::const_iterator& i = _model_iter;
|
||||
if (_last_read_end == 0 || start != _last_read_end || !_model_iter_valid) {
|
||||
// Cached iterator is invalid, search for the first event past start
|
||||
i = _model->begin(converter.from(start), false, filtered);
|
||||
_model_iter_valid = true;
|
||||
}
|
||||
|
||||
_last_read_end = start + cnt;
|
||||
|
||||
// Copy events in [start, start + cnt) into dst
|
||||
for (; i != _model->end(); ++i) {
|
||||
const framecnt_t time_frames = converter.to(i->time());
|
||||
if (time_frames < start + cnt) {
|
||||
// Offset by source start to convert event time to session time
|
||||
|
|
@ -225,7 +243,10 @@ MidiSource::midi_write (MidiRingBuffer<framepos_t>& source,
|
|||
|
||||
const framecnt_t ret = write_unlocked (source, source_start, cnt);
|
||||
|
||||
if (cnt != max_framecnt) {
|
||||
if (cnt == max_framecnt) {
|
||||
_last_read_end = 0;
|
||||
invalidate();
|
||||
} else {
|
||||
_capture_length += cnt;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue