From a596fd93b1cd7f6f6e49dc84a25b79695be983e3 Mon Sep 17 00:00:00 2001 From: Reinhold Kainhofer Date: Tue, 23 Oct 2007 22:18:27 +0200 Subject: [PATCH] MusicXML: Fix lyrics on chords, ignore lyrics for notes inside melismata The lyrics detection code so far ignored chords (ie. it added a \skip for every additional note in the chord). Now I simply ignore all subsequent notes and the corresponding syllables for the lyrics. By default, lilypond does not add lyrics to notes in melismata (i.e. tied notes and notes inside slurs), so while walking through all notes, we need to check whether we are inside a slur, a tie or a grace note and simply ignore the lyrics on these notes. There are some scores, which still put lyrics on notes inside slurs, so in the future, I'll also add a way to set/unset ignoreMelismata, but that's left for the future. --- .../musicxml/06d-Lyrics-Melisma-Finale.xml | 186 ++++++++++++++++++ .../musicxml/06e-Lyrics-Chords-Finale.xml | 150 ++++++++++++++ scripts/musicxml2ly.py | 28 ++- 3 files changed, 357 insertions(+), 7 deletions(-) create mode 100644 input/regression/musicxml/06d-Lyrics-Melisma-Finale.xml create mode 100644 input/regression/musicxml/06e-Lyrics-Chords-Finale.xml diff --git a/input/regression/musicxml/06d-Lyrics-Melisma-Finale.xml b/input/regression/musicxml/06d-Lyrics-Melisma-Finale.xml new file mode 100644 index 0000000000..5ffbeb98b5 --- /dev/null +++ b/input/regression/musicxml/06d-Lyrics-Melisma-Finale.xml @@ -0,0 +1,186 @@ + + + + Lyrics and melismata (ignore them) + + + Finale 2007 for Windows + Dolet Light for Finale 2007 + 2007-10-23 + + + + + MusicXML Part + + Grand Piano + + + 1 + 1 + + + + + + + + 1 + + 0 + major + + + + G + 2 + + + + + + C + 5 + + 1 + 1 + quarter + down + + + + + begin + Me + + + + + A + 4 + + 1 + 1 + quarter + down + + + + + E + 5 + + 1 + 1 + quarter + down + + + + C + 5 + + 1 + 1 + quarter + down + + + + C + 5 + + 1 + 1 + quarter + down + + + + + + + + E + 5 + + 1 + 1 + quarter + down + + + + + + + C + 5 + + 1 + 1 + quarter + down + + + + + middle + lis + + + + + E + 5 + + 1 + 1 + quarter + down + + + + + + + C + 5 + + 1 + 1 + quarter + down + + + + + end + ma. + + + + + + E + 5 + + 1 + 1 + quarter + down + + + + + + light-heavy + + + + + diff --git a/input/regression/musicxml/06e-Lyrics-Chords-Finale.xml b/input/regression/musicxml/06e-Lyrics-Chords-Finale.xml new file mode 100644 index 0000000000..6521be5908 --- /dev/null +++ b/input/regression/musicxml/06e-Lyrics-Chords-Finale.xml @@ -0,0 +1,150 @@ + + + + Lyrics on Chords + + + Finale 2007 for Windows + Dolet Light for Finale 2007 + 2007-10-23 + + + + + MusicXML Part + + Grand Piano + + + 1 + 1 + + + + + + + + 1 + + 0 + major + + + + G + 2 + + + + + + E + 4 + + 1 + 1 + quarter + up + + begin + Ly + + + + + + C + 5 + + 1 + 1 + quarter + up + + + + A + 4 + + 1 + 1 + quarter + down + + end + rics + + + + + + C + 5 + + 1 + 1 + quarter + down + + + + E + 4 + + 1 + 1 + quarter + up + + single + on + + + + + + C + 5 + + 1 + 1 + quarter + up + + + + A + 4 + + 1 + 1 + quarter + down + + single + chords + + + + + + C + 5 + + 1 + 1 + quarter + down + + + light-heavy + + + + + diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 1f0dd06adb..b81c9e8344 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -894,7 +894,13 @@ def musicxml_voice_to_lily_voice (voice): tuplet_events = [] modes_found = {} lyrics = {} - + + # Needed for melismata detection (ignore lyrics on those notes!): + inside_slur = False + is_tied = False + is_chord = False + ignore_lyrics = False + # TODO: Make sure that the keys in the dict don't get reordered, since # we need the correct ordering of the lyrics stanzas! By default, # a dict will reorder its keys @@ -921,7 +927,8 @@ def musicxml_voice_to_lily_voice (voice): voice_builder.add_command (a) continue - if not n.get_maybe_exist_named_child ('chord'): + is_chord = n.get_maybe_exist_named_child ('chord') + if not is_chord: try: voice_builder.jumpto (n._when) except NegativeSkip, neg: @@ -968,8 +975,9 @@ def musicxml_voice_to_lily_voice (voice): num = 0 if num > 0: voice_builder.add_bar_check (num) - + main_event = musicxml_note_to_lily_main_event (n) + ignore_lyrics = inside_slur or is_tied or is_chord if hasattr (main_event, 'drum_type') and main_event.drum_type: modes_found['drummode'] = True @@ -998,6 +1006,7 @@ def musicxml_voice_to_lily_voice (voice): # everything into that chord instead of the ev_chord ev_chord = grace_chord ev_chord.append (main_event) + ignore_lyrics = True else: ev_chord.append (main_event) # When a note/chord has grace notes (duration==0), the duration of the @@ -1009,7 +1018,7 @@ def musicxml_voice_to_lily_voice (voice): notations = n.get_maybe_exist_typed_child (musicxml.Notations) tuplet_event = None span_events = [] - + # The element can have the following children (+ means implemented, ~ partially, - not): # +tied | +slur | +tuplet | glissando | slide | # ornaments | technical | articulations | dynamics | @@ -1030,14 +1039,19 @@ def musicxml_voice_to_lily_voice (voice): if slurs: if len (slurs) > 1: error_message ('more than 1 slur?') - + # record the slur status for the next note in the loop + if slurs[0].get_type () == 'start': + inside_slur = True + elif slurs[0].get_type () == 'stop': + inside_slur = False lily_ev = musicxml_spanner_to_lily_event (slurs[0]) ev_chord.append (lily_ev) mxl_tie = notations.get_tie () if mxl_tie and mxl_tie.type == 'start': ev_chord.append (musicexp.TieEvent ()) - + is_tied = True + fermatas = notations.get_named_children ('fermata') for a in fermatas: ev = musicxml_fermata_to_lily_event (a) @@ -1093,7 +1107,7 @@ def musicxml_voice_to_lily_voice (voice): ev_chord.append (ev) # Extract the lyrics - if not rest: + if not rest and not ignore_lyrics: note_lyrics_processed = [] note_lyrics_elements = n.get_typed_children (musicxml.Lyric) for l in note_lyrics_elements: -- 2.39.5