]> git.donarmstrong.com Git - lilypond.git/commitdiff
MusicXML: Add support for chord names
authorReinhold Kainhofer <reinhold@kainhofer.com>
Fri, 11 Apr 2008 15:05:05 +0000 (17:05 +0200)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Fri, 11 Apr 2008 15:05:05 +0000 (17:05 +0200)
Implemented it similar to FiguredBass (using its own voice builder).
The duration of a chord is always the duration of the next following
note (MusicXML does not have the concept of duration for a chord...)

input/regression/musicxml/17f-AllChordTypes.xml [new file with mode: 0644]
python/musicexp.py
python/musicxml.py
scripts/musicxml2ly.py

diff --git a/input/regression/musicxml/17f-AllChordTypes.xml b/input/regression/musicxml/17f-AllChordTypes.xml
new file mode 100644 (file)
index 0000000..18433bb
--- /dev/null
@@ -0,0 +1,444 @@
+<?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>All MusicXM chord names/types</movement-title>\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>Acoustic Grand Piano</instrument-name>\r
+      </score-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
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>major</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>minor</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>augmented</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>diminished</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+    </measure>\r
+    <!--=======================================================-->\r
+    <measure number="2">\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>dominant</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>major-seventh</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>minor-seventh</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>diminished-seventh</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+    </measure>\r
+    <!--=======================================================-->\r
+    <measure number="3">\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>augmented-seventh</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>half-diminished</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>major-minor</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>major-sixth</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+    </measure>\r
+    <!--=======================================================-->\r
+    <measure number="4">\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>minor-sixth</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>dominant-ninth</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>major-ninth</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>minor-ninth</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+    </measure>\r
+    <!--=======================================================-->\r
+    <measure number="5">\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>dominant-11th</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>major-11th</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>minor-11th</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>dominant-13th</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+    </measure>\r
+    <!--=======================================================-->\r
+    <measure number="6">\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>major-13th</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>minor-13th</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>suspended-second</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>suspended-fourth</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+    </measure>\r
+    <!--=======================================================-->\r
+    <measure number="7">\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>Neapolitan</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>Italian</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>French</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>German</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+    </measure>\r
+    <!--=======================================================-->\r
+    <measure number="8">\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>pedal</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>power</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>Tristan</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\r
+      </note>\r
+      <harmony>\r
+        <root>\r
+          <root-step>C</root-step>\r
+        </root>\r
+        <kind>other</kind>\r
+      </harmony>\r
+      <note>\r
+        <pitch><step>C</step><octave>4</octave></pitch>\r
+        <duration>1</duration>\r
+        <voice>1</voice>\r
+        <type>quarter</type>\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 0346e91f4c96df400292d751f6a3641d96af63f4..00b288176c766b091d8da194057a3664c625606b 100644 (file)
@@ -719,7 +719,15 @@ class ChordEvent (NestedMusic):
         for e in self.elements:
             l = max(l, e.get_length())
         return l
-    
+
+    def get_duration (self):
+        note_events = [e for e in self.elements if
+               isinstance (e, NoteEvent)]
+        if note_events:
+            return note_events[0].duration
+        else:
+            return None
+
     def print_ly (self, printer):
         note_events = [e for e in self.elements if
                isinstance (e, NoteEvent)]
@@ -757,7 +765,9 @@ class ChordEvent (NestedMusic):
                     basepitch = previous_pitch
             printer ('<%s>' % string.join (pitches))
             previous_pitch = basepitch
-            note_events[0].duration.print_ly (printer)
+            duration = self.get_duration ()
+            if duration:
+                duration.print_ly (printer)
         else:
             pass
         
@@ -1089,6 +1099,33 @@ class FretEvent (MarkupEvent):
         else:
             return ''
 
+class ChordRoot:
+    def __init__ (self):
+        self.alteration = 0
+        self.step = 0
+    def __repr__(self):
+        return self.ly_expression()
+    def ly_expression (self): 
+        return pitch_generating_function (self)
+
+class ChordNameEvent (Event):
+    def __init__ (self):
+        Event.__init__ (self)
+        self.root = None
+        self.kind = None
+        self.duration = None
+    def ly_expression (self):
+        if not self.root:
+            return ''
+        value = self.root.ly_expression ()
+        if self.duration:
+            value += self.duration.ly_expression ()
+        if self.kind:
+            value += ":"
+            value += self.kind
+        return value
+
+
 class TremoloEvent (ArticulationEvent):
     def __init__ (self):
         Event.__init__ (self)
@@ -1494,8 +1531,10 @@ class Staff (StaffGroup):
             printer.newline ()
             n = 0
             nr_voices = len (voices)
-            for [v, lyrics, figuredbass] in voices:
+            for [v, lyrics, figuredbass, chordnames] in voices:
                 n += 1
+                if chordnames:
+                    printer ('\context ChordNames = "%s" \\%s' % (chordnames, chordnames))
                 voice_count_text = ''
                 if nr_voices > 1:
                     voice_count_text = {1: ' \\voiceOne', 2: ' \\voiceTwo',
index 194fffbd9c709dbf418114b5de59a3be266ae3f7..c71bf2d0be68ba9cecd8fe9ca88900a32b19187b 100644 (file)
@@ -872,6 +872,17 @@ class Words (Music_xml_node):
 class Harmony (Music_xml_node):
     pass
 
+class Root (Music_xml_node):
+    def get_step (self):
+        ch = self.get_unique_typed_child (get_class (u'root-step'))
+        return ch.get_text ().strip ()
+    def get_alteration (self):
+        ch = self.get_maybe_exist_typed_child (get_class (u'root-alter'))
+        alter = 0
+        if ch:
+            alter = int (ch.get_text ().strip ())
+        return alter
+
 class Frame (Music_xml_node):
     def get_frets (self):
         return self.get_named_child_value_number ('frame-frets', 4)
@@ -879,6 +890,7 @@ class Frame (Music_xml_node):
         return self.get_named_child_value_number ('frame-strings', 6)
     def get_first_fret (self):
         return self.get_named_child_value_number ('first-fret', 1)
+
 class Frame_Note (Music_xml_node):
     def get_string (self):
         return self.get_named_child_value_number ('string', 1)
@@ -947,7 +959,8 @@ class_dict = {
         'per-minute': PerMinute,
        'pitch': Pitch,
        'rest': Rest,
-    'score-part': Score_part,
+        'root': Root,
+        'score-part': Score_part,
         'slide': Slide,
        'slur': Slur,
        'staff': Staff,
index a2b27e6aad18603c3d40c4c577f09f79b4b5f566..c7b1000349d7882eaf1e0cf38bdf67136755a194 100644 (file)
@@ -1308,6 +1308,86 @@ def musicxml_harmony_to_lily (n):
         ev = musicxml_frame_to_lily_event (f)
         if ev:
             res.append (ev)
+    return res
+
+
+def musicxml_chordroot_to_lily (mxl_root):
+    r = musicexp.ChordRoot ()
+    r.alteration = mxl_root.get_alteration ()
+    r.step = musicxml_step_to_lily (mxl_root.get_step ())
+    return r
+
+chordkind_dict = {
+    'major': '',
+    'minor': 'm',
+    'augmented': 'aug',
+    'diminished': 'dim',
+        # Sevenths:
+    'dominant': '7',
+    'major-seventh': 'maj',
+    'minor-seventh': 'm7',
+    'diminished-seventh': 'dim7',
+    'augmented-seventh': 'aug7',
+    #'half-diminished': '???', (diminished triad, minor seventh)
+    #'major-minor': '???', (minor triad, major seventh)
+        # Sixths:
+    'major-sixth': '6',
+    'minor-sixth': 'm6',
+        # Ninths:
+    'dominant-ninth': '9',
+    'major-ninth': 'maj9',
+    'minor-ninth': 'm9',
+        # 11ths (usually as the basis for alteration):
+    'dominant-11th': '11',
+    'major-11th': 'maj11',
+    'minor-11th': 'm11',
+        # 13ths (usually as the basis for alteration):
+    'dominant-13th': '13',
+    'major-13th': 'maj13',
+    'minor-13th': 'm13',
+        # Suspended:
+    'suspended-second': 'sus2',
+    'suspended-fourth': 'sus4',
+        # Functional sixths:
+    #'Neapolitan': '???',
+    #'Italian': '???',
+    #'French': '???',
+    #'German': '???',
+        # Other:
+    #'pedal': '???',(pedal-point bass)
+    #'power': '???',(perfect fifth)
+    #'Tristan': '???',
+    #'other': '',
+    'none': '',
+}
+
+def musicxml_chordkind_to_lily (kind):
+    res = chordkind_dict.get (kind, None)
+    if not res:
+        error_message (_ ("Unable to convert chord type %s to lilypond.") % kind)
+    return res
+
+def musicxml_harmony_to_lily_chordname (n):
+    res = []
+    root = n.get_maybe_exist_named_child ('root')
+    if root:
+        ev = musicexp.ChordNameEvent ()
+        ev.root = musicxml_chordroot_to_lily (root)
+        kind = n.get_maybe_exist_named_child ('kind')
+        if kind:
+            ev.kind = musicxml_chordkind_to_lily (kind.get_text ())
+        #TODO: convert the user-symbols attribute: 
+            #major: a triangle, like Unicode 25B3
+            #minor: -, like Unicode 002D
+            #augmented: +, like Unicode 002B
+            #diminished: (degree), like Unicode 00B0
+            #half-diminished: (o with slash), like Unicode 00F8
+        # TODO: Convert the inversion and bass children
+        for deg in n.get_named_children ('degree'):
+            # TODO: Convert the added/removed degrees to lilypond
+            pass
+        if ev and ev.root:
+            res.append (ev)
 
     return res
 
@@ -1556,6 +1636,7 @@ class VoiceData:
         self.voicedata = None
         self.ly_voice = None
         self.figured_bass = None
+        self.chordnames = None
         self.lyrics_dict = {}
         self.lyrics_order = []
 
@@ -1585,6 +1666,7 @@ def musicxml_voice_to_lily_voice (voice):
     current_staff = None
     
     pending_figured_bass = []
+    pending_chordnames = []
 
     # Make sure that the keys in the dict don't get reordered, since
     # we need the correct ordering of the lyrics stanzas! By default,
@@ -1595,6 +1677,7 @@ def musicxml_voice_to_lily_voice (voice):
 
     voice_builder = LilyPondVoiceBuilder ()
     figured_bass_builder = LilyPondVoiceBuilder ()
+    chordnames_builder = LilyPondVoiceBuilder ()
 
     for n in voice._elements:
         if n.get_name () == 'forward':
@@ -1626,8 +1709,10 @@ def musicxml_voice_to_lily_voice (voice):
                     voice_builder.add_dynamics (a)
                 else:
                     voice_builder.add_command (a)
+            for a in musicxml_harmony_to_lily_chordname (n):
+                pending_chordnames.append (a)
             continue
-        
+
         if isinstance (n, musicxml.FiguredBass):
             a = musicxml_figured_bass_to_lily (n)
             if a:
@@ -1650,6 +1735,8 @@ def musicxml_voice_to_lily_voice (voice):
                     number = 0
                 if number > 0:
                     voice_builder.add_bar_check (number)
+                    figured_bass_builder.add_bar_check (number)
+                    chordnames_builder.add_bar_check (number)
 
             for a in musicxml_attributes_to_lily (n):
                 voice_builder.add_command (a)
@@ -1725,13 +1812,28 @@ def musicxml_voice_to_lily_voice (voice):
         # if we have a figured bass, set its voice builder to the correct position
         # and insert the pending figures
         if pending_figured_bass:
-          try:
-              figured_bass_builder.jumpto (n._when)
-          except NegativeSkip, neg:
-              pass
-          for fb in pending_figured_bass:
-              figured_bass_builder.add_music (fb, fb.real_duration)
-          pending_figured_bass = []
+            try:
+                figured_bass_builder.jumpto (n._when)
+            except NegativeSkip, neg:
+                pass
+            for fb in pending_figured_bass:
+                # if a duration is given, use that, otherwise the one of the note
+                dur = fb.real_duration
+                if not dur:
+                    dur = ev_chord.get_length ()
+                figured_bass_builder.add_music (fb, dur)
+            pending_figured_bass = []
+        
+        if pending_chordnames:
+            try:
+                chordnames_builder.jumpto (n._when)
+            except NegativeSkip, neg:
+                pass
+            for cn in pending_chordnames:
+                # Assign the duration of the EventChord
+                cn.duration = ev_chord.get_duration ()
+                chordnames_builder.add_music (cn, ev_chord.get_length ())
+            pending_chordnames = []
 
 
         notations_children = n.get_typed_children (musicxml.Notations)
@@ -1918,6 +2020,15 @@ def musicxml_voice_to_lily_voice (voice):
         v.element = fbass_music
         return_value.figured_bass = v
     
+    # create \chordmode { chords }
+    if chordnames_builder.elements:
+        cname_music = musicexp.SequentialMusic ()
+        cname_music.elements = chordnames_builder.elements
+        v = musicexp.ModeChangingMusicWrapper()
+        v.mode = 'chordmode'
+        v.element = cname_music
+        return_value.chordnames = v
+    
     return return_value
 
 def musicxml_id_to_lily (id):
@@ -2088,6 +2199,10 @@ def music_xml_figuredbass_name_to_lily_name (part_id, voicename):
     str = "Part%sVoice%sFiguredBass" % (part_id, voicename)
     return musicxml_id_to_lily (str) 
 
+def music_xml_chordnames_name_to_lily_name (part_id, voicename):
+    str = "Part%sVoice%sChords" % (part_id, voicename)
+    return musicxml_id_to_lily (str) 
+
 def print_voice_definitions (printer, part_list, voices):
     for part in part_list:
         part_id = part.id
@@ -2097,6 +2212,11 @@ def print_voice_definitions (printer, part_list, voices):
             printer.dump ('%s = ' % k)
             voice.ly_voice.print_ly (printer)
             printer.newline()
+            if voice.chordnames:
+                cnname = music_xml_chordnames_name_to_lily_name (part_id, name)
+                printer.dump ('%s = ' % cnname )
+                voice.chordnames.print_ly (printer)
+                printer.newline()
             for l in voice.lyrics_order:
                 lname = music_xml_lyrics_name_to_lily_name (part_id, name, l)
                 printer.dump ('%s = ' % lname )
@@ -2123,14 +2243,17 @@ def uniq_list (l):
 # raw_voices is of the form [(voicename, lyricsids, havefiguredbass)*]
 def format_staff_info (part_id, staff_id, raw_voices):
     voices = []
-    for (v, lyricsids, figured_bass) in raw_voices:
+    for (v, lyricsids, figured_bass, chordnames) in raw_voices:
         voice_name = music_xml_voice_name_to_lily_name (part_id, v)
         voice_lyrics = [music_xml_lyrics_name_to_lily_name (part_id, v, l)
                    for l in lyricsids]
         figured_bass_name = ''
         if figured_bass:
             figured_bass_name = music_xml_figuredbass_name_to_lily_name (part_id, v)
-        voices.append ([voice_name, voice_lyrics, figured_bass_name])
+        chordnames_name = ''
+        if chordnames:
+            chordnames_name = music_xml_chordnames_name_to_lily_name (part_id, v)
+        voices.append ([voice_name, voice_lyrics, figured_bass_name, chordnames_name])
     return [staff_id, voices]
 
 def update_score_setup (score_structure, part_list, voices):
@@ -2152,12 +2275,12 @@ def update_score_setup (score_structure, part_list, voices):
             staves = uniq_list (staves)
             staves.sort ()
             for s in staves:
-                thisstaff_raw_voices = [(voice_name, voice.lyrics_order, voice.figured_bass) 
+                thisstaff_raw_voices = [(voice_name, voice.lyrics_order, voice.figured_bass, voice.chordnames
                     for (voice_name, voice) in nv_dict.items ()
                     if voice.voicedata._start_staff == s]
                 staves_info.append (format_staff_info (part_id, s, thisstaff_raw_voices))
         else:
-            thisstaff_raw_voices = [(voice_name, voice.lyrics_order, voice.figured_bass) 
+            thisstaff_raw_voices = [(voice_name, voice.lyrics_order, voice.figured_bass, voice.chordnames
                 for (voice_name, voice) in nv_dict.items ()]
             staves_info.append (format_staff_info (part_id, None, thisstaff_raw_voices))
         score_structure.set_part_information (part_id, staves_info)