]> git.donarmstrong.com Git - lilypond.git/commitdiff
MusicXML: Implement complex time signatures
authorReinhold Kainhofer <reinhold@kainhofer.com>
Mon, 8 Dec 2008 21:45:49 +0000 (22:45 +0100)
committerReinhold Kainhofer <reinhold@kainhofer.com>
Mon, 8 Dec 2008 22:22:45 +0000 (23:22 +0100)
I needed to implement complex time signatures in LilyPond itself, so
I had to copy large portions of lilypond code into the script.
Remove this once LilyPond gets native support for complex time signatures!

python/musicexp.py
scripts/musicxml2ly.py

index 6f181c1980ee2f31d9dfc6cba24bf91663d3e8ab..c8898bcc547be6f9f9131839f24ce2697f7863bc 100644 (file)
@@ -1478,6 +1478,13 @@ class TimeSignatureChange (Music):
         Music.__init__ (self)
         self.fractions = [4,4]
         self.style = None
+    def format_fraction (self, frac):
+        if isinstance (frac, list):
+            l = [self.format_fraction (f) for f in frac]
+            return "(" + string.join (l, " ") + ")"
+        else:
+            return "%s" % frac
+
     def ly_expression (self):
         st = ''
         # Print out the style if we have ome, but the '() should only be 
@@ -1495,11 +1502,9 @@ class TimeSignatureChange (Music):
         # Easy case: self.fractions = [n,d] => normal \time n/d call:
         if len (self.fractions) == 2 and isinstance (self.fractions[0], int):
             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 st + ''
+        elif self.fractions:
+            return st + "\\compoundMeter #'%s" % self.format_fraction (self.fractions)
         else:
-            # TODO: Implement non-standard time-signatures
             return st + ''
     
 class ClefChange (Music):
index fcc24bf0e65db6ce9248ec1ee4a17bcce4e878e6..d5d421ef9d485396306ef6e40772f63520e96a66 100644 (file)
@@ -99,8 +99,108 @@ eyeglasses =  \markup { \with-dimensions #'(0 . 4.4) #'(0 . 2.5) \postscript #ey
            (den (if denominator denominator (ly:event-property ev 'denominator)))
            (num (if numerator numerator (ly:event-property ev 'numerator))))
        (format "~a:~a" den num)))
-"""
+""",
 
+  "compound-time-signature": """%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Formatting of (possibly complex) compound time signatures
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#(define-public (insert-markups l m)
+  (let* ((ll (reverse l)))
+    (let join-markups ((markups (list (car ll)))
+                       (remaining (cdr ll)))
+      (if (pair? remaining)
+        (join-markups (cons (car remaining) (cons m markups)) (cdr remaining))
+        markups))))
+
+% Use a centered-column inside a left-column, because the centered column 
+% moves its reference point to the center, which the left-column undoes. 
+% The center-column also aligns its contented centered, which is not undone...
+#(define-public (format-time-fraction time-sig-fraction)
+  (let* ((revargs (reverse (map number->string time-sig-fraction)))
+         (den (car revargs))
+         (nums (reverse (cdr revargs))))
+    (make-override-markup '(baseline-skip . 0)
+      (make-number-markup 
+        (make-left-column-markup (list
+          (make-center-column-markup (list
+            (make-line-markup (insert-markups nums "+"))
+            den))))))))
+
+#(define-public (format-complex-compound-time time-sig)
+  (let* ((sigs (map format-time-fraction time-sig)))
+    (make-override-markup '(baseline-skip . 0)
+      (make-number-markup
+        (make-line-markup 
+          (insert-markups sigs (make-vcenter-markup "+")))))))
+
+#(define-public (format-compound-time time-sig)
+  (cond
+    ((not (pair? time-sig)) (null-markup))
+    ((pair? (car time-sig)) (format-complex-compound-time time-sig))
+    (else (format-time-fraction time-sig))))
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Measure length calculation of (possibly complex) compound time signatures
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#(define-public (calculate-time-fraction time-sig-fraction)
+  (let* ((revargs (reverse time-sig-fraction))
+         (den (car revargs))
+         (nums (cdr revargs)))
+    (ly:make-moment (apply + nums) den)))
+
+#(define-public (calculate-complex-compound-time time-sig)
+  (let* ((sigs (map calculate-time-fraction time-sig)))
+    (let add-moment ((moment ZERO-MOMENT)
+                     (remaining sigs))
+      (if (pair? remaining)
+        (add-moment (ly:moment-add moment (car remaining)) (cdr remaining))
+        moment))))
+
+#(define-public (calculate-compound-measure-length time-sig)
+  (cond
+    ((not (pair? time-sig)) (ly:make-moment 4 4))
+    ((pair? (car time-sig)) (calculate-complex-compound-time time-sig))
+    (else (calculate-time-fraction time-sig))))
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Base beat lenth
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+#(define-public (calculate-compound-base-beat-full time-sig)
+  (let* ((den (map last time-sig)))
+    (apply max den)))
+
+#(define-public (calculate-compound-base-beat time-sig)
+  (ly:make-moment 1 (cond
+    ((not (pair? time-sig)) 4)
+    ((pair? (car time-sig)) (calculate-compound-base-beat-full time-sig))
+    (else (calculate-compound-base-beat-full (list time-sig))))))
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% The music function to set the complex time signature
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+compoundMeter =
+#(define-music-function (parser location args) (pair?)
+  (let ((mlen (calculate-compound-measure-length args))
+        (beat (calculate-compound-base-beat args)))
+  #{
+\once \override Staff.TimeSignature #'stencil = #ly:text-interface::print
+\once \override Staff.TimeSignature #'text = #(format-compound-time $args)
+% \set Staff.beatGrouping = #(reverse (cdr (reverse $args)))
+\set Timing.measureLength = $mlen
+\set Timing.timeSignatureFraction = #(cons (ly:moment-main-numerator $mlen)
+                                           (ly:moment-main-denominator $mlen))
+\set Timing.beatLength = $beat
+
+% TODO: Implement beatGrouping and auto-beam-settings!!!
+#} ))
+"""
 }
 
 def round_to_two_digits (val):
@@ -743,6 +843,8 @@ def musicxml_time_to_lily (attributes):
         return None
     change = musicexp.TimeSignatureChange()
     change.fractions = sig
+    if (len(sig) != 2) or isinstance (sig[0], list):
+        needed_additional_definitions.append ("compound-time-signature")
 
     time_elm = attributes.get_maybe_exist_named_child ('time')
     if time_elm and hasattr (time_elm, 'symbol'):