Skip to content

Commit f0d6d78

Browse files
authored
Merge pull request #1806 from gregchapman-dev/gregc/musicXmlWriterFixes
One fix in m21ToXML.py:parseFlatElements()
2 parents b6bcb2d + 2fcf874 commit f0d6d78

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

music21/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
'''
5151
from __future__ import annotations
5252

53-
__version__ = '9.7.1'
53+
__version__ = '9.7.2a4'
5454

5555
def get_version_tuple(vv):
5656
v = vv.split('.')

music21/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<class 'music21.base.Music21Object'>
2828
2929
>>> music21.VERSION_STR
30-
'9.7.1'
30+
'9.7.2a4'
3131
3232
Alternatively, after doing a complete import, these classes are available
3333
under the module "base":

music21/musicxml/m21ToXml.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
from music21 import chord
3939
from music21 import common
4040
from music21.common.enums import AppendSpanners
41+
from music21.common.numberTools import opFrac
4142
from music21 import defaults
4243
from music21 import duration
4344
from music21 import dynamics
@@ -3322,7 +3323,7 @@ def parseFlatElements(
33223323
else:
33233324
# if necessary, jump to end of the measure.
33243325
if self.offsetInMeasure < firstPassEndOffsetInMeasure:
3325-
self.moveForward(firstPassEndOffsetInMeasure)
3326+
self.moveForward(opFrac(firstPassEndOffsetInMeasure - self.offsetInMeasure))
33263327

33273328
self.currentVoiceId = None
33283329

music21/musicxml/test_m21ToXml.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,60 @@ def test_instrumentDoesNotCreateForward(self):
695695
self.assertTrue(tree.findall('.//note'))
696696
self.assertFalse(tree.findall('.//forward'))
697697

698+
def test_writeFromSpannerAnchorsGetsMeasureEndOffsetRight(self):
699+
'''
700+
Write to MusicXML from a Measure containing SpannerAnchors was not positioning
701+
the current time offset correctly before starting the next written measure.
702+
Now the next measure is positioned at the correct offset.
703+
'''
704+
m1 = stream.Measure()
705+
m1.append(note.Note())
706+
m1.append(note.Note())
707+
m1.append(note.Note())
708+
m1.append(note.Note())
709+
cresc = dynamics.Crescendo()
710+
startAnchor = spanner.SpannerAnchor()
711+
endAnchor = spanner.SpannerAnchor()
712+
m1.insert(0.5, startAnchor)
713+
m1.insert(1.5, endAnchor)
714+
cresc.addSpannedElements(startAnchor, endAnchor)
715+
m1.append(cresc)
716+
p = stream.Part()
717+
p.append(m1)
718+
s = stream.Score()
719+
s.append(p)
720+
# write to MusicXML
721+
tree = self.getET(s)
722+
723+
# walk all the durations (notes, forwards, backups) and make sure they add up
724+
# to where the end of the measure should be (4.0ql)
725+
measEl = None
726+
divisionsEl = None
727+
for el in tree.iter():
728+
if el.tag == 'measure':
729+
measEl = el
730+
for el in measEl.iter():
731+
if el.tag == 'divisions':
732+
divisionsEl = el
733+
break
734+
break
735+
736+
self.assertIsNotNone(measEl)
737+
self.assertIsNotNone(divisionsEl)
738+
739+
divisionsInt = int(divisionsEl.text)
740+
currOffsetQL = 0.
741+
for el in measEl.findall('*'):
742+
dur = el.find('duration')
743+
if dur is not None:
744+
durInt = int(dur.text)
745+
durQL = common.opFrac(fractions.Fraction(durInt, divisionsInt))
746+
if el.tag == 'backup':
747+
currOffsetQL = common.opFrac(currOffsetQL - durQL)
748+
else:
749+
currOffsetQL = common.opFrac(currOffsetQL + durQL)
750+
self.assertEqual(currOffsetQL, 4.)
751+
698752
def testOutOfBoundsExpressionDoesNotCreateForward(self):
699753
'''
700754
A metronome mark at an offset exceeding the bar duration was causing

0 commit comments

Comments
 (0)