View Issue Details

IDProjectCategoryView StatusLast Update
0006192ardourbugspublic2015-03-04 23:20
Reportertlat Assigned To 
PrioritynormalSeveritymajorReproducibilityalways
Status newResolutionopen 
Summary0006192: second MIDI event ignored after save-session and play
DescriptionExample:

0) new midi track (select a sustained instrument to hear the problem)

1) a sequence of three notes is enough

   - put the first note at position zero to simplify the test

   - the duration of the first note is >= `midi_readahead'
     (one second in my case)

2) go to zero

3) save session

4) play


After (2) we have:

DEBUG::Sequence: Created Iterator @ 0 (is end: 0)
)DEBUG::Sequence: iterator = note on
DEBUG::Sequence: Starting at type 0x222 : 0x144 @ 0
DEBUG::MidiSourceIO: MIDI 1-1.mid: add event @ 0 type 222 size 3
DEBUG::Sequence: iterator = note off
DEBUG::MidiSourceIO: MIDI 1-1.mid: reached end with event @ 48000 vs. 48000


(the typo ")DEBUG" is in `libs/evoral/src/Sequence.cpp:86')

The first note-on is added to the MIDI buffer. If we play without
save-session, the result is

DEBUG::MidiSourceIO: MIDI 1-1.mid: add event @ 48000 type 173 size 3


and there aren't problems because the note-off is also added to the buffer.

However, if we save the session after (2), the result during playback is

DEBUG::Sequence: Created Iterator @ 2 (is end: 0)
)DEBUG::Sequence: iterator = note on
DEBUG::Sequence: Starting at type 0x222 : 0x144 @ 5
DEBUG::MidiSourceIO: MIDI 1-1.mid: reached end with event @ 120000 vs. 50048


and the first note-off is lost.

In practice, after save-session and play, if the first two events of a
sequence occur before `start', the playback is correct, otherwise the
second event is lost.

In my test, the first cnt for `MidiSource::midi_read' is 48000 and
it is related to `midi_readahead':

  MidiDiskstream::set_readahead_frames ((framecnt_t) (Config->get_midi_readahead() * rate));

(I'm using Jack)

The successive durations are

   midi_readahead - (frames_written - frames_read)

and this value is 2048 in my case.

After stop (or a generic request_locate), cnt is again 48000.

It works without save-session, because the cached iterator in
MidiSource::midi_read is valid when `start' is 48000 (_last_read_end
is equal to `start' and _model_iter_valid is true).

It fails with goto-zero and save-session, because _model_iter_valid
is false after `invalidate' and the iterator in MidiSource::midi_read

    i = _model->begin(converter.from(start), false, filtered);

is updated with the first event past one second (start = 48000),
but it consumes two events and the second is called "sub-iterator"
(see Sequence<Time>::const_iterator). In the example, the event
before the sub-iterator is the skipped note-off.

A possible solution is to cache (or check) the time of the event that
precedes the sub-iterator when

    converter.to(i->time()) >= start

If the time of the previous event is minor than `start', it is not
necessary to update `i'.
TagsNo tags attached.

Activities

There are no notes attached to this issue.

Issue History

Date Modified Username Field Change
2015-03-04 23:20 tlat New Issue