]> git.donarmstrong.com Git - lilypond.git/commitdiff
MusicXML: Implement the symbol attribute of time signatures
authorReinhold Kainhofer <reinhold@kainhofer.com>
Sun, 30 Nov 2008 16:46:04 +0000 (17:46 +0100)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Sun, 30 Nov 2008 20:25:20 +0000 (21:25 +0100)
-) Fix time keeping (i.e. use the cached value for the current time sig
   and thus the current measure length!): revert to
   self.get_named_attribute ('time')
-) Implement single-digit time signatures
-) Implement C vs. numeric time signatures; Change the signature style
   to '() only if a C or C/ would be printed (i.e. 2/2 or 4/4).
   By default, MusicXML uses numeric signatures (style '()), while
   LilyPond's default is 'C, so we have to add some manual overrides
   in those cases of 2/2 or 4/4 where no symbol is given in the
   MusicXML file

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

diff --git a/input/regression/musicxml/11f-TimeSignatures-SymbolMeaning.xml b/input/regression/musicxml/11f-TimeSignatures-SymbolMeaning.xml
new file mode 100644 (file)
index 0000000..4787a71
--- /dev/null
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 1.1 Partwise//EN"
+                                "http://www.musicxml.org/dtds/partwise.dtd">
+<score-partwise version="1.1">
+  <identification>
+    <miscellaneous>
+      <miscellaneous-field name="description">A time signature of 3/8 with the 
+          symbol="cut" attribute and two symbol="single-number" attributes with
+          compound time signatures. Shall the symbol be ignored in this 
+          case?</miscellaneous-field>
+    </miscellaneous>
+  </identification>
+  <part-list>
+    <score-part id="P1">
+      <part-name>MusicXML Part</part-name>
+    </score-part>
+  </part-list>
+  <!--=========================================================-->
+  <part id="P1">
+    <measure number="1">
+      <attributes>
+        <divisions>2</divisions>
+        <key>
+          <fifths>0</fifths>
+          <mode>major</mode>
+        </key>
+        <time symbol="cut">
+          <beats>3</beats>
+          <beat-type>8</beat-type>
+        </time>
+        <clef>
+          <sign>G</sign>
+          <line>2</line>
+        </clef>
+      </attributes>
+      <note>
+        <pitch>
+          <step>B</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>3</duration>
+        <voice>1</voice>
+        <type>quarter</type>
+        <dot/>
+      </note>
+    </measure>
+    <!--=========================================================-->
+    <measure number="2">
+      <attributes>
+        <time symbol="single-number">
+          <beats>3+2</beats>
+          <beat-type>8</beat-type>
+        </time>
+      </attributes>
+      <note>
+        <pitch>
+          <step>B</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+      </note>
+      <note>
+        <pitch>
+          <step>B</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>4</duration>
+        <voice>1</voice>
+        <type>half</type>
+      </note>
+    </measure>
+    <!--=========================================================-->
+    <measure number="3">
+      <attributes>
+        <time symbol="single-number">
+          <beats>1</beats>
+          <beat-type>8</beat-type>
+          <beats>2</beats>
+          <beat-type>4</beat-type>
+        </time>
+      </attributes>
+      <note>
+        <pitch>
+          <step>B</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>1</duration>
+        <voice>1</voice>
+        <type>eighth</type>
+      </note>
+      <note>
+        <pitch>
+          <step>B</step>
+          <octave>4</octave>
+        </pitch>
+        <duration>4</duration>
+        <voice>1</voice>
+        <type>half</type>
+      </note>
+      <barline location="right">
+        <bar-style>light-heavy</bar-style>
+      </barline>
+    </measure>
+  </part>
+  <!--=========================================================-->
+</score-partwise>
index e69f2ab9f0c9944889c790a514e8bdf9199ff3ee..c5635a2c020c9cbf82673d2d583fa38a69eabb25 100644 (file)
@@ -1441,16 +1441,26 @@ class TimeSignatureChange (Music):
     def __init__ (self):
         Music.__init__ (self)
         self.fractions = [4,4]
+        self.style = None
     def ly_expression (self):
+        st = ''
+        # Print out the style if we have ome, but the '() should only be 
+        # forced for 2/2 or 4/4, since in all other cases we'll get numeric 
+        # signatures anyway despite the default 'C signature style!
+        is_common_signature = self.fractions in ([2,2], [4,4], [4,2])
+        if self.style:
+            if (self.style != "'()") or is_common_signature:
+                st = "\\once \\override Staff.TimeSignature #'style = #%s " % self.style
+
         # Easy case: self.fractions = [n,d] => normal \time n/d call:
         if len (self.fractions) == 2 and isinstance (self.fractions[0], int):
-            return '\\time %d/%d ' % tuple (self.fractions)
+            return st + '\\time %d/%d ' % tuple (self.fractions)
         elif self.fractions and not isinstance (self.fractions[0], list):
             # TODO: Implement non-standard time-signatures
-            return ''
+            return st + ''
         else:
             # TODO: Implement non-standard time-signatures
-            return ''
+            return st + ''
     
 class ClefChange (Music):
     def __init__ (self):
index 1ababbc7d5ba5dbee466f0deda33f5a57e1cd601..115bfaa4455354099fdaaf7b02b21d3f5d63ece0 100644 (file)
@@ -323,8 +323,8 @@ class Attributes (Measure_element):
 
     def get_measure_length (self):
         sig = self.get_time_signature ()
-        if len (sig) == 0:
-            return 0
+        if not sig or len (sig) == 0:
+            return 1
         if isinstance (sig[0], list):
             # Complex compound time signature
             l = 0
@@ -346,7 +346,7 @@ class Attributes (Measure_element):
         try:
             mxl = self.get_named_attribute ('time')
             if not mxl:
-                return (4, 4)
+                return None
 
             if mxl.get_maybe_exist_named_child ('senza-misura'):
                 # TODO: Handle pieces without a time signature!
@@ -363,17 +363,13 @@ class Attributes (Measure_element):
                         current_sig.append (int (i.get_text ()))
                         signature.append (current_sig)
                         current_sig = []
-                if len (signature) == 1 and isinstance (signature[0], list):
+                if isinstance (signature[0], list) and len (signature) == 1:
                     signature = signature[0]
-                if len (signature) ==0:
-                    error (_ ("requested time signature, but time sig is unknown"))
-                    return (4, 4)
                 self._time_signature_cache = signature
                 return signature
-        except KeyError:
-            error (_ ("requested time signature, but time sig is unknown"))
+        except (KeyError, ValueError):
+            self.message (_ ("Unable to interpret time signature! Falling back to 4/4."))
             return (4, 4)
-        #except 
 
     # returns clef information in the form ("cleftype", position, octave-shift)
     def get_clef_information (self):
index 78d8325c6d5da274871c0d8f30942a93693237ca..e06795d69b257a1a8928b9574b7b9867478912e4 100644 (file)
@@ -738,13 +738,25 @@ def musicxml_clef_to_lily (attributes):
     
 def musicxml_time_to_lily (attributes):
     sig = attributes.get_time_signature ()
-
-    # TODO: Handle single-digit time sigs
-    # TODO: Handle senza-misura measures
-
+    if not sig:
+        return None
     change = musicexp.TimeSignatureChange()
     change.fractions = sig
 
+    time_elm = attributes.get_maybe_exist_named_child ('time')
+    if time_elm and hasattr (time_elm, 'symbol'):
+        change.style = { 'single-number': "'single-digit",
+                         'cut': None,
+                         'common': None,
+                         'normal': "'()"}.get (time_elm.symbol, "'()")
+    else:
+        change.style = "'()"
+
+    # TODO: Handle senza-misura measures
+    # TODO: Handle hidden time signatures (print-object="no")
+    # TODO: What shall we do if the symbol clashes with the sig? e.g. "cut" 
+    #       with 3/8 or "single-number" with (2+3)/8 or 3/8+2/4?
+
     return change
 
 def musicxml_key_to_lily (attributes):
@@ -828,7 +840,9 @@ def musicxml_attributes_to_lily (attrs):
     for (k, func) in attr_dispatch.items ():
         children = attrs.get_named_children (k)
         if children:
-            elts.append (func (attrs))
+            ev = func (attrs)
+            if ev:
+                elts.append (ev)
     
     return elts
 
@@ -1930,11 +1944,10 @@ def musicxml_step_to_lily (step):
        return None
 
 def measure_length_from_attributes (attr, current_measure_length):
-    mxl = attr.get_named_attribute ('time')
-    if mxl:
-        return attr.get_measure_length ()
-    else:
-        return current_measure_length
+    len = attr.get_measure_length ()
+    if not len:
+        len = current_measure_length
+    return len
 
 def musicxml_voice_to_lily_voice (voice):
     tuplet_events = []