From 686757f5c98b43d40458ff3e5ced93f666f36498 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Fri, 11 Apr 2008 20:56:56 +0200 Subject: [PATCH] MusicXML: Implement to modify chords (add/remove/alter); support bass Signed-off-by: Reinhold Kainhofer --- python/musicexp.py | 29 ++++++++++++++++++++++++++++- python/musicxml.py | 39 ++++++++++++++++++++++++++++++++++++--- scripts/musicxml2ly.py | 33 ++++++++++++++++++++++----------- 3 files changed, 86 insertions(+), 15 deletions(-) diff --git a/python/musicexp.py b/python/musicexp.py index 5efff8a416..8cedf06dec 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -1099,7 +1099,7 @@ class FretEvent (MarkupEvent): else: return '' -class ChordRoot: +class ChordPitch: def __init__ (self): self.alteration = 0 self.step = 0 @@ -1108,12 +1108,30 @@ class ChordRoot: def ly_expression (self): return pitch_generating_function (self) +class ChordModification: + def __init__ (self): + self.alteration = 0 + self.step = 0 + self.type = 0 + def ly_expression (self): + if self.type: + val = {1: ".", -1: "^" }.get (self.type, "") + val += "%s" % self.step + val += {1: "+", -1: "-"}.get (self.alteration, "") + return val + else: + return '' + class ChordNameEvent (Event): def __init__ (self): Event.__init__ (self) self.root = None self.kind = None self.duration = None + self.modifications = [] + self.bass = None + def add_modification (self, mod): + self.modifications.append (mod) def ly_expression (self): if not self.root: return '' @@ -1123,6 +1141,15 @@ class ChordNameEvent (Event): if self.kind: value += ":" value += self.kind + # First print all additions/changes, and only afterwards all subtractions + for m in self.modifications: + if m.type == 1: + value += m.ly_expression () + for m in self.modifications: + if m.type == -1: + value += m.ly_expression () + if self.bass: + value += "/%s" % self.bass.ly_expression () return value diff --git a/python/musicxml.py b/python/musicxml.py index c71bf2d0be..5afd4f2795 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -872,17 +872,48 @@ class Words (Music_xml_node): class Harmony (Music_xml_node): pass -class Root (Music_xml_node): +class ChordPitch (Music_xml_node): + def step_class_name (self): + return u'root-step' + def alter_class_name (self): + return u'root-alter' def get_step (self): - ch = self.get_unique_typed_child (get_class (u'root-step')) + ch = self.get_unique_typed_child (get_class (self.step_class_name ())) return ch.get_text ().strip () def get_alteration (self): - ch = self.get_maybe_exist_typed_child (get_class (u'root-alter')) + ch = self.get_maybe_exist_typed_child (get_class (self.alter_class_name ())) alter = 0 if ch: alter = int (ch.get_text ().strip ()) return alter +class Root (ChordPitch): + pass + +class Bass (ChordPitch): + def step_class_name (self): + return u'bass-step' + def alter_class_name (self): + return u'bass-alter' + +class ChordModification (Music_xml_node): + def get_type (self): + ch = self.get_maybe_exist_typed_child (get_class (u'degree-type')) + return {'add': 1, 'alter': 1, 'subtract': -1}.get (ch.get_text ().strip (), 0) + def get_value (self): + ch = self.get_maybe_exist_typed_child (get_class (u'degree-value')) + value = 0 + if ch: + value = int (ch.get_text ().strip ()) + return value + def get_alter (self): + ch = self.get_maybe_exist_typed_child (get_class (u'degree-alter')) + value = 0 + if ch: + value = int (ch.get_text ().strip ()) + return value + + class Frame (Music_xml_node): def get_frets (self): return self.get_named_child_value_number ('frame-frets', 4) @@ -929,6 +960,7 @@ class_dict = { 'attributes': Attributes, 'barline': Barline, 'bar-style': BarStyle, + 'bass': Bass, 'beam' : Beam, 'beat-unit': BeatUnit, 'beat-unit-dot': BeatUnitDot, @@ -936,6 +968,7 @@ class_dict = { 'bracket' : Bracket, 'chord': Chord, 'dashes' : Dashes, + 'degree' : ChordModification, 'dot': Dot, 'direction': Direction, 'direction-type': DirType, diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 3bed2ed9be..22f7852375 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -1311,14 +1311,14 @@ def musicxml_harmony_to_lily (n): return res -def musicxml_chordroot_to_lily (mxl_root): - r = musicexp.ChordRoot () - r.alteration = mxl_root.get_alteration () - r.step = musicxml_step_to_lily (mxl_root.get_step ()) +def musicxml_chordpitch_to_lily (mxl_cpitch): + r = musicexp.ChordPitch () + r.alteration = mxl_cpitch.get_alteration () + r.step = musicxml_step_to_lily (mxl_cpitch.get_step ()) return r chordkind_dict = { - 'major': '', + 'major': '5', 'minor': 'm', 'augmented': 'aug', 'diminished': 'dim', @@ -1357,7 +1357,7 @@ chordkind_dict = { #'pedal': '???',(pedal-point bass) #'power': '???',(perfect fifth) #'Tristan': '???', - #'other': '', + 'other': '1', 'none': None, } @@ -1373,20 +1373,31 @@ def musicxml_harmony_to_lily_chordname (n): root = n.get_maybe_exist_named_child ('root') if root: ev = musicexp.ChordNameEvent () - ev.root = musicxml_chordroot_to_lily (root) + ev.root = musicxml_chordpitch_to_lily (root) kind = n.get_maybe_exist_named_child ('kind') if kind: ev.kind = musicxml_chordkind_to_lily (kind.get_text ()) + if not ev.kind: + return res + bass = n.get_maybe_exist_named_child ('bass') + if bass: + ev.bass = musicxml_chordpitch_to_lily (bass) + inversion = n.get_maybe_exist_named_child ('inversion') + if inversion: + # TODO: Lilypond does not support inversions, does it? + pass + for deg in n.get_named_children ('degree'): + d = musicexp.ChordModification () + d.type = deg.get_type () + d.step = deg.get_value () + d.alteration = deg.get_alter () + ev.add_modification (d) #TODO: convert the user-symbols attribute: #major: a triangle, like Unicode 25B3 #minor: -, like Unicode 002D #augmented: +, like Unicode 002B #diminished: (degree), like Unicode 00B0 #half-diminished: (o with slash), like Unicode 00F8 - # TODO: Convert the inversion and bass children - for deg in n.get_named_children ('degree'): - # TODO: Convert the added/removed degrees to lilypond - pass if ev and ev.root: res.append (ev) -- 2.39.2