]> git.donarmstrong.com Git - lilypond.git/commitdiff
MusicXML: Fix lyrics on chords, ignore lyrics for notes inside melismata
authorReinhold Kainhofer <reinhold@kainhofer.com>
Tue, 23 Oct 2007 20:18:27 +0000 (22:18 +0200)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Tue, 23 Oct 2007 20:18:27 +0000 (22:18 +0200)
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.

input/regression/musicxml/06d-Lyrics-Melisma-Finale.xml [new file with mode: 0644]
input/regression/musicxml/06e-Lyrics-Chords-Finale.xml [new file with mode: 0644]
scripts/musicxml2ly.py

diff --git a/input/regression/musicxml/06d-Lyrics-Melisma-Finale.xml b/input/regression/musicxml/06d-Lyrics-Melisma-Finale.xml
new file mode 100644 (file)
index 0000000..5ffbeb9
--- /dev/null
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.0 Partwise//EN"\r
+                                "http://www.musicxml.org/dtds/partwise.dtd">\r
+<score-partwise>\r
+  <movement-title>Lyrics and melismata (ignore them)</movement-title>\r
+  <identification>\r
+    <encoding>\r
+      <software>Finale 2007 for Windows</software>\r
+      <software>Dolet Light for Finale 2007</software>\r
+      <encoding-date>2007-10-23</encoding-date>\r
+    </encoding>\r
+  </identification>\r
+  <part-list>\r
+    <score-part id="P1">\r
+      <part-name>MusicXML Part</part-name>\r
+      <score-instrument id="P1-I1">\r
+        <instrument-name>Grand Piano</instrument-name>\r
+      </score-instrument>\r
+      <midi-instrument id="P1-I1">\r
+        <midi-channel>1</midi-channel>\r
+        <midi-program>1</midi-program>\r
+      </midi-instrument>\r
+    </score-part>\r
+  </part-list>\r
+  <!--=========================================================-->\r
+  <part id="P1">\r
+    <measure number="1">\r
+      <attributes>\r
+        <divisions>1</divisions>\r
+        <key>\r
+          <fifths>0</fifths>\r
+          <mode>major</mode>\r
+        </key>\r
+        <time symbol="common">\r
+          <beats>4</beats>\r
+          <beat-type>4</beat-type>\r
+        </time>\r
+        <clef>\r
+          <sign>G</sign>\r
+          <line>2</line>\r
+        </clef>\r
+      </attributes>\r
+      <sound tempo="120"/>\r
+      <note>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+        <notations>\r
+          <slur number="1" type="start"/>\r
+        </notations>\r
+        <lyric number="1">\r
+          <syllabic>begin</syllabic>\r
+          <text>Me</text>\r
+        </lyric>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>A</step>\r
+          <octave>4</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+      </note>\r
+      <note>\r
+        <chord/>\r
+        <pitch>\r
+          <step>E</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+        <notations>\r
+          <slur number="1" type="stop"/>\r
+        </notations>\r
+      </note>\r
+      <note>\r
+        <chord/>\r
+        <pitch>\r
+          <step>E</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+      </note>\r
+    </measure>\r
+    <!--=======================================================-->\r
+    <measure number="2">\r
+      <note>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+        <notations>\r
+          <slur number="1" type="start"/>\r
+        </notations>\r
+        <lyric number="1">\r
+          <syllabic>middle</syllabic>\r
+          <text>lis</text>\r
+        </lyric>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>E</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+        <notations>\r
+          <slur number="1" type="stop"/>\r
+        </notations>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+        <notations>\r
+          <slur number="1" type="start"/>\r
+        </notations>\r
+        <lyric number="1">\r
+          <syllabic>end</syllabic>\r
+          <text>ma.</text>\r
+          <extend/>\r
+        </lyric>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>E</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+        <notations>\r
+          <slur number="1" type="stop"/>\r
+        </notations>\r
+      </note>\r
+      <barline location="right">\r
+        <bar-style>light-heavy</bar-style>\r
+      </barline>\r
+    </measure>\r
+  </part>\r
+  <!--=========================================================-->\r
+</score-partwise>\r
diff --git a/input/regression/musicxml/06e-Lyrics-Chords-Finale.xml b/input/regression/musicxml/06e-Lyrics-Chords-Finale.xml
new file mode 100644 (file)
index 0000000..6521be5
--- /dev/null
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.0 Partwise//EN"\r
+                                "http://www.musicxml.org/dtds/partwise.dtd">\r
+<score-partwise>\r
+  <movement-title>Lyrics on Chords</movement-title>\r
+  <identification>\r
+    <encoding>\r
+      <software>Finale 2007 for Windows</software>\r
+      <software>Dolet Light for Finale 2007</software>\r
+      <encoding-date>2007-10-23</encoding-date>\r
+    </encoding>\r
+  </identification>\r
+  <part-list>\r
+    <score-part id="P1">\r
+      <part-name>MusicXML Part</part-name>\r
+      <score-instrument id="P1-I1">\r
+        <instrument-name>Grand Piano</instrument-name>\r
+      </score-instrument>\r
+      <midi-instrument id="P1-I1">\r
+        <midi-channel>1</midi-channel>\r
+        <midi-program>1</midi-program>\r
+      </midi-instrument>\r
+    </score-part>\r
+  </part-list>\r
+  <!--=========================================================-->\r
+  <part id="P1">\r
+    <measure number="1">\r
+      <attributes>\r
+        <divisions>1</divisions>\r
+        <key>\r
+          <fifths>0</fifths>\r
+          <mode>major</mode>\r
+        </key>\r
+        <time symbol="common">\r
+          <beats>4</beats>\r
+          <beat-type>4</beat-type>\r
+        </time>\r
+        <clef>\r
+          <sign>G</sign>\r
+          <line>2</line>\r
+        </clef>\r
+      </attributes>\r
+      <sound tempo="120"/>\r
+      <note>\r
+        <pitch>\r
+          <step>E</step>\r
+          <octave>4</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>up</stem>\r
+        <lyric number="1">\r
+          <syllabic>begin</syllabic>\r
+          <text>Ly</text>\r
+        </lyric>\r
+      </note>\r
+      <note>\r
+        <chord/>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>up</stem>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>A</step>\r
+          <octave>4</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+        <lyric number="1">\r
+          <syllabic>end</syllabic>\r
+          <text>rics</text>\r
+        </lyric>\r
+      </note>\r
+      <note>\r
+        <chord/>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>E</step>\r
+          <octave>4</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>up</stem>\r
+        <lyric number="1">\r
+          <syllabic>single</syllabic>\r
+          <text>on</text>\r
+        </lyric>\r
+      </note>\r
+      <note>\r
+        <chord/>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>up</stem>\r
+      </note>\r
+      <note>\r
+        <pitch>\r
+          <step>A</step>\r
+          <octave>4</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+        <lyric number="1">\r
+          <syllabic>single</syllabic>\r
+          <text>chords</text>\r
+        </lyric>\r
+      </note>\r
+      <note>\r
+        <chord/>\r
+        <pitch>\r
+          <step>C</step>\r
+          <octave>5</octave>\r
+        </pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+        <stem>down</stem>\r
+      </note>\r
+      <barline location="right">\r
+        <bar-style>light-heavy</bar-style>\r
+      </barline>\r
+    </measure>\r
+  </part>\r
+  <!--=========================================================-->\r
+</score-partwise>\r
index 1f0dd06adbdb162f7d98144d2b952b867924d6b8..b81c9e8344976325d307f526f65fbff66ed71a96 100644 (file)
@@ -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 <notation> 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: