fix #293733: If note is tied to preceding grace note of equal pitch, only the grace note is played back

Why this is happening

In collectNote() in rendermidi.cpp, grace notes are currently not treated as notes that could potentially have forward ties; in fact, it is assumed that they will not. When a note is encountered that ties back to a previous note, it is assumed that the length of the note has already been added to the previous note, when in fact this is not the case if the previous note is a grace note.

Why this commit fixes the issue

The code for computing the entire length of the tie chain is now executed whether the current note is a grace note or not.
This commit is contained in:
Matt McClinch 2019-08-28 08:17:51 -04:00
parent 3d4488323c
commit e98b0edd1d

View file

@ -253,35 +253,31 @@ static void collectNote(EventMap* events, int channel, const Note* note, int vel
if (chord->isGrace()) {
Q_ASSERT( !graceNotesMerged(chord)); // this function should not be called on a grace note if grace notes are merged
chord = toChord(chord->parent());
ticks = chord->actualTicks().ticks(); // ticks of the parent note
tieLen = 0;
}
else {
ticks = chord->actualTicks().ticks(); // ticks of the actual note
// calculate additional length due to ties forward
// taking NoteEvent length adjustments into account
// but stopping at any note with multiple NoteEvents
// and processing those notes recursively
if (note->tieFor()) {
Note* n = note->tieFor()->endNote();
while (n) {
NoteEventList nel = n->playEvents();
if (nel.size() == 1) {
// add value of this note to main note
// if we wish to suppress first note of ornament,
// then do this regardless of number of NoteEvents
tieLen += (n->chord()->actualTicks().ticks() * (nel[0].len())) / 1000;
}
else {
// recurse
collectNote(events, channel, n, velo, tickOffset, staffIdx);
break;
}
if (n->tieFor() && n != n->tieFor()->endNote())
n = n->tieFor()->endNote();
else
break;
ticks = chord->actualTicks().ticks();
// calculate additional length due to ties forward
// taking NoteEvent length adjustments into account
// but stopping at any note with multiple NoteEvents
// and processing those notes recursively
if (note->tieFor()) {
Note* n = note->tieFor()->endNote();
while (n) {
NoteEventList nel = n->playEvents();
if (nel.size() == 1) {
// add value of this note to main note
// if we wish to suppress first note of ornament,
// then do this regardless of number of NoteEvents
tieLen += (n->chord()->actualTicks().ticks() * (nel[0].len())) / 1000;
}
else {
// recurse
collectNote(events, channel, n, velo, tickOffset, staffIdx);
break;
}
if (n->tieFor() && n != n->tieFor()->endNote())
n = n->tieFor()->endNote();
else
break;
}
}