music21 version
9.9.2 and 10.3.0
Operating System(s) checked
This was checked on Linux but is not OS-specific because it's pure Python logic
Problem summary
When using tremolos between notes, roundtrips add a spurious visible tuplet bracket with the number visible. Two notes in the time of one note give a 2/1 time-modification which is not a printed tuplet, but tuplet notation is not properly suppressed after a parse --> write reconstruction back into musicxml roundtrip.
Steps to reproduce
import music21
from music21 import converter
# Minimal between-note tremolo: two whole notes (E3, G3) in the time of one.
# NOTE: there is no <tuplet> element anywhere -- only <time-modification>.
src = '''<?xml version="1.0" encoding="UTF-8"?>
<score-partwise version="4.0">
<part-list><score-part id="P1"><part-name>Piano</part-name></score-part></part-list>
<part id="P1">
<measure number="1">
<attributes>
<divisions>256</divisions>
<key><fifths>0</fifths></key>
<time><beats>2</beats><beat-type>2</beat-type></time>
<clef><sign>F</sign><line>4</line></clef>
</attributes>
<note>
<pitch><step>E</step><octave>3</octave></pitch>
<duration>512</duration><voice>1</voice><type>whole</type>
<time-modification><actual-notes>2</actual-notes><normal-notes>1</normal-notes></time-modification>
<notations><ornaments><tremolo type="start">4</tremolo></ornaments></notations>
</note>
<note>
<pitch><step>G</step><octave>3</octave></pitch>
<duration>512</duration><voice>1</voice><type>whole</type>
<time-modification><actual-notes>2</actual-notes><normal-notes>1</normal-notes></time-modification>
<notations><ornaments><tremolo type="stop">4</tremolo></ornaments></notations>
</note>
</measure>
</part>
</score-partwise>'''
s = converter.parse(src, format='musicxml')
# The importer left the auto-created tuplet visible, even though the source
# had no <tuplet> element:
for n in s.recurse().notes:
t = n.duration.tuplets[0]
print(n.nameWithOctave, 'bracket=', t.bracket, 'actualShow=', t.tupletActualShow)
# E3 bracket= True actualShow= number
# G3 bracket= True actualShow= number
out = s.write('musicxml')
xml = open(out, encoding='utf-8').read()
print('bracket="yes" in output:', 'bracket="yes"' in xml) # -> True
Expected vs. actual behavior
Expected: Round trip should keep the tremolo and time-modification but NOT emit a visible tuplet bracket (either no <tuplet> element, or <tuplet bracket="no" show-number="none">), since the source drew no bracket.)
Actual: output contains <tuplet bracket="yes" number="1" placement="above" type="start"> … <tuplet type="stop"/>
More information
Issue appears to be a fallback tuplet from when there are no tuplet definitions in the tuplet tag. (MeasureParser.xmlToTuplets() in music21/musicxml/xmlToM21.py)
Possible fix: when the fallback 2:1 tuplet is created from <time-modification> alone (no matching <tuplet>), set tup.bracket = False, tup.tupletActualShow = None, and tup.tupletNormalShow = None. Clearest when note has a <tremolo type="start|stop"> ornament, where the 2:1 time-modification is directly from the tremolo and not a tuplet.
music21 version
9.9.2and10.3.0Operating System(s) checked
This was checked on Linux but is not OS-specific because it's pure Python logic
Problem summary
When using tremolos between notes, roundtrips add a spurious visible tuplet bracket with the number visible. Two notes in the time of one note give a 2/1 time-modification which is not a printed tuplet, but tuplet notation is not properly suppressed after a parse --> write reconstruction back into musicxml roundtrip.
Steps to reproduce
Expected vs. actual behavior
Expected: Round trip should keep the tremolo and time-modification but NOT emit a visible tuplet bracket (either no
<tuplet>element, or<tuplet bracket="no" show-number="none">), since the source drew no bracket.)Actual: output contains
<tuplet bracket="yes" number="1" placement="above" type="start">…<tuplet type="stop"/>More information
Issue appears to be a fallback tuplet from when there are no tuplet definitions in the tuplet tag. (
MeasureParser.xmlToTuplets()inmusic21/musicxml/xmlToM21.py)Possible fix: when the fallback 2:1 tuplet is created from
<time-modification>alone (no matching<tuplet>), settup.bracket = False,tup.tupletActualShow = None, andtup.tupletNormalShow = None. Clearest when note has a<tremolo type="start|stop">ornament, where the 2:1 time-modification is directly from the tremolo and not a tuplet.