def __init__(self):
Event.__init__ (self)
self.span_direction = 0
+ self.line_type = 0
+ self.size = 0
+ def wait_for_note (self):
+ return True
def get_properties(self):
return "'span-direction %d" % self.span_direction
class SlurEvent (SpanEvent):
def ly_expression (self):
- return {-1: '(',
+ before = ''
+ after = ''
+ # TODO: setting dashed/dotted line style does not work, because that
+ # command needs to be written before the note, not when the
+ # event is observed after the note!
+ #if self.line_type == 1:
+ #before = '\\slurDotted'
+ #elif self.line_type == 2:
+ #before = '\\slurDashed'
+ #if before:
+ #after = '\\slurSolid'
+
+ return {-1: before + '(' + after,
0:'',
1:')'}.get (self.span_direction, '')
0:'',
1:']'}.get (self.span_direction, '')
+class PedalEvent (SpanEvent):
+ def ly_expression (self):
+ return {-1: '\\sustainDown',
+ 0:'',
+ 1:'\\sustainUp'}.get (self.span_direction, '')
+
+# type==-1 means octave up, type==-2 means octave down
+class OctaveShiftEvent (SpanEvent):
+ def wait_for_note (self):
+ return False;
+ def ly_octave_shift_indicator (self):
+ if self.size == 8:
+ value = 1
+ elif self.size == 15:
+ value = 2
+ else:
+ value = 0
+ # -2 means up
+ if self.span_direction == -2:
+ value = -value
+ return value
+ def ly_expression (self):
+ dir = self.ly_octave_shift_indicator ()
+ value = ''
+ if dir:
+ value = '#(set-octavation %s)' % dir
+ return {-2: value,
+ -1: value,
+ 0: '',
+ 1: '#(set-octavation 0)'}.get (self.span_direction, '')
+
+class TrillSpanEvent (SpanEvent):
+ def ly_expression (self):
+ return {-1: '\\startTrillSpan',
+ 0:'',
+ 1:'\\stopTrillSpan'}.get (self.span_direction, '')
+
+class GlissandoEvent (SpanEvent):
+ def ly_expression (self):
+ style = ''
+ # TODO: wavy-line glissandos don't work, becasue the style has to be
+ # set before the note, at the \glissando it's already too late!
+ #if self.line_type == 3: # wavy-line:
+ #style = "\once\override Glissando #'style = #'zigzag"
+ # In lilypond, glissando is NOT a spanner, unlike MusicXML.
+ return {-1: style + '\\glissando',
+ 0:'',
+ 1:''}.get (self.span_direction, '')
+
class ArpeggioEvent(Event):
+ def wait_for_note (self):
+ return True;
def ly_expression (self):
return ('\\arpeggio')
return '~'
-class HairpinEvent (Event):
+class HairpinEvent (SpanEvent):
def __init__ (self, type):
self.type = type
def hairpin_to_ly (self):
"mp", "mf",
"f", "ff", "fff", "ffff",
"fp", "sf", "sff", "sp", "spp", "sfz", "rfz" ];
+ def wait_for_note (self):
+ return True;
def ly_expression (self):
if self.type == None:
return;
def ly_expression (self):
return '%s\\%s' % (self.direction_mod (), self.type)
+class ShortArticulationEvent (ArticulationEvent):
+ def direction_mod (self):
+ # default is -
+ return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '-')
+ def ly_expression (self):
+ return '%s%s' % (self.direction_mod (), self.type)
class TremoloEvent (Event):
def __init__ (self):
- self.bars = 0;
+ Event.__init__ (self)
+ self.bars = 0
def ly_expression (self):
str=''
str += ':%s' % (2 ** (2 + string.atoi (self.bars)))
return str
+class BendEvent (Event):
+ def __init__ (self):
+ Event.__init__ (self)
+ self.alter = 0
+ def ly_expression (self):
+ if self.alter:
+ return "-\\bendAfter #%s" % self.alter
+ else:
+ return ''
class RhythmicEvent(Event):
def __init__ (self):
self.editorial = False
self.cautionary = False
+class Music_xml_spanner (Music_xml_node):
+ def get_type (self):
+ if hasattr (self, 'type'):
+ return self.type
+ else:
+ return 0
+ def get_size (self):
+ if hasattr (self, 'size'):
+ return string.atoi (self.size)
+ else:
+ return 0
-class Tuplet(Music_xml_node):
+class Tuplet(Music_xml_spanner):
pass
-class Slur (Music_xml_node):
+class Slur (Music_xml_spanner):
def get_type (self):
return self.type
-class Beam (Music_xml_node):
+class Beam (Music_xml_spanner):
def get_type (self):
return self.get_text ()
def is_primary (self):
return self.number == "1"
+
+class Wavy_line (Music_xml_spanner):
+ pass
+class Pedal (Music_xml_spanner):
+ pass
+
+class Glissando (Music_xml_spanner):
+ pass
+
+class Octave_shift (Music_xml_spanner):
+ # default is 8 for the octave-shift!
+ def get_size (self):
+ if hasattr (self, 'size'):
+ return string.atoi (self.size)
+ else:
+ return 8
+
class Chord (Music_xml_node):
pass
class DirType (Music_xml_node):
pass
+class Bend (Music_xml_node):
+ def bend_alter (self):
+ alter = self.get_maybe_exist_named_child ('bend-alter')
+ if alter:
+ return alter.get_text()
+ else:
+ return 0
+
+
## need this, not all classes are instantiated
## for every input file. Only add those classes, that are either directly
'accidental': Accidental,
'attributes': Attributes,
'beam' : Beam,
+ 'bend' : Bend,
'chord': Chord,
'dot': Dot,
'direction': Direction,
'direction-type': DirType,
'duration': Duration,
+ 'glissando': Glissando,
'grace': Grace,
'identification': Identification,
'lyric': Lyric,
'measure': Measure,
'notations': Notations,
'note': Note,
+ 'octave-shift': Octave_shift,
'part': Part,
'part-list': Part_list,
+ 'pedal': Pedal,
'pitch': Pitch,
'rest': Rest,
'slur': Slur,
'syllabic': Syllabic,
'text': Text,
'time-modification': Time_modification,
+ 'tuplet': Tuplet,
'type': Type,
+ 'wavy-line': Wavy_line,
'work': Work,
}
spanner_event_dict = {
'slur' : musicexp.SlurEvent,
'beam' : musicexp.BeamEvent,
-}
+ 'glissando' : musicexp.GlissandoEvent,
+ 'pedal' : musicexp.PedalEvent,
+ 'wavy-line' : musicexp.TrillSpanEvent,
+ 'octave-shift' : musicexp.OctaveShiftEvent
+}
spanner_type_dict = {
'start': -1,
'begin': -1,
+ 'up': -2,
+ 'down': -1,
'stop': 1,
'end' : 1
}
+spanner_line_type_dict = {
+ 'solid': 0,
+ 'dashed': 1,
+ 'dotted': 2,
+ 'wavy': 3
+}
def musicxml_spanner_to_lily_event (mxl_event):
ev = None
else:
print 'unknown span event ', mxl_event
+
key = mxl_event.get_type ()
span_direction = spanner_type_dict.get (key)
if span_direction:
else:
print 'unknown span type', key, 'for', name
+ if hasattr (mxl_event, 'line-type'):
+ span_line_type = spanner_line_type_dict.get (getattr (mxl_event, 'line-type'))
+ if span_line_type:
+ ev.line_type = span_line_type
+ # assign the size, which is used for octave-shift, etc.
+ ev.size = mxl_event.get_size ()
+
return ev
def musicxml_direction_to_indicator (direction):
ev.force_direction = dir
return ev
-def musicxml_tremolo_to_lily_event(mxl_event):
+def musicxml_tremolo_to_lily_event (mxl_event):
if mxl_event.get_name () != "tremolo":
return
ev = musicexp.TremoloEvent ()
ev.bars = mxl_event.get_text ()
return ev
+def musicxml_bend_to_lily_event (mxl_event):
+ if mxl_event.get_name () != "bend":
+ return
+ ev = musicexp.BendEvent ()
+ ev.alter = mxl_event.bend_alter ()
+ return ev
+
+
# TODO: Some translations are missing!
+short_articulations_dict = {
+ "staccato": ".",
+ "tenuto": "-",
+ "stopped": "+",
+ "staccatissimo": "|",
+ "accent": ">",
+ "strong-accent": "^",
+ #"portato": "_", # does not exist in MusicXML
+ #"fingering": "", # fingering is special cased, as get_text() will be the event's name
+}
articulations_dict = {
##### ORNAMENTS
"trill-mark": "trill",
#"shake": "?",
#"wavy-line": "?",
"mordent": "mordent",
- "inverted-mordent": "downmordent",
+ "inverted-mordent": "prall",
#"schleifer": "?"
##### TECHNICALS
"up-bow": "upbow",
"harmonic": "flageolet",
#"open-string": "",
#"thumb-position": "",
- #"fingering": "",
#"pluck": "",
#"double-tongue": "",
#"triple-tongue": "",
- #"stopped": "",
#"snap-pizzicato": "",
#"fret": "",
#"string": "",
#"hammer-on": "",
#"pull-off": "",
- #"bend": "",
+ #"bend": "bendAfter #%s", # bend is special-cased, as we need to process the bend-alter subelement!
#"tap": "",
#"heel": "",
#"toe": "",
#"fingernails": ""
##### ARTICULATIONS
- "accent": "accent",
- "strong-accent": "marcato",
- "staccato": "staccato",
- "tenuto": "tenuto",
#"detached-legato": "",
- "staccatissimo": "staccatissimo",
#"spiccato": "",
#"scoop": "",
#"plop": "",
#"stress": "",
#"unstress": ""
}
+articulation_spanners = [ "wavy-line" ]
+
+def musicxml_articulation_to_lily_event (mxl_event):
+ # wavy-line elements are treated as trill spanners, not as articulation ornaments
+ if mxl_event.get_name () in articulation_spanners:
+ return musicxml_spanner_to_lily_event (mxl_event)
+
+ # special case, because of the bend-alter subelement
+ if mxl_event.get_name() == "bend":
+ return musicxml_bend_to_lily_event (mxl_event)
+
+ # If we can write a shorthand, use them!
+ if mxl_event.get_name() == "fingering":
+ ev = musicexp.ShortArticulationEvent ()
+ tp = mxl_event.get_text()
+ # In all other cases, use the dicts to translate the xml tag name to a proper lilypond command
+ elif short_articulations_dict.get (mxl_event.get_name ()):
+ ev = musicexp.ShortArticulationEvent ()
+ tp = short_articulations_dict.get (mxl_event.get_name ())
+ else:
+ ev = musicexp.ArticulationEvent ()
+ tp = articulations_dict.get (mxl_event.get_name ())
-def musicxml_articulation_to_lily_event(mxl_event):
- ev = musicexp.ArticulationEvent ()
- tp = articulations_dict.get (mxl_event.get_name ())
if not tp:
return
if not dirtype:
return res
+ direction_spanners = [ 'octave-shift', 'pedal' ]
+
for entry in dirtype.get_all_children ():
if entry.get_name () == "dynamics":
for dynentry in entry.get_all_children ():
event = musicexp.HairpinEvent (wedgetypeval)
res.append (event)
+
+ # octave shifts. pedal marks etc. are spanners:
+ if entry.get_name() in direction_spanners:
+ event = musicxml_spanner_to_lily_event (entry)
+ if event:
+ res.append (event)
+
+
return res
instrument_drumtype_dict = {
if isinstance (n, musicxml.Direction):
for a in musicxml_direction_to_lily (n):
- voice_builder.add_dynamics (a)
+ if a.wait_for_note ():
+ voice_builder.add_dynamics (a)
+ else:
+ voice_builder.add_music (a, 0)
continue
if not n.get_maybe_exist_named_child ('chord'):
fermatas = notations.get_named_children ('fermata')
for a in fermatas:
- ev = musicxml_fermata_to_lily_event (a);
+ ev = musicxml_fermata_to_lily_event (a)
if ev:
ev_chord.append (ev)
+
+ arpeggiate = notations.get_named_children ('arpeggiate')
+ for a in arpeggiate:
+ ev_chord.append (musicexp.ArpeggioEvent ())
+
+ glissandos = notations.get_named_children ('glissando')
+ for a in glissandos:
+ ev = musicxml_spanner_to_lily_event (a)
+ if ev:
+ ev_chord.append (ev)
# Articulations can contain the following child elements:
# accent | strong-accent | staccato | tenuto |