]> git.donarmstrong.com Git - lilypond.git/commitdiff
MusicXML: Cleanup voice handling and fix lyrics order for multiple stanzas
authorReinhold Kainhofer <reinhold@kainhofer.com>
Sun, 28 Oct 2007 13:27:58 +0000 (14:27 +0100)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Sun, 28 Oct 2007 13:27:58 +0000 (14:27 +0100)
So far, multiple stanzas were handled by a dict, indexed by the voice ID.
However, the order of the elements in a dict is not defined (in particular,
the order is not preserved), so the stanzas got reordered and lost their
sorting.
Furthermore, each voice (with the associated lyrics and the raw data) was
handled by nested lists, which were really complicated to work with (since
one always had to remember the structure of these lists). I now use a
class/struct instead for each voice, which is much more intuitive!

input/regression/musicxml/06b-MultipleLyrics-Finale.xml
scripts/musicxml2ly.py

index 6c48ac27c1235a6d2be0ec95ae2206ea9383041c..f2d7c8d869fa52e0bbd45825a2833b2cd6f743ad 100644 (file)
-<?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>Finale Multiple Lyrics</movement-title>\r
-  <identification>\r
-    <creator type="composer">Reinhold Kainhofer</creator>\r
-    <rights>Public Domain</rights>\r
-    <encoding>\r
-      <software>Finale 2007 for Windows</software>\r
-      <software>Dolet Light for Finale 2007</software>\r
-      <encoding-date>2007-08-31</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>G</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>Tra</text>\r
-        </lyric>\r
-        <lyric number="2">\r
-          <syllabic>begin</syllabic>\r
-          <text>tra</text>\r
-        </lyric>\r
-        <lyric number="3">\r
-          <syllabic>begin</syllabic>\r
-          <text>TRA</text>\r
-        </lyric>\r
-      </note>\r
-      <note>\r
-        <pitch>\r
-          <step>G</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>middle</syllabic>\r
-          <text>la</text>\r
-        </lyric>\r
-        <lyric number="2">\r
-          <syllabic>middle</syllabic>\r
-          <text>la</text>\r
-        </lyric>\r
-        <lyric number="3">\r
-          <syllabic>middle</syllabic>\r
-          <text>LA</text>\r
-        </lyric>\r
-      </note>\r
-      <note>\r
-        <pitch>\r
-          <step>G</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>end</syllabic>\r
-          <text>la,</text>\r
-        </lyric>\r
-        <lyric number="2">\r
-          <syllabic>end</syllabic>\r
-          <text>la,</text>\r
-        </lyric>\r
-        <lyric number="3">\r
-          <syllabic>end</syllabic>\r
-          <text>LA,</text>\r
-        </lyric>\r
-      </note>\r
-      <note>\r
-        <pitch>\r
-          <step>G</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>ja!</text>\r
-          <extend/>\r
-        </lyric>\r
-        <lyric number="2">\r
-          <syllabic>single</syllabic>\r
-          <text>ja!</text>\r
-          <extend/>\r
-        </lyric>\r
-        <lyric number="3">\r
-          <syllabic>single</syllabic>\r
-          <text>JA!</text>\r
-          <extend/>\r
-        </lyric>\r
-      </note>\r
-    </measure>\r
-    <!--=======================================================-->\r
-    <measure number="2">\r
-      <note>\r
-        <pitch>\r
-          <step>G</step>\r
-          <octave>4</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>G</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>Tra</text>\r
-        </lyric>\r
-        <lyric number="2">\r
-          <syllabic>begin</syllabic>\r
-          <text>Tra</text>\r
-        </lyric>\r
-        <lyric number="3">\r
-          <syllabic>begin</syllabic>\r
-          <text>TRA</text>\r
-        </lyric>\r
-      </note>\r
-      <note>\r
-        <pitch>\r
-          <step>G</step>\r
-          <octave>4</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>G</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>end</syllabic>\r
-          <text>ra...</text>\r
-        </lyric>\r
-        <lyric number="2">\r
-          <syllabic>end</syllabic>\r
-          <text>ra.</text>\r
-        </lyric>\r
-        <lyric number="3">\r
-          <syllabic>end</syllabic>\r
-          <text>RA...</text>\r
-        </lyric>\r
-      </note>\r
-      <barline location="right">\r
-        <bar-style>light-heavy</bar-style>\r
-      </barline>\r
-    </measure>\r
-  </part>\r
-  <!--=========================================================-->\r
-</score-partwise>\r
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.0 Partwise//EN"
+                                "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise>
+  <movement-title>Finale Multiple Lyrics</movement-title>
+  <identification>
+    <creator type="composer">Reinhold Kainhofer</creator>
+    <rights>Public Domain</rights>
+    <encoding>
+      <software>Finale 2007 for Windows</software>
+      <software>Dolet Light for Finale 2007</software>
+      <encoding-date>2007-08-31</encoding-date>
+    </encoding>
+  </identification>
+  <part-list>
+    <score-part id="P1">
+      <part-name>MusicXML Part</part-name>
+      <score-instrument id="P1-I1">
+        <instrument-name>Grand Piano</instrument-name>
+      </score-instrument>
+      <midi-instrument id="P1-I1">
+        <midi-channel>1</midi-channel>
+        <midi-program>1</midi-program>
+      </midi-instrument>
+    </score-part>
+  </part-list>
+  <!--=========================================================-->
+  <part id="P1">
+    <measure number="1">
+      <attributes>
+        <divisions>1</divisions>
+        <key>
+          <fifths>0</fifths>
+          <mode>major</mode>
+        </key>
+        <time symbol="common">
+          <beats>4</beats>
+          <beat-type>4</beat-type>
+        </time>
+        <clef>
+          <sign>G</sign>
+          <line>2</line>
+        </clef>
+      </attributes>
+      <sound tempo="120"/>
+      <note>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <lyric number="1">
+          <syllabic>begin</syllabic>
+          <text>1.Tra</text>
+        </lyric>
+        <lyric number="2">
+          <syllabic>begin</syllabic>
+          <text>2.tra</text>
+        </lyric>
+        <lyric number="3">
+          <syllabic>begin</syllabic>
+          <text>3.TRA</text>
+        </lyric>
+      </note>
+      <note>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <lyric number="1">
+          <syllabic>middle</syllabic>
+          <text>la</text>
+        </lyric>
+        <lyric number="2">
+          <syllabic>middle</syllabic>
+          <text>la</text>
+        </lyric>
+        <lyric number="3">
+          <syllabic>middle</syllabic>
+          <text>LA</text>
+        </lyric>
+      </note>
+      <note>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <lyric number="1">
+          <syllabic>end</syllabic>
+          <text>la,</text>
+        </lyric>
+        <lyric number="2">
+          <syllabic>end</syllabic>
+          <text>la,</text>
+        </lyric>
+        <lyric number="3">
+          <syllabic>end</syllabic>
+          <text>LA,</text>
+        </lyric>
+      </note>
+      <note>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <lyric number="1">
+          <syllabic>single</syllabic>
+          <text>ja!</text>
+          <extend/>
+        </lyric>
+        <lyric number="2">
+          <syllabic>single</syllabic>
+          <text>ja!</text>
+          <extend/>
+        </lyric>
+        <lyric number="3">
+          <syllabic>single</syllabic>
+          <text>JA!</text>
+          <extend/>
+        </lyric>
+      </note>
+    </measure>
+    <!--=======================================================-->
+    <measure number="2">
+      <note>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+      </note>
+      <note>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <lyric number="1">
+          <syllabic>begin</syllabic>
+          <text>Tra</text>
+        </lyric>
+        <lyric number="2">
+          <syllabic>begin</syllabic>
+          <text>Tra</text>
+        </lyric>
+        <lyric number="3">
+          <syllabic>begin</syllabic>
+          <text>TRA</text>
+        </lyric>
+      </note>
+      <note>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+      </note>
+      <note>
+        <pitch>
+          <step>G</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <stem>up</stem>
+        <lyric number="1">
+          <syllabic>end</syllabic>
+          <text>ra...</text>
+        </lyric>
+        <lyric number="2">
+          <syllabic>end</syllabic>
+          <text>ra.</text>
+        </lyric>
+        <lyric number="3">
+          <syllabic>end</syllabic>
+          <text>RA...</text>
+        </lyric>
+      </note>
+      <barline location="right">
+        <bar-style>light-heavy</bar-style>
+      </barline>
+    </measure>
+  </part>
+  <!--=========================================================-->
+</score-partwise>
index 4a8548630b85177381a90a1fa2bb36aa7c2b756c..4a944b1fd294427dd3cbe3f513f3e6def3e97a4f 100644 (file)
@@ -936,11 +936,21 @@ class LilyPondVoiceBuilder:
         self.begin_moment = goto
         evc = musicexp.EventChord ()
         self.elements.append (evc)
-        
+
+
+class VoiceData:
+    def __init__ (self):
+        self.voicedata = None
+        self.ly_voice = None
+        self.lyrics_dict = {}
+        self.lyrics_order = []
+
 def musicxml_voice_to_lily_voice (voice):
     tuplet_events = []
     modes_found = {}
     lyrics = {}
+    return_value = VoiceData ()
+    return_value.voicedata = voice
 
     # Needed for melismata detection (ignore lyrics on those notes!):
     inside_slur = False
@@ -953,7 +963,8 @@ def musicxml_voice_to_lily_voice (voice):
     # 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
-    for k in voice.get_lyrics_numbers ():
+    return_value.lyrics_order = voice.get_lyrics_numbers ()
+    for k in return_value.lyrics_order:
         lyrics[k] = []
 
     voice_builder = LilyPondVoiceBuilder()
@@ -1220,23 +1231,22 @@ def musicxml_voice_to_lily_voice (voice):
                     if not isinstance(e, musicexp.KeySignatureChange)]
     
     seq_music.elements = ly_voice
-    lyrics_dict = {}
     for k in lyrics.keys ():
-        lyrics_dict[k] = musicexp.Lyrics ()
-        lyrics_dict[k].lyrics_syllables = lyrics[k]
+        return_value.lyrics_dict[k] = musicexp.Lyrics ()
+        return_value.lyrics_dict[k].lyrics_syllables = lyrics[k]
     
     
     if len (modes_found) > 1:
        error_message ('Too many modes found %s' % modes_found.keys ())
 
-    return_value = seq_music
+    return_value.ly_voice = seq_music
     for mode in modes_found.keys ():
         v = musicexp.ModeChangingMusicWrapper()
-        v.element = return_value
+        v.element = seq_music
         v.mode = mode
-        return_value = v
+        return_value.ly_voice = v
     
-    return (return_value, lyrics_dict)
+    return return_value
 
 
 def musicxml_id_to_lily (id):
@@ -1292,7 +1302,7 @@ def get_all_voices (parts):
         for n, v in name_voice.items ():
             progress ("Converting to LilyPond expressions...")
             # musicxml_voice_to_lily_voice returns (lily_voice, {nr->lyrics, nr->lyrics})
-            part_ly_voices[n] = (musicxml_voice_to_lily_voice (v), v)
+            part_ly_voices[n] = musicxml_voice_to_lily_voice (v)
 
         all_ly_voices[p] = part_ly_voices
         
@@ -1352,16 +1362,17 @@ def print_voice_definitions (printer, part_list, voices):
 
     for part in part_list:
         (p, nv_dict) = part_dict.get (part.id, (None, {}))
-        for (name, ((voice, lyrics), mxlvoice)) in nv_dict.items ():
+        #for (name, ((voice, lyrics), mxlvoice)) in nv_dict.items ():
+        for (name, voice) in nv_dict.items ():
             k = music_xml_voice_name_to_lily_name (p, name)
             printer.dump ('%s = ' % k)
-            voice.print_ly (printer)
+            voice.ly_voice.print_ly (printer)
             printer.newline()
-            
-            for l in lyrics.keys ():
+
+            for l in voice.lyrics_order:
                 lname = music_xml_lyrics_name_to_lily_name (p, name, l)
                 printer.dump ('%s = ' %lname )
-                lyrics[l].print_ly (printer)
+                voice.lyrics_dict[l].print_ly (printer)
                 printer.newline()
 
             
@@ -1376,13 +1387,13 @@ def uniq_list (l):
 #            ...
 #         ]
 #     ]
-# raw_voices is of the form [(voicename, lyrics)*]
+# raw_voices is of the form [(voicename, lyricsids)*]
 def format_staff_info (part, staff_id, raw_voices):
     voices = []
-    for (v, lyrics) in raw_voices:
+    for (v, lyricsids) in raw_voices:
         voice_name = music_xml_voice_name_to_lily_name (part, v)
         voice_lyrics = [music_xml_lyrics_name_to_lily_name (part, v, l)
-                   for l in lyrics.keys ()]
+                   for l in lyricsids]
         voices.append ([voice_name, voice_lyrics])
     return [staff_id, voices]
 
@@ -1399,8 +1410,8 @@ def update_score_setup (score_structure, part_list, voices):
 
         nv_dict = voices.get (part)
         staves = reduce (lambda x,y: x+ y,
-                [mxlvoice._staves.keys ()
-                 for (v, mxlvoice) in nv_dict.values ()],
+                [voice.voicedata._staves.keys ()
+                 for voice in nv_dict.values ()],
                 [])
         staves_info = []
         if len (staves) > 1:
@@ -1408,13 +1419,14 @@ def update_score_setup (score_structure, part_list, voices):
             staves = uniq_list (staves)
             staves.sort ()
             for s in staves:
-                thisstaff_raw_voices = [(voice_name, lyrics) 
-                    for (voice_name, ((music, lyrics), mxlvoice)) in nv_dict.items ()
-                    if mxlvoice._start_staff == s]
+                #((music, lyrics), mxlvoice))
+                thisstaff_raw_voices = [(voice_name, voice.lyrics_order) 
+                    for (voice_name, voice) in nv_dict.items ()
+                    if voice.voicedata._start_staff == s]
                 staves_info.append (format_staff_info (part, s, thisstaff_raw_voices))
         else:
-            thisstaff_raw_voices = [(voice_name, lyrics
-                for (voice_name, ((music, lyrics), mxlvoice)) in nv_dict.items ()]
+            thisstaff_raw_voices = [(voice_name, voice.lyrics_order
+                for (voice_name, voice) in nv_dict.items ()]
             staves_info.append (format_staff_info (part, None, thisstaff_raw_voices))
         score_structure.setPartInformation (part_name, staves_info)