lilypond-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Issue 913: improve \partcombine when parts have unequal lengths (issue 2


From: nine . fierce . ballads
Subject: Issue 913: improve \partcombine when parts have unequal lengths (issue 267790043 by address@hidden)
Date: Tue, 08 Sep 2015 02:46:23 +0000

Reviewers: ,

Description:
Issue 913: improve \partcombine when parts have unequal lengths

Add terminal entries to Voice-state arrays at the moment the last
event ends.

This also improves Issue 1677 by engraving notes that were missing;
however, it does not resolve it because the rests are still wrong.

Please review this at https://codereview.appspot.com/267790043/

Affected files (+52, -10 lines):
  A input/regression/part-combine-unequal-lengths.ly
  M scm/part-combiner.scm


Index: input/regression/part-combine-unequal-lengths.ly
diff --git a/input/regression/part-combine-unequal-lengths.ly b/input/regression/part-combine-unequal-lengths.ly
new file mode 100644
index 0000000000000000000000000000000000000000..8b7c23bd3bf8f8650bfb54a8d6f074db3288eadd
--- /dev/null
+++ b/input/regression/part-combine-unequal-lengths.ly
@@ -0,0 +1,13 @@
+\version "2.19.27"
+
+\header {
+  texidoc ="The part combiner can combine parts of unequal lengths."
+}
+
+\layout { ragged-right = ##t }
+
+\new Staff { %% based on the example in Issue 913
+  c'1
+  \partcombine { e' r } { c' }
+  c'
+}
Index: scm/part-combiner.scm
diff --git a/scm/part-combiner.scm b/scm/part-combiner.scm
index 85548030ecaddb33cde537a8c4d731d3b9afedaf..d7361864b7ed6c2262509bfe88b0482719a26854 100644
--- a/scm/part-combiner.scm
+++ b/scm/part-combiner.scm
@@ -39,6 +39,20 @@
   (display (span-state x) file)
   (display "\n" file))

+;; Return the duration of the longest event in the Voice-state.
+(define-method (duration (vs <Voice-state>))
+  (define (duration-max event d1)
+    (let ((d2 (ly:event-property event 'duration #f)))
+      (if d2
+          (if (ly:duration<? d1 d2) d2 d1)
+          d1)))
+
+  (fold duration-max (ly:make-duration 0 0 0) (events vs)))
+
+;; Return the moment that the longest event in the Voice-state ends.
+(define-method (end-moment (vs <Voice-state>))
+  (ly:moment-add (moment vs) (ly:duration-length (duration vs))))
+
 (define-method (note-events (vs <Voice-state>))
   (define (f? x)
     (ly:in-event-class? x 'note-event))
@@ -129,16 +143,31 @@ return the previous voice state."
     (if p (span-state p) '())))

 (define (make-voice-states evl)
-  (let ((vec (list->vector (map (lambda (v)
-                                  (make <Voice-state>
-                                    #:moment (caar v)
-                                    #:tuning (cdar v)
-                                    #:events (map car (cdr v))))
-                                evl))))
-    (do ((i 0 (1+ i)))
-        ((= i (vector-length vec)) vec)
-      (slot-set! (vector-ref vec i) 'vector-index i)
-      (slot-set! (vector-ref vec i) 'state-vector vec))))
+  (let* ((states (map (lambda (v)
+                        (make <Voice-state>
+                          #:moment (caar v)
+                          #:tuning (cdar v)
+                          #:events (map car (cdr v))))
+                      (reverse evl)))
+         (last-real-event (car states)))
+
+    ;; add an entry with no events at the moment the last event ends
+    (set! states
+          (cons (make <Voice-state>
+                  #:moment (end-moment last-real-event)
+                  #:tuning (tuning last-real-event)
+                  #:events '())
+                states))
+
+    ;; TODO: Add an entry at +inf.0 and see if it allows us to remove
+    ;; the many instances of conditional code handling the case that
+    ;; there is no voice state at a given moment.
+
+    (let ((vec (list->vector (reverse! states))))
+      (do ((i 0 (1+ i)))
+          ((= i (vector-length vec)) vec)
+        (slot-set! (vector-ref vec i) 'vector-index i)
+        (slot-set! (vector-ref vec i) 'state-vector vec)))))

 (define (make-split-state vs1 vs2)
   "Merge lists VS1 and VS2, containing Voice-state objects into vector





reply via email to

[Prev in Thread] Current Thread [Next in Thread]