Corruption pasting into a sequence that ends in the middle of a tuplet

• Mar 29, 2015 - 18:20
Type
Functional
Severity
S2 - Critical
Status
closed
Project

If I copy a sequence of notes and paste into another portion of the score such that the copied sequence ends in the middle of a tuplet in the paste target, I get an erroneous number of beats. See the attached simple example. To produce it: Enter the notes in staff one. Enter the notes in staff 2. Copy staff 2 into staff 3. Now copy the quarter note and eighth note from staff one (but not the rests), select the first quarter note of staff 3, and paste. This will produce the result shown for staff 3, which is missing 1/6 of a beat. This is for nightly 2015-03-27-1017-a249aea on Mac OS X; same happens for the released 2.0.

By the way, if one inputs the example as shown above and attempts to save the score, MuseScore Nightly crashes. Released MuseScore 2.0 does not, it produces a .mscz file, which if I attempt to re-open, produces a "file corrupted" error message, but if I click "ignore", will open and get me back to where I was.

MuseScore attempts to exclude errors like this by forbidding pastes into targets that start in a tuplet. But a problem with the adopted approach is that it arbitrarily rejects pasting some material into a note in the tuplet, but not a longer sequence that ends with the identical copied material and the identical paste target as subsets. So I would think that any musically illegal operation that has been excluded by the "can't paste into tuplets" rule can still be made to happen. Also the restriction on pasting into a triplet excludes quite legitimate operations (e.g. pasting lyrics, or replacing a triplet of eighth notes by a pasted sequence of two ordinary eighth notes.)

Attachment Size
tripletpaste.pdf 30.52 KB

Comments

EDIT: I'm struggling to think of an example that justifies forbidding pasting into triplets (the current MuseScore restriction). It seems to me there is always a correct (if awkward) result from any such paste. In the example I included, the proper fix is to introduce a 1/6-beat rest -- So in staff 3, following the eighth-note B, there should be a half-beat triplet (what you would enter by selecting an eighth note, then the "triplet" option), consisting of a 16th note rest followed by the eighth note F, with the triplet beam over that combination. This would of course be a valid result even for the now forbidden operation of just copying the eighth note from staff one and pasting into the first triplet of staff 2.

Try pasting a half note into the second note of an eighth-note triplet. I think the idea is to make sure we don't break up tuplets - they are copied or replaced as a whole or not at all.

In your example, yes, it would be possible to create a "1/6 rest", but that's complicated to figure out and may be impossible in the more general case (nested tuplets, tuplets that are not simple multiples of 3, etc.

I can reproduce a corruption from the same root cause without use of copy and paste:

1) 4/4 score
2) enter half note followed by quarter note triplets (6 C Ctrl+3 D E F)
3) exit note entry mode
4) select the half note
5) press "."

Result: corrupt measure.

Here's what it looks like before step 5:

tuplet-1.png

And here is how it looks after:

tuplet-2.png

The last note should be a plain quarter note, but it shows as part of a triplet. It's the same corruption that would have resulted from trying to paste a dotted half into that measure.

I have identified the problem as stemming from here:

https://github.com/musescore/MuseScore/blob/master/libmscore/cmd.cpp#L7…

At this point we have already deleted the complete tuplet, but we realized that was too much, so we are trying to add a beat back. We are doing this by cloning the first note of the tuplet - which adds a note that thinks it is part of a tuplet even though it should not be. I propose adding back rests in this case.

Another related issue happens if we take the above example but this time, after step 3, click the first note of the triplet, and press Ctrl+3 to split it a nested eighth note triplets, which yields the following:

tuplet-nested-1.png

At this point, if try to add a dot to the half note, the full inner tuplet is deleted, and because it adds up to a quarter note duration (even though it is not really a full beat), the code thinks it has cleared enough space, so it leaves the rest of the outer triplet in place:

tuplet-nested-2.png

This is a a separate issue - we are not correctly counting the length of the inner tuplet. I tried using globalDuration() instead of duration(), and it helped, but things were off elsewhere. I have a feeling that isn't going to work - we really do need to delete the full complete tuplet from the top.

I have fixes I am testing for both of these issues, but frankly, it's a bit scary, as I know this code is called in a number of different contexts and it feels like there might be cases where my changes could result in tuplets being deleted in cases where they shouldn't. On the other hand, these corruptions are not good either. I hope to be submitting a PR shortly, but it will will definitely be something we want to look at closely.

Where you say "The last note should be a plain quarter note, but it shows as part of a triplet"—not only that, but it should be the last note of the triplet (an A), but instead it's the first note (an F). Just an observation.

Zack - yes, I did notice it's the wrong note. Kind of unavoidable that we don't know which note(s) to keep, since things don't line up exactly, so my fix actually just fill the rest of the space with rests. Meaning that with my fix, you will get a quarter rest on beat 4 in both of those cases.