MusicXML imports - seconds display in wrong order if notes not in pitch order in input

• Mar 13, 2014 - 23:30
S4 - Minor

Windows 7, GIT commit: 5b4bd95 (this is my local build with my layout changes, but issue has existed since 1.X).

1) open attached file
2) look at first chord

Result: the second between the F# and Gb is rendered incorrectly. The F# should be on the left.


MuseScore apparently uses the order of notes in the input to say something about what side of the stem notes appear on. They are listed "D# Gb F#" in the input, and if I edit the file to put the F# first, ti works as expected. But I don't see anything in the spec saying we're supposed to care about the order of notes within a chord, and in any case, neither Finale nor Sibelius appear to.

BTW, this file was created by music21, a Python-based package from MIT. It was provided by Daniel Spreadbury from Steinberg, who created it to compare different programs' accidental layout algorithms.

Attachment Size
steinberg-randomAccs2-excerpt.xml 73.85 KB
xml-wrong-order.png 1.34 KB


Not sure who is wrong here... the comment in chord.h suggests that the notes in the chord are sorted by line. In Chord::add(), notes are sorted by pitch and not by lines, probably because we don't know the line yet(?). The code in layoutChord1() doesn't sort the notes by line if the number of voices up is not *>* 1. Is there a good reason for this? Changing it to >=1 seems to work.…

The chord layout routines assume the chord is already sorted (by line I guess, which could be different from pitch if you have B# and Cb). This assumption was the case before my recent changes, and it remains the case now. I wouldn't be surprised if this assumption existed elsewhere in the code too. So layoutChord1() only performs a sort operation when combining multiple chords (from different voices of the same stem direction) into one note list. Hence the "> 1" test. Failure to sort these combined-voice chords was the culprit in #3325: Seconds between voices overlap, but I was pretty careful not to sort unnecessarily for performance reasons, and it seems it is not normally necessary for single voice chords.

As I recall, failure to sort before layout was the culprit in #23298: stem too short after changing octave of a note in a chord - the chord was either not being resorted after an arrow-key-induced change, or it was being resorted before the new line info was calculated. Either way, the chord sure was sorted incorrectly before the layout code was called, and this led to bad things, and the fix was to get the chord sorted properly before layoutChord1() was ever called. And now everything else seems to work.

So while we could sort even single voice chords in layoutChords, it seems this is normally not needed and would just waste time for most chords. I think we should do the sort at the importxml end so chords are sorted before layout just as with chords created by other means.

We can't sort them at the end of MusicXML import. That's the whole issue. The line is known only after a call to Note::layout10(). I will set the line in MusicXML import with the info we have at this point and make sure that the line is considered when adding a note in the chord.