Repository navigation
MusicXML import ignores jumps written as <sound> attributes #2079
Description
music21 version
10.5.0
Problem summary
The MusicXML importer only creates repeat expressions (Segno, Coda, DalSegnoAlCoda, ...) from the text of <words> directions. It ignores the dacapo, dalsegno, tocoda, fine, segno and coda attributes of <sound>, which are how MusicXML encodes jumps for playback. So when the <words> text isn't one of the recognized phrases, or there's no text, expandRepeats() skips the jump even though the <sound> says exactly what it is.
Steps to reproduce
from music21 import converter
def measure(number, step, before="", after=""):
return (f'<measure number="{number}">{before}<note><pitch><step>{step}</step>'
f'<octave>4</octave></pitch><duration>4</duration><type>whole</type></note>{after}</measure>')
xml = f'''<score-partwise version="4.0">
<part-list><score-part id="P1"><part-name>Music</part-name></score-part></part-list>
<part id="P1">
{measure(1, "C", "<attributes><divisions>1</divisions></attributes>")}
{measure(2, "D", '<direction><direction-type><segno/></direction-type><sound segno="segno"/></direction>')}
{measure(3, "E", after='<direction><direction-type><words>To Coda</words></direction-type><sound tocoda="coda"/></direction>')}
{measure(4, "F", after='<direction><direction-type><words>Repeat from sign, then go to the coda</words></direction-type><sound dalsegno="segno"/></direction>')}
{measure(5, "G", '<direction><direction-type><coda/></direction-type><sound coda="coda"/></direction>')}
</part>
</score-partwise>'''
expanded = converter.parse(xml, format='musicxml').expandRepeats()
print([n.name for n in expanded.flatten().notes])Expected vs. actual behavior
Expected ['C', 'D', 'E', 'F', 'D', 'E', 'G'], from the dalsegno attribute. Actual:
['C', 'D', 'E', 'F', 'G']
With <words>D.S. al Coda</words> the jump is taken, so this only affects jumps whose text isn't a recognized phrase.
More information
SoundTagMixin.setSound in musicxml/xmlSoundParser.py only handles tempo, and has TODOs for coda, dacapo, dalsegno, fine, segno and tocoda.
A suggestion for how the two sources could combine: if only one of <words> and <sound> gives a jump, use it; if both do and they disagree, prefer <sound>, since it's the playback encoding, and maybe warn.
One complication: music21 represents a jump as a single expression, like DalSegnoAlCoda, but MusicXML spreads it over several <sound>s: dalsegno at the jump, tocoda at the "To Coda", and fine at the Fine. So a <sound dalsegno> on its own only says "D.S.", and telling whether it's "al Coda" or "al Fine" means looking for tocoda or fine elsewhere in the part. For the same reason, <words>D.S. al Coda</words> with <sound dalsegno="segno"/> isn't a disagreement, just a more specific description.
Activity