Skip to content

Commit 8d18a16

Browse files
authored
Merge pull request #183 from hexbold/fix-musicxml-chord-bar-duration
Fix MusicXML export losing measure boundaries with chords
2 parents 3aecbd5 + 5837f41 commit 8d18a16

File tree

4 files changed

+275
-0
lines changed

4 files changed

+275
-0
lines changed

ly/musicxml/ly2xml_mediator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ def new_chordbase(self, note, duration, rel=False):
565565
self.current_note.set_duration(duration)
566566
self.current_lynote = note
567567
self.check_current_note(rel)
568+
self.increase_bar_dura(duration)
568569

569570
def new_chordnote(self, note, rel):
570571
chord_note = self.create_barnote_from_note(note)
@@ -601,6 +602,7 @@ def copy_prev_chord(self, duration):
601602
cn.set_tie('stop')
602603
self.bar.add(cn)
603604
self.tied = False
605+
self.increase_bar_dura(duration)
604606

605607
def clear_chord(self):
606608
self.q_chord = self.current_chord

tests/test_xml.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ def test_no_barcheck():
7676
compare_output('no_barcheck')
7777

7878

79+
def test_chord_duration():
80+
compare_output('chord_duration')
81+
82+
7983
def ly_to_xml(filename):
8084
"""Read Lilypond file and return XML string."""
8185
writer = ly.musicxml.writer()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
\version "2.24.0"
2+
3+
% Test chord duration counting for bar boundaries (issue #171)
4+
% Both explicit chords and duration shorthand must count toward measure duration
5+
6+
\score {
7+
<<
8+
% Explicit chord notation: 3 measures
9+
\new Staff { c''1 | <d'' f'' a''>1 | e''1 }
10+
11+
% Duration shorthand after chord: 3 measures
12+
\new Staff { \time 3/4 <e' f'>4 4 4 | 4 4 8 r8 | r4 a' g' }
13+
>>
14+
\layout { }
15+
}
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
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.9</software>
8+
<encoding-date>2026-01-26</encoding-date>
9+
</encoding>
10+
</identification>
11+
<part-list>
12+
<score-part id="P1">
13+
<part-name />
14+
</score-part>
15+
<score-part id="P2">
16+
<part-name />
17+
</score-part>
18+
</part-list>
19+
<part id="P1">
20+
<measure number="1">
21+
<attributes>
22+
<divisions>2</divisions>
23+
<time>
24+
<beats>3</beats>
25+
<beat-type>4</beat-type>
26+
</time>
27+
<clef>
28+
<sign>G</sign>
29+
<line>2</line>
30+
</clef>
31+
</attributes>
32+
<note>
33+
<pitch>
34+
<step>C</step>
35+
<octave>5</octave>
36+
</pitch>
37+
<duration>8</duration>
38+
<voice>1</voice>
39+
<type>whole</type>
40+
</note>
41+
<backup>
42+
<duration>8</duration>
43+
</backup>
44+
</measure>
45+
<measure number="2">
46+
<note>
47+
<pitch>
48+
<step>D</step>
49+
<octave>5</octave>
50+
</pitch>
51+
<duration>8</duration>
52+
<voice>1</voice>
53+
<type>whole</type>
54+
</note>
55+
</measure>
56+
<measure number="3">
57+
<note>
58+
<chord />
59+
<pitch>
60+
<step>F</step>
61+
<octave>5</octave>
62+
</pitch>
63+
<duration>8</duration>
64+
<voice>1</voice>
65+
<type>whole</type>
66+
</note>
67+
<note>
68+
<chord />
69+
<pitch>
70+
<step>A</step>
71+
<octave>5</octave>
72+
</pitch>
73+
<duration>8</duration>
74+
<voice>1</voice>
75+
<type>whole</type>
76+
</note>
77+
<note>
78+
<pitch>
79+
<step>E</step>
80+
<octave>5</octave>
81+
</pitch>
82+
<duration>8</duration>
83+
<voice>1</voice>
84+
<type>whole</type>
85+
</note>
86+
</measure>
87+
</part>
88+
<part id="P2">
89+
<measure number="1">
90+
<attributes>
91+
<divisions>2</divisions>
92+
<time>
93+
<beats>3</beats>
94+
<beat-type>4</beat-type>
95+
</time>
96+
<clef>
97+
<sign>G</sign>
98+
<line>2</line>
99+
</clef>
100+
</attributes>
101+
<note>
102+
<pitch>
103+
<step>E</step>
104+
<octave>4</octave>
105+
</pitch>
106+
<duration>2</duration>
107+
<voice>1</voice>
108+
<type>quarter</type>
109+
</note>
110+
<note>
111+
<chord />
112+
<pitch>
113+
<step>F</step>
114+
<octave>4</octave>
115+
</pitch>
116+
<duration>2</duration>
117+
<voice>1</voice>
118+
<type>quarter</type>
119+
</note>
120+
<note>
121+
<pitch>
122+
<step>E</step>
123+
<octave>4</octave>
124+
</pitch>
125+
<duration>2</duration>
126+
<voice>1</voice>
127+
<type>quarter</type>
128+
</note>
129+
<note>
130+
<chord />
131+
<pitch>
132+
<step>F</step>
133+
<octave>4</octave>
134+
</pitch>
135+
<duration>2</duration>
136+
<voice>1</voice>
137+
<type>quarter</type>
138+
</note>
139+
<note>
140+
<pitch>
141+
<step>E</step>
142+
<octave>4</octave>
143+
</pitch>
144+
<duration>2</duration>
145+
<voice>1</voice>
146+
<type>quarter</type>
147+
</note>
148+
<note>
149+
<chord />
150+
<pitch>
151+
<step>F</step>
152+
<octave>4</octave>
153+
</pitch>
154+
<duration>2</duration>
155+
<voice>1</voice>
156+
<type>quarter</type>
157+
</note>
158+
<backup>
159+
<duration>6</duration>
160+
</backup>
161+
</measure>
162+
<measure number="2">
163+
<note>
164+
<pitch>
165+
<step>E</step>
166+
<octave>4</octave>
167+
</pitch>
168+
<duration>2</duration>
169+
<voice>1</voice>
170+
<type>quarter</type>
171+
</note>
172+
<note>
173+
<chord />
174+
<pitch>
175+
<step>F</step>
176+
<octave>4</octave>
177+
</pitch>
178+
<duration>2</duration>
179+
<voice>1</voice>
180+
<type>quarter</type>
181+
</note>
182+
<note>
183+
<pitch>
184+
<step>E</step>
185+
<octave>4</octave>
186+
</pitch>
187+
<duration>2</duration>
188+
<voice>1</voice>
189+
<type>quarter</type>
190+
</note>
191+
<note>
192+
<chord />
193+
<pitch>
194+
<step>F</step>
195+
<octave>4</octave>
196+
</pitch>
197+
<duration>2</duration>
198+
<voice>1</voice>
199+
<type>quarter</type>
200+
</note>
201+
<note>
202+
<pitch>
203+
<step>E</step>
204+
<octave>4</octave>
205+
</pitch>
206+
<duration>1</duration>
207+
<voice>1</voice>
208+
<type>eighth</type>
209+
</note>
210+
<note>
211+
<chord />
212+
<pitch>
213+
<step>F</step>
214+
<octave>4</octave>
215+
</pitch>
216+
<duration>1</duration>
217+
<voice>1</voice>
218+
<type>eighth</type>
219+
</note>
220+
<note>
221+
<rest />
222+
<duration>1</duration>
223+
<voice>1</voice>
224+
<type>eighth</type>
225+
</note>
226+
</measure>
227+
<measure number="3">
228+
<note>
229+
<rest />
230+
<duration>2</duration>
231+
<voice>1</voice>
232+
<type>quarter</type>
233+
</note>
234+
<note>
235+
<pitch>
236+
<step>A</step>
237+
<octave>4</octave>
238+
</pitch>
239+
<duration>2</duration>
240+
<voice>1</voice>
241+
<type>quarter</type>
242+
</note>
243+
<note>
244+
<pitch>
245+
<step>G</step>
246+
<octave>4</octave>
247+
</pitch>
248+
<duration>2</duration>
249+
<voice>1</voice>
250+
<type>quarter</type>
251+
</note>
252+
</measure>
253+
</part>
254+
</score-partwise>

0 commit comments

Comments
 (0)