From 33e002e3b1eef9296e4d945bdb44b105a20f82f7 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Fri, 21 Sep 2007 09:40:11 +0200 Subject: [PATCH] MusicXML: Fix graces to allow beams, chords, etc. Instead of keeping an array of grace elements for each chord, rather use a full SequentialMusic object that holds EventChords (so we can insert beams, real grace chords, etc.). For this we also need a method in the SequentialMusic class to get the last chord. Depending on the slash attribute of the element, we now use acciaccatura rather than grace for slashed grace notes. Signed-off-by: Reinhold Kainhofer --- python/musicexp.py | 35 +++++++++++++++++++++++++++-------- scripts/musicxml2ly.py | 31 ++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/python/musicexp.py b/python/musicexp.py index 45a2e6d4c8..9c6e2341f3 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -393,17 +393,31 @@ class NestedMusic(Music): return None class SequentialMusic (NestedMusic): - def print_ly (self, printer): + def get_last_event_chord (self): + value = None + at = len( self.elements ) - 1 + while (at >= 0 and + not isinstance (self.elements[at], EventChord) and + not isinstance (self.elements[at], BarCheck)): + at -= 1 + + if (at >= 0 and isinstance (self.elements[at], EventChord)): + value = self.elements[at] + return value + + def print_ly (self, printer, newline = True): printer ('{') if self.comment: self.print_comment (printer) - printer.newline() + if newline: + printer.newline() for e in self.elements: e.print_ly (printer) printer ('}') - printer.newline() + if newline: + printer.newline() def lisp_sub_expression (self, pred): name = self.name() @@ -459,9 +473,12 @@ class Header: class EventChord (NestedMusic): def __init__ (self): NestedMusic.__init__ (self) - self.grace_elements = [] + self.grace_elements = None + self.grace_type = None def append_grace (self, element): if element: + if not self.grace_elements: + self.grace_elements = SequentialMusic () self.grace_elements.append (element) def get_length (self): @@ -482,10 +499,12 @@ class EventChord (NestedMusic): not isinstance (e, RhythmicEvent)] if self.grace_elements and self.elements: - printer ('\grace {') - for g in self.grace_elements: - g.print_ly (printer) - printer ('}') + if self.grace_type: + printer ('\\%s' % self.grace_type) + else: + printer ('\\grace') + # don't print newlines after the { and } braces + self.grace_elements.print_ly (printer, False) if rest_events: rest_events[0].print_ly (printer) diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 985ffa45c9..9502e16bc6 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -683,15 +683,32 @@ def musicxml_voice_to_lily_voice (voice): if not ev_chord: ev_chord = musicexp.EventChord() voice_builder.add_music (ev_chord, n._duration) - # When a note/chord has grace notes (duration==0), the duration of the - # event chord is not yet known, but the event chord was already added - # with duration 0. The following correct this when we hit the real note! - if voice_builder.current_duration () == 0 and n._duration > 0: - voice_builder.set_duration (n._duration) - if n.get_maybe_exist_typed_child (musicxml.Grace): - ev_chord.append_grace (main_event) + + grace = n.get_maybe_exist_typed_child (musicxml.Grace) + if grace: + grace_chord = None + if n.get_maybe_exist_typed_child (musicxml.Chord) and ev_chord.grace_elements: + grace_chord = ev_chord.grace_elements.get_last_event_chord () + if not grace_chord: + grace_chord = musicexp.EventChord () + ev_chord.append_grace (grace_chord) + if hasattr (grace, 'slash'): + # TODO: use grace_type = "appoggiatura" for slurred grace notes + if grace.slash == "yes": + ev_chord.grace_type = "acciaccatura" + elif grace.slash == "no": + ev_chord.grace_type = "grace" + # now that we have inserted the chord into the grace music, insert + # everything into that chord instead of the ev_chord + ev_chord = grace_chord + ev_chord.append (main_event) else: ev_chord.append (main_event) + # When a note/chord has grace notes (duration==0), the duration of the + # event chord is not yet known, but the event chord was already added + # with duration 0. The following correct this when we hit the real note! + if voice_builder.current_duration () == 0 and n._duration > 0: + voice_builder.set_duration (n._duration) notations = n.get_maybe_exist_typed_child (musicxml.Notations) tuplet_event = None -- 2.39.5