Skip to content

Commit 144dcca

Browse files
authored
Merge pull request #99 from FelippeRoza/partial-export
MusicXML: \partial export as pickup measure
2 parents dd0b316 + bddf5c7 commit 144dcca

File tree

7 files changed

+99
-2
lines changed

7 files changed

+99
-2
lines changed

ly/musicxml/create_musicxml.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,10 @@ def create_part(self, name="unnamed", abbr=False, midi=False):
112112
self.part_count += 1
113113
self.bar_nr = 1
114114

115-
def create_measure(self, **bar_attrs):
115+
def create_measure(self, pickup = False, **bar_attrs):
116116
"""Create new measure """
117+
if pickup and self.bar_nr == 1:
118+
self.bar_nr = 0
117119
self.current_bar = etree.SubElement(self.current_part, "measure", number=str(self.bar_nr))
118120
self.bar_nr +=1
119121
if bar_attrs:

ly/musicxml/ly2xml_mediator.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def __init__(self):
7676
self.prev_tremolo = 8
7777
self.tupl_dur = 0
7878
self.tupl_sum = 0
79+
self.bar_is_pickup = False
7980

8081
def new_header_assignment(self, name, value):
8182
"""Distributing header information."""
@@ -309,11 +310,17 @@ def get_first_var(self):
309310
if self.sections:
310311
return self.sections[0].barlist
311312

313+
def set_pickup(self):
314+
self.bar_is_pickup = True
315+
312316
def new_bar(self, fill_prev=True):
313317
if self.bar and fill_prev:
314318
self.bar.list_full = True
315319
self.current_attr = xml_objs.BarAttr()
316320
self.bar = xml_objs.Bar()
321+
if self.bar_is_pickup:
322+
self.bar.pickup = True
323+
self.bar_is_pickup = False
317324
self.bar.obj_list = [self.current_attr]
318325
self.insert_into.barlist.append(self.bar)
319326

ly/musicxml/lymus2musxml.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ def __init__(self):
8989
self.slurcount = 0
9090
self.slurnr = 0
9191
self.phrslurnr = 0
92+
self.pickup = False
9293

9394
def parse_text(self, ly_text, filename=None):
9495
"""Parse the LilyPond source specified as text.
@@ -266,6 +267,9 @@ def Relative(self, relative):
266267
r"""A \relative music expression."""
267268
self.relative = True
268269

270+
def Partial(self, partial):
271+
self.pickup = True
272+
269273
def Note(self, note):
270274
""" notename, e.g. c, cis, a bes ... """
271275
#print(note.token)
@@ -340,6 +344,9 @@ def Duration(self, duration):
340344
elif self.tupl_span:
341345
self.mediator.set_tuplspan_dur(duration.token, duration.tokens)
342346
self.tupl_span = False
347+
elif self.pickup:
348+
self.mediator.set_pickup()
349+
self.pickup = False
343350
else:
344351
self.mediator.new_duration_token(duration.token, duration.tokens)
345352
if self.trem_rep:

ly/musicxml/xml_objs.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def iterate_part(self, part):
102102

103103
def iterate_bar(self, bar):
104104
"""The objects in the bar are output to the xml-file."""
105-
self.musxml.create_measure()
105+
self.musxml.create_measure(pickup = bar.pickup)
106106
for obj in bar.obj_list:
107107
if isinstance(obj, BarAttr):
108108
self.new_xml_bar_attr(obj)
@@ -432,6 +432,7 @@ class Bar():
432432
Contains also information about how complete it is."""
433433
def __init__(self):
434434
self.obj_list = []
435+
self.pickup = False
435436
self.list_full = False
436437

437438
def __repr__(self):

tests/test_xml.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ def test_tuplet():
3131
compare_output('tuplet')
3232

3333

34+
def test_partial():
35+
compare_output('partial')
36+
37+
3438
def ly_to_xml(filename):
3539
"""Read Lilypond file and return XML string."""
3640
writer = ly.musicxml.writer()

tests/test_xml_files/partial.ly

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
score{
2+
\partial 8 f8 |
3+
c2 d2 |
4+
\partial 8 f8
5+
}

tests/test_xml_files/partial.xml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN"
3+
"http://www.musicxml.org/dtds/partwise.dtd">
4+
<score-partwise version="3.0">
5+
<identification>
6+
<encoding>
7+
<software>python-ly 0.9.5</software>
8+
<encoding-date>2017-05-28</encoding-date>
9+
</encoding>
10+
</identification>
11+
<part-list>
12+
<score-part id="P1">
13+
<part-name />
14+
</score-part>
15+
</part-list>
16+
<part id="P1">
17+
<measure number="0">
18+
<attributes>
19+
<divisions>2</divisions>
20+
<time symbol="common">
21+
<beats>4</beats>
22+
<beat-type>4</beat-type>
23+
</time>
24+
<clef>
25+
<sign>G</sign>
26+
<line>2</line>
27+
</clef>
28+
</attributes>
29+
<note>
30+
<pitch>
31+
<step>F</step>
32+
<octave>3</octave>
33+
</pitch>
34+
<duration>1</duration>
35+
<voice>1</voice>
36+
<type>eighth</type>
37+
</note>
38+
</measure>
39+
<measure number="1">
40+
<note>
41+
<pitch>
42+
<step>C</step>
43+
<octave>3</octave>
44+
</pitch>
45+
<duration>4</duration>
46+
<voice>1</voice>
47+
<type>half</type>
48+
</note>
49+
<note>
50+
<pitch>
51+
<step>D</step>
52+
<octave>3</octave>
53+
</pitch>
54+
<duration>4</duration>
55+
<voice>1</voice>
56+
<type>half</type>
57+
</note>
58+
</measure>
59+
<measure number="2">
60+
<note>
61+
<pitch>
62+
<step>F</step>
63+
<octave>3</octave>
64+
</pitch>
65+
<duration>1</duration>
66+
<voice>1</voice>
67+
<type>eighth</type>
68+
</note>
69+
</measure>
70+
</part>
71+
</score-partwise>

0 commit comments

Comments
 (0)