cmdSplitMeasure() must break notes in other Voices using toDurationList()
I seems to have make a segfault with #183846: Splitting irregular measures produce extra rests (I need to verify this, though). If I split measure before the selected 16th rest:
Then segfault:
1 raise 0x7fffee8dfa10 2 abort 0x7fffee8e113a 3 QMessageLogger::fatal(const char *, ...) const 0x7fffef282e21 4 qt_assert(const char *, const char *, int) 0x7fffef27e3de 5 Ms::TDuration::TDuration durationtype.cpp 422 0x11991a4 6 Ms::TrackList::write range.cpp 384 0x13a1cea 7 Ms::ScoreRange::write range.cpp 552 0x13a2be8 8 Ms::Score::cmdSplitMeasure splitMeasure.cpp 49 0x13a77e0 9 Ms::ScoreView::cmd scoreview.cpp 3130 0xa53a54 10 Ms::MuseScore::cmd musescore.cpp 4685 0xbbce60 11 Ms::MuseScore::cmd musescore.cpp 4287 0xbbaa7a 12 Ms::MuseScore::qt_static_metacall moc_musescore_IKSZSQWDH4YDZS.cpp 734 0x10151e5 13 QMetaObject::activate(QObject *, int, int, void * *) 0x7fffef4a2d49 14 Ms::ScoreTab::actionTriggered moc_scoretab_QR4BWIRYNXAVBM.cpp 195 0x101c6d9 15 Ms::ScoreTab::qt_static_metacall moc_scoretab_QR4BWIRYNXAVBM.cpp 97 0x101c2e4 16 QMetaObject::activate(QObject *, int, int, void * *) 0x7fffef4a2d49 17 QActionGroup::triggered(QAction *) 0x7ffff01564ff 18 ?? 0x7ffff0157079 19 QMetaObject::activate(QObject *, int, int, void * *) 0x7fffef4a2d49 20 QAction::triggered(bool) 0x7ffff0152c92 ...
Let me investigate right now...
Comments
Well the attached:
Works in both 2.1-dev 5104373 (which has my commit) and 2.1-dev 1ffaed2 (the previous commit before my commit). So maybe I didn't break it. Maybe I need to type the score exactly according to the screenshot.
never mind :(
Ok, I figured out that the issue is not a *SegFault*, but rather is a Q_ASSERT failure, which only occurs when run on a *debug build*.
in that assert for my earlier attached example:
fraction() is a half note.
l is 11/16
Therefore fraction() - l doesn't evaluate to zero...so isn't an exact fit.
Note that the assert failure is still present on d4ea2418aacc2dfc100bad5993ddcd2588c83d6c which was the commit before maxDots changed from 4 into 3.
I am noting that on latest 2.1 commit, there is no assert failure when splitting before the dotted eight, or splitting before the first eight rest, but only when splitting before the sixteenth rest.
I am noting that a score with just the first measure will case the assert failure:
split184061-one-measure.mxl
Although if I remove the whole note in voice 2, then there is no longer an assert failure:
split184061-one-measure-one-voice.mscx
I am noting that the assert failure happens when there is a whole *note* rest in voice 2
split184061-one-measure-whole-note-voice-2.mscx
But doesn't happen when there is a whole *rest* in voice 2.
split184061-one-measure-whole-rest-voice-2.mscx
There is an actual bug, since the result in 2.1-nightly ae09a44:
splits the whole note into only a half note and a quarter note...which do not fill entire duration of whole note. Neither of the resulting notes fill their entire measure.
I'm changing variable name Fraction "rest" in TrackList::write to "remaining", because it appears to represent that reamining time in the measure being written to. "rest" is just confusing because a Rest is something different.
"Rest" is German for "remainder" :-)
:-) ok...that is pretty humorous, I will admit.
I think I'll still change it to "remainder" for less ambiguity.
And the German word for rest means pause :-)
It's very confusing.
I'm trying to figure out why TrackList::write will break up rests according to toDurationList:
But doesn't use toDurationList for breaking up chords, and instead just sets duration of note to d (the minimum of what is remaining in the measure and the duration of the note being split up:
I think should use toDurationlist for both cases, to handle note duration which can't be easily split up into two smaller durations.
Two tests:
split184061-no-tie:
when split 11/16 through becomes:
and split184061-keep-tie:
when split 11/16 through becomes:
The strange thing is those test work from inside mscore, but the second one is not working from inside mtest because it is not copying that final quarter note when it saves the file for comparison. So I need to look into that. But other than that, I'm sharing my changes for others to comment before I make some more tests and submit PR:
https://github.com/musescore/MuseScore/compare/2.1...ericfont:184061-Sp…
Turns out I had to add score->doLayout() to the test in order for that quarter note to actually become a segment in the initial score. I don't quite understand why that is necessary, to be honest.
I made a PR: https://github.com/musescore/MuseScore/pull/3108
I might add some more tests later. I do have a test which results in triple-dots...I hope that is ok:
When split becomes:
Actually I'd better readjust that last test so it doesn't have any rests, because the problem is split measure undoes the rest organization, but there is another feature request that says should instead try to preserve as much of repeats organization before and after the split.
Anyway I'd appreciate any suggestions about what strange behavior to test. I'm wondering if we allow to split measures where one or more instruments have a measure rest. I would think measure rests are unbreakable, so maybe we need to prohibit that...
I put in the feature request #166096: Make individual beat rests when splitting a measure because when you split a measure on a multi instrument score and fewer than all of the instruments have notes, those who do not have notes have no way of knowing that the measure has been shortened if there are measure rests in both measures, or actually either measure. This will put a human off on his count to reenter the song. It is normal that if a measure has fewer than a whole measure's rest, the rests are indicated with the correct count. The song that I noticed this on was in 3/4 time that started with a pickup of 1 beat. There was a repeat after beat 2 of the last measure of the phrase, with another 1 beat pickup starting the next phrase. Both sides of the repeat had whole measure rests. How is a human supposed to know these measures are shortened. Sorry I don't remember which song it is, but it looked something like this:
Of course I fixed it when I realized the problem, but MS should do that.
I'm all in agreement that measure rests are extremely confusing way to represent the result of split measures. I think measure rests only should be used when measure's actual beats equals its time signature, which is not the case for newly-split measures. So I support that.
But in the latest pic I shared, you will notice that the split completely reorganized how the empty space is divided into rests. What I think is if there are already rest elements (other than Measure Rest), then each of those rest elements should be preserved in same manner that they were before the split if possible (and if that isn't possible, for instance if a rest was straddling the tick of the split, then that rest should be broken up). But no combining of rests. There is always the "Simplify Durations" function which user could manually apply after performing the split, which could merge rests according to the time Sig's subdivision if desired.
After further testing I realize that when the parts are extracted, both measures are counted as part of multi measure rests. When I manually changed the rests before the repeat to 1/4 notes it broke the multi measure rest but making a 1/4 rest left it included in the ensuing multi measure rest. Making the measure after the repeat 2 1/8 rests caused it to break the multi measure rest.
You can test this by making a score with more than 1 instrument. Leave at least 1 instrument with no notes (for the multi measure rests) split the measure and make the changes I described above. Include a repeat sign in the middle of the split measure.
#20 - I agree with what you said about existing rests. The user was obviously happy with the rests before the split, so they should be left as is unless one is split.
Fixed in branch 2.1, commit 10edf46add
fix #184061 Split Measure must break notes w/ toDurationList()
Splitting a measure via cmdSplitMeasure() may require that notes in other voices break apart their duration into something that cannot be represented with just a single note. Therefore it is necessary to use toDurationList() to break the note's duration up into multiple durations that are tied together to represent the original note before the split.
Fixed in branch 2.1, commit ced33640a8
Merge pull request #3108 from ericfont/184061-SplitOtherVoiceToDurationList
fix #184061 split measure must break notes in other Voices using toDurationList()
Automatically closed -- issue fixed for 2 weeks with no activity.