From: Reinhold Kainhofer <reinhold@kainhofer.com> Date: Fri, 26 Oct 2007 14:38:08 +0000 (+0200) Subject: MusicXML: Convert fretboards from MusicXML to Lilypond X-Git-Tag: release/2.11.35-1~75 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=c84481ad23d3c527489d491bc589ca99de504c1c;p=lilypond.git MusicXML: Convert fretboards from MusicXML to Lilypond In MusicXML, fretboards are inside <harmony> elements, assigned to a particular staff, while in lilypond the \fret-diagram is a text markup assigned to a particular note. So we run into the same problems as we do with dynamics (i.e. we need to find a proper note to assign the element to, which is not very robust). For single-voice harmony, this works quite well so far. --- diff --git a/input/regression/musicxml/17b-Fretboards-Finale.xml b/input/regression/musicxml/17b-Fretboards-Finale.xml new file mode 100644 index 0000000000..bfd24c5e5f --- /dev/null +++ b/input/regression/musicxml/17b-Fretboards-Finale.xml @@ -0,0 +1,229 @@ +<?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>Fretboards</movement-title> + <identification> + <encoding> + <software>Finale 2007 for Windows</software> + <software>Dolet Light for Finale 2007</software> + <encoding-date>2007-10-25</encoding-date> + </encoding> + </identification> + <part-list> + <score-part id="P1"> + <part-name>MusicXML Part</part-name> + <score-instrument id="P1-I1"> + <instrument-name>Acoustic 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"/> + <harmony default-y="100"> + <root> + <root-step>D</root-step> + </root> + <kind>major</kind> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>2</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>2</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>C</root-step> + </root> + <kind>dominant</kind> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>2</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>1</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>0</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>C</root-step> + </root> + <kind>minor-seventh</kind> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <first-fret>3</first-fret> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>5</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>4</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>3</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>C</root-step> + </root> + <kind>dominant</kind> + <degree> + <degree-value>13</degree-value> + <degree-alter>-1</degree-alter> + <degree-type>add</degree-type> + </degree> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <first-fret>8</first-fret> + <frame-note> + <string>6</string> + <fret>8</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>8</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>9</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>9</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>0</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <barline location="right"> + <bar-style>light-heavy</bar-style> + </barline> + </measure> + </part> + <!--=========================================================--> +</score-partwise> diff --git a/input/regression/musicxml/17c-ChordsFrets-Finale.xml b/input/regression/musicxml/17c-ChordsFrets-Finale.xml new file mode 100644 index 0000000000..06eca4ace3 --- /dev/null +++ b/input/regression/musicxml/17c-ChordsFrets-Finale.xml @@ -0,0 +1,430 @@ +<?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>Chords and fretboards example</movement-title> + <identification> + <encoding> + <software>Finale 2007 for Windows</software> + <software>Dolet Light for Finale 2007</software> + <encoding-date>2007-10-25</encoding-date> + </encoding> + </identification> + <part-list> + <score-part id="P1"> + <part-name>MusicXML Part</part-name> + <score-instrument id="P1-I1"> + <instrument-name>Acoustic 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"/> + <harmony default-y="100"> + <root> + <root-step>C</root-step> + </root> + <kind>major</kind> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>2</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>1</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>0</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>C</root-step> + </root> + <kind>major-seventh</kind> + <degree> + <degree-value>11</degree-value> + <degree-alter>1</degree-alter> + <degree-type>add</degree-type> + </degree> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <first-fret>2</first-fret> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>5</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>4</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>5</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>2</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>B</root-step> + </root> + <kind>dominant</kind> + <degree> + <degree-value>5</degree-value> + <degree-alter>1</degree-alter> + <degree-type>alter</degree-type> + </degree> + <degree> + <degree-value>9</degree-value> + <degree-alter>1</degree-alter> + <degree-type>add</degree-type> + </degree> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>2</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>1</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>2</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>3</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>E</root-step> + <root-alter>-1</root-alter> + </root> + <kind>major</kind> + <degree> + <degree-value>2</degree-value> + <degree-alter>0</degree-alter> + <degree-type>add</degree-type> + </degree> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>5</frame-frets> + <first-fret>11</first-fret> + <frame-note> + <string>6</string> + <fret>11</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>13</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>15</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>12</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>11</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>11</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + </measure> + <!--=======================================================--> + <measure number="2"> + <harmony default-y="100"> + <root> + <root-step>G</root-step> + </root> + <kind>minor</kind> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <first-fret>3</first-fret> + <frame-note> + <string>6</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>5</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>5</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>3</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>D</root-step> + <root-alter>1</root-alter> + </root> + <kind>major-seventh</kind> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>1</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>3</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>A</root-step> + </root> + <kind>diminished-seventh</kind> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>1</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>2</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>1</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>2</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <harmony default-y="100"> + <root> + <root-step>A</root-step> + </root> + <kind>augmented</kind> + <frame> + <frame-strings>6</frame-strings> + <frame-frets>4</frame-frets> + <frame-note> + <string>6</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>5</string> + <fret>0</fret> + </frame-note> + <frame-note> + <string>4</string> + <fret>3</fret> + </frame-note> + <frame-note> + <string>3</string> + <fret>2</fret> + </frame-note> + <frame-note> + <string>2</string> + <fret>2</fret> + </frame-note> + <frame-note> + <string>1</string> + <fret>0</fret> + </frame-note> + </frame> + </harmony> + <note> + <pitch> + <step>A</step> + <octave>4</octave> + </pitch> + <duration>1</duration> + <voice>1</voice> + <type>quarter</type> + <stem>up</stem> + </note> + <barline location="right"> + <bar-style>light-heavy</bar-style> + </barline> + </measure> + </part> + <!--=========================================================--> +</score-partwise> diff --git a/python/musicexp.py b/python/musicexp.py index c4ef903a32..ef896f9e53 100644 --- a/python/musicexp.py +++ b/python/musicexp.py @@ -761,6 +761,8 @@ class ArticulationEvent (Event): def __init__ (self): self.type = None self.force_direction = None + def wait_for_note (self): + return True; def direction_mod (self): return { 1: '^', -1: '_', 0: '-' }.get (self.force_direction, '') @@ -786,6 +788,39 @@ class MarkupEvent (ShortArticulationEvent): def ly_expression (self): if self.contents: return "%s\\markup { %s }" % (self.direction_mod (), self.contents) + else: + return '' + +class FretEvent (MarkupEvent): + def __init__ (self): + MarkupEvent.__init__ (self) + self.force_direction = 1 + self.strings = 6 + self.frets = 4 + self.barre = None + self.elements = [] + def ly_expression (self): + val = "" + if self.strings <> 6: + val += "w:%s;" % self.strings + if self.frets <> 4: + val += "h:%s;" % self.frets + if self.barre and len (self.barre) >= 3: + val += "c:%s-%s-%s;" % (self.barre[0], self.barre[1], self.barre[2]) + have_fingering = False + for i in self.elements: + if len (i) > 1: + val += "%s-%s" % (i[0], i[1]) + if len (i) > 2: + have_fingering = True + val += "-%s" % i[2] + val += ";" + if have_fingering: + val = "f:1;" + val + if val: + return "%s\\markup { \\fret-diagram #\"%s\" }" % (self.direction_mod (), val) + else: + return '' class TremoloEvent (ArticulationEvent): def __init__ (self): diff --git a/python/musicxml.py b/python/musicxml.py index 86eca63bf7..3c38f30828 100644 --- a/python/musicxml.py +++ b/python/musicxml.py @@ -89,6 +89,14 @@ class Xml_node: return cn[0] + def get_named_child_value_number (self, name, default): + n = self.get_maybe_exist_named_child (name) + if n: + return string.atoi (n.get_text()) + else: + return default + + class Music_xml_node (Xml_node): def __init__ (self): Xml_node.__init__ (self) @@ -610,7 +618,7 @@ class Part (Music_xml_node): if not (voice_id or isinstance (n, Attributes) or isinstance (n, Direction) or isinstance (n, Partial) or - isinstance (n, Barline) ): + isinstance (n, Barline) or isinstance (n, Harmony) ): continue if isinstance (n, Attributes) and not start_attr: @@ -630,7 +638,7 @@ class Part (Music_xml_node): voices[v].add_element (n) continue - if isinstance (n, Direction): + if isinstance (n, Direction) or isinstance (n, Harmony): staff_id = n.get_maybe_exist_named_child (u'staff') if staff_id: staff_id = staff_id.get_text () @@ -638,8 +646,11 @@ class Part (Music_xml_node): dir_voices = staff_to_voice_dict.get (staff_id, voices.keys ()) else: dir_voices = voices.keys () - for v in dir_voices: - voices[v].add_element (n) + # assign only to first voice, otherwise we'll have duplicates! + if dir_voices: + voices[dir_voices[0]].add_element (n) + #for v in dir_voices: + #voices[v].add_element (n) continue id = voice_id.get_text () @@ -783,6 +794,30 @@ class Bend (Music_xml_node): class Words (Music_xml_node): pass +class Harmony (Music_xml_node): + pass + +class Frame (Music_xml_node): + def get_frets (self): + return self.get_named_child_value_number ('frame-frets', 4) + def get_strings (self): + 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) + def get_fret (self): + return self.get_named_child_value_number ('fret', 0) + def get_fingering (self): + return self.get_named_child_value_number ('fingering', -1) + def get_barre (self): + n = self.get_maybe_exist_named_child ('barre') + if n: + return getattr (n, 'type', '') + else: + return '' + ## need this, not all classes are instantiated ## for every input file. Only add those classes, that are either directly @@ -801,8 +836,11 @@ class_dict = { 'direction': Direction, 'direction-type': DirType, 'duration': Duration, + 'frame': Frame, + 'frame-note': Frame_Note, 'glissando': Glissando, 'grace': Grace, + 'harmony': Harmony, 'identification': Identification, 'lyric': Lyric, 'measure': Measure, diff --git a/scripts/musicxml2ly.py b/scripts/musicxml2ly.py index 4441f5be68..7238230cb7 100644 --- a/scripts/musicxml2ly.py +++ b/scripts/musicxml2ly.py @@ -737,6 +737,40 @@ def musicxml_direction_to_lily (n): return res +def musicxml_frame_to_lily_event (frame): + ev = musicexp.FretEvent () + ev.strings = frame.get_strings () + ev.frets = frame.get_frets () + #offset = frame.get_first_fret () - 1 + barre = [] + for fn in frame.get_named_children ('frame-note'): + fret = fn.get_fret () + if fret <= 0: + fret = "o" + el = [ fn.get_string (), fret ] + fingering = fn.get_fingering () + if fingering >= 0: + el.append (fingering) + ev.elements.append (el) + b = fn.get_barre () + if b == 'start': + barre[0] = el[0] # start string + barre[2] = el[1] # fret + elif b == 'stop': + barre[1] = el[0] # end string + if barre: + ev.barre = barre + return ev + +def musicxml_harmony_to_lily (n): + res = [] + for f in n.get_named_children ('frame'): + ev = musicxml_frame_to_lily_event (f) + if ev: + res.append (ev) + + return res + instrument_drumtype_dict = { 'Acoustic Snare Drum': 'acousticsnare', 'Side Stick': 'sidestick', @@ -938,7 +972,15 @@ def musicxml_voice_to_lily_voice (voice): else: voice_builder.add_command (a) continue - + + if isinstance (n, musicxml.Harmony): + for a in musicxml_harmony_to_lily (n): + if a.wait_for_note (): + voice_builder.add_dynamics (a) + else: + voice_builder.add_command (a) + continue + is_chord = n.get_maybe_exist_named_child ('chord') if not is_chord: try: