From: Reinhold Kainhofer Date: Sun, 16 Sep 2007 20:57:16 +0000 (+0200) Subject: MusicXML: Convert grace notes from MusicXML to Lilypond X-Git-Tag: release/2.11.35-1~114 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=e8af8e814eab52b8080f18f78bad7bade87c1c10;p=lilypond.git MusicXML: Convert grace notes from MusicXML to Lilypond Grace notes are normal elements in XML, only with a child element. I append these notes to a special array of EventChord and try to take care of the zero duration of grace notes (which come before the real note and thus also create the EventChord with duration zero!) There is still one problem with things like beams or articulations on grace notes (they are printed after the whole cord (not inside the \grace!), but this is a general problem that musicxml2ly inserts slurs, ties, beams, articulations, etc. as separate events not assigned to any particular note/EventChord. The code should be changed to assign these ornaments/settings directly to the note or the chord they apply to. This would (1) get rid of e.g. triple [ with beamed chords, (2) make it possible to combine multiple MusicXML articulations into single lilypond articulations, (3) apply fingerings and ties to notes inside chords rather than the whole chord, and (4) fix the grace notes. The other problem is when a chord is used as a grace chord in MusicXML. Due to the whole structure of musicxml2ly, this problem goes very deep and I don't know of any way to fix this short of a big rewrite. Signed-off-by: Reinhold Kainhofer --- diff --git a/python/musicexp.py b/python/musicexp.py index 0b41d275c9..4f4b262f77 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -434,6 +434,13 @@ class Lyrics: class EventChord (NestedMusic): + def __init__ (self): + NestedMusic.__init__ (self) + self.grace_elements = [] + def append_grace (self, element): + if element: + self.grace_elements.append (element) + def get_length (self): l = Rational (0) for e in self.elements: @@ -451,6 +458,12 @@ class EventChord (NestedMusic): other_events = [e for e in self.elements if 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 rest_events: rest_events[0].print_ly (printer) elif len (note_events) == 1: diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 9a291a223d..10b21980e3 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -80,7 +80,10 @@ def musicxml_duration_to_lily (mxl_note): d.duration_log = mxl_note.get_duration_log () d.dots = len (mxl_note.get_typed_children (musicxml.Dot)) - d.factor = mxl_note._duration / d.get_length () + # Grace notes by specification have duration 0, so no time modification + # factor is possible. It even messes up the output with *0/1 + if not mxl_note.get_maybe_exist_typed_child (musicxml.Grace): + d.factor = mxl_note._duration / d.get_length () return d @@ -467,7 +470,11 @@ class LilyPondVoiceBuilder: def add_multibar_rest (self, duration): self.pending_multibar += duration - + + def set_duration (self, duration): + self.end_moment = self.begin_moment + duration + def current_duration (self): + return self.end_moment - self.begin_moment def add_music (self, music, duration): assert isinstance (music, musicexp.Music) @@ -476,7 +483,7 @@ class LilyPondVoiceBuilder: self.elements.append (music) self.begin_moment = self.end_moment - self.end_moment = self.begin_moment + duration + self.set_duration (duration) # Insert all pending dynamics right after the note/rest: if duration > Rational (0): @@ -613,8 +620,15 @@ def musicxml_voice_to_lily_voice (voice): if not ev_chord: ev_chord = musicexp.EventChord() voice_builder.add_music (ev_chord, n._duration) - - 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) + if n.get_maybe_exist_typed_child (musicxml.Grace): + ev_chord.append_grace (main_event) + else: + ev_chord.append (main_event) notations = n.get_maybe_exist_typed_child (musicxml.Notations) tuplet_event = None