Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XML: Start supporting manual Beam #120

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ly/musicxml/create_musicxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ def add_dot(self):

def add_beam(self, nr, beam_type):
"""Add beam. """
beam_node = etree.SubElement(self.current_notation, "beam", number=str(nr))
beam_node = etree.SubElement(self.current_note, "beam", number=str(nr))
beam_node.text = beam_type

def add_tie(self, tie_type):
Expand Down
3 changes: 3 additions & 0 deletions ly/musicxml/ly2xml_mediator.py
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,9 @@ def tie_to_next(self):
self.tied = True
self.current_note.set_tie(tie_type)

def set_beam(self, nr, beam_type):
self.current_note.set_beam(nr, beam_type)

def set_slur(self, nr, slur_type):
"""
Set the slur start or stop for the current note. """
Expand Down
20 changes: 15 additions & 5 deletions ly/musicxml/lymus2musxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ def __init__(self):
self.unset_tuplspan = False
self.alt_mode = None
self.rel_pitch_isset = False
self.beamcount = 0
self.beamnr = 0
self.slurcount = 0
self.slurnr = 0
self.phrslurnr = 0
Expand All @@ -94,22 +96,22 @@ def __init__(self):

def parse_text(self, ly_text, filename=None):
"""Parse the LilyPond source specified as text.

If you specify a filename, it can be used to resolve \\include commands
correctly.

"""
doc = ly.document.Document(ly_text)
doc.filename = filename
self.parse_document(doc)

def parse_document(self, ly_doc, relative_first_pitch_absolute=False):
"""Parse the LilyPond source specified as a ly.document document.

If relative_first_pitch_absolute is set to True, the first pitch in a
\relative expression without startpitch is considered to be absolute
(LilyPond 2.18+ behaviour).

"""
# The document is copied and the copy is converted to absolute mode to
# facilitate the export. The original document is unchanged.
Expand Down Expand Up @@ -295,6 +297,8 @@ def Note(self, note):
# chord as grace note
if self.grace_seq:
self.mediator.new_chord_grace()
if self.beamcount > 0:
self.mediator.set_beam(self.beamnr, "continue")

def Unpitched(self, unpitched):
"""A note without pitch, just a standalone duration."""
Expand Down Expand Up @@ -412,7 +416,13 @@ def Postfix(self, postfix):
pass

def Beam(self, beam):
pass
if beam.token == '[':
self.beamcount += 1
self.beamnr = self.beamcount
self.mediator.set_beam(self.beamnr, "begin")
else:
self.mediator.set_beam(self.beamnr, "end")
self.beamcount -= 1

def Slur(self, slur):
""" Slur, '(' = start, ')' = stop. """
Expand Down
20 changes: 19 additions & 1 deletion ly/musicxml/xml_objs.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def iterate_bar(self, bar):
def new_xml_bar_attr(self, obj):
"""Create bar attribute xml-nodes."""
if obj.has_attr():
self.musxml.new_bar_attr(obj.clef, obj.time, obj.key, obj.mode,
self.musxml.new_bar_attr(obj.clef, obj.time, obj.key, obj.mode,
obj.divs, obj.multirest)
if obj.new_system:
self.musxml.new_system(obj.new_system)
Expand Down Expand Up @@ -195,6 +195,8 @@ def new_xml_note(self, obj):
self.musxml.tie_note(t)
for s in obj.slur:
self.musxml.add_slur(s.nr, s.slurtype)
for b in obj.beam:
self.musxml.add_beam(b.nr, b.beam_type)
for a in obj.artic:
self.musxml.new_articulation(a)
if obj.ornament:
Expand Down Expand Up @@ -619,6 +621,11 @@ def __init__(self, nr, slurtype):
self.nr = nr
self.slurtype = slurtype

class Beam():
def __init__(self, nr, beam_type):
"""Stores information about a beam."""
self.nr = nr
self.beam_type = beam_type

##
# Subclasses of BarMus
Expand All @@ -637,6 +644,7 @@ def __init__(self, pitch_note, alter, accidental, duration, voice=1):
self.grace = (0, 0)
self.gliss = None
self.tremolo = ('', 0)
self.beam = []
self.skip = False
self.slur = []
self.artic = []
Expand All @@ -646,6 +654,16 @@ def __init__(self, pitch_note, alter, accidental, duration, voice=1):
self.lyric = None
self.stem_direction = None

def set_beam(self, nr, beam_type):
# NOTE: The following is only function as long as we're
# only dealing with *one* beam instead of a proper beaming pattern.
# If we have a real beaming pattern, a beam end has to end *all*
# beam levels.
if beam_type == 'end':
self.beam = [Beam(nr, beam_type)]
else:
self.beam.append(Beam(nr, beam_type))

def set_duration(self, duration, durtype=''):
self.duration = duration
self.dot = 0
Expand Down
7 changes: 7 additions & 0 deletions tests/test_xml_files/beam.ly
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
\version "2.19.80"

{
a'8 [ b'16 a' ]
g'8 [ a'32 b' c''16 ]
b'16.. [ a'64 g'16 f'32 e' ]
}
153 changes: 153 additions & 0 deletions tests/test_xml_files/beam.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN"
"http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise version="3.0">
<identification>
<encoding>
<software>python-ly 0.9.5</software>
<encoding-date>2018-05-05</encoding-date>
</encoding>
</identification>
<part-list>
<score-part id="P1">
<part-name />
</score-part>
</part-list>
<part id="P1">
<measure number="1">
<attributes>
<divisions>128</divisions>
<time symbol="common">
<beats>4</beats>
<beat-type>4</beat-type>
</time>
<clef>
<sign>G</sign>
<line>2</line>
</clef>
</attributes>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>64</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<duration>32</duration>
<voice>1</voice>
<type>16th</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>32</duration>
<voice>1</voice>
<type>16th</type>
<beam number="1">end</beam>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>64</duration>
<voice>1</voice>
<type>eighth</type>
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>16</duration>
<voice>1</voice>
<type>32nd</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<duration>16</duration>
<voice>1</voice>
<type>32nd</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>C</step>
<octave>5</octave>
</pitch>
<duration>32</duration>
<voice>1</voice>
<type>16th</type>
<beam number="1">end</beam>
</note>
<note>
<pitch>
<step>B</step>
<octave>4</octave>
</pitch>
<duration>56</duration>
<voice>1</voice>
<type>16th</type>
<dot />
<dot />
<beam number="1">begin</beam>
</note>
<note>
<pitch>
<step>A</step>
<octave>4</octave>
</pitch>
<duration>8</duration>
<voice>1</voice>
<type>64th</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>G</step>
<octave>4</octave>
</pitch>
<duration>32</duration>
<voice>1</voice>
<type>16th</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>F</step>
<octave>4</octave>
</pitch>
<duration>16</duration>
<voice>1</voice>
<type>32nd</type>
<beam number="1">continue</beam>
</note>
<note>
<pitch>
<step>E</step>
<octave>4</octave>
</pitch>
<duration>16</duration>
<voice>1</voice>
<type>32nd</type>
<beam number="1">end</beam>
</note>
</measure>
</part>
</score-partwise>