lilypond-devel
[Top][All Lists]
Advanced

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

parallel relative music (was Re: Yet Another music macro proposal)


From: Nicolas Sceaux
Subject: parallel relative music (was Re: Yet Another music macro proposal)
Date: Sat, 13 May 2006 14:06:39 +0200
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (darwin)

Werner LEMBERG <address@hidden> writes:

>> Your post just reminded me that I've written a version of \parallelMusic
>> with relative mode after a request by Werner (and I forgot about it
>> during holidays).
>
> Aaah!  Is this mature enough that you can send it to the list?
>
>     Werner

Here is a patch introducing a \parallelRelativeMusic function, but I'm
not sure if it is really convenient. At each new bar, you have to
specify the absolute octave of the first note:

\version "2.9.5"

\parallelMusic #'(A B) {
  c'4 d' e' c' | c4 g, c2 |
  c'4 d' e' c' | c4 g, c2 |
}
%% <==>
\parallelRelativeMusic #'(C D) {
  c'4 d e c | c4 g c2 |
  c'4 d e c | c4 g c2 |
}

<<
  \new Staff { \A \C }
  \new Staff { \clef bass \B \D }
>>

May you try it and see whether it fits your needs?

nicolas
 

Index: ly/music-functions-init.ly
===================================================================
RCS file: /cvsroot/lilypond/lilypond/ly/music-functions-init.ly,v
retrieving revision 1.57
diff -u -r1.57 music-functions-init.ly
--- ly/music-functions-init.ly  6 May 2006 00:21:04 -0000       1.57
+++ ly/music-functions-init.ly  13 May 2006 11:59:04 -0000
@@ -319,42 +319,48 @@
       (list chain-grob-member-functions `(,cons 0 0))
       (check-slope-callbacks comp))))))
 
-
-parallelMusic =
-#(define-music-function (parser location voice-ids music) (list? ly:music?)
-  "Define parallel music sequences, separated by '|' (bar check signs),
-and assign them to the identifiers provided in @var{voice-ids}.
-
address@hidden: a list of music identifiers (symbols containing only letters)
-
address@hidden: a music sequence, containing BarChecks as limiting expressions.
-
-Example:
-  \\parallelMusic #'(A B C) {
-    c c | d d | e e |
-    d d | e e | f f |
-  }
-<==>
-  A = { c c | d d | }
-  B = { d d | e e | }
-  C = { e e | f f | }
-"
-  (let* ((voices (apply circular-list (make-list (length voice-ids) (list))))
-         (current-voices voices)
-         (current-sequence (list)))
+%% Parallel music utilities
+#(use-modules (ice-9 optargs)) % for lambda*
+#(define (relativize-music! music root-pitch)
+   (music-map
+    (let ((previous-pitch root-pitch))
+      (lambda (m)
+        (if (eq? (ly:music-property m 'name) 'NoteEvent)
+            (begin
+              (if (ly:pitch? previous-pitch)
+                  ;; set octave relative to the previous note
+                  (let* ((entered-pitch (ly:music-property m 'pitch))
+                         (pitch-note (ly:pitch-notename entered-pitch))
+                         (prev-pitch-note (ly:pitch-notename previous-pitch)))
+                    (set! (ly:music-property m 'pitch)
+                          (ly:make-pitch (+ (ly:pitch-octave previous-pitch)
+                                            (1+ (ly:pitch-octave 
entered-pitch))
+                                            (cond ((>= (- pitch-note 
prev-pitch-note) 4) -1)
+                                                  ((<= (- pitch-note 
prev-pitch-note) -4) +1)
+                                                  (else 0)))
+                                         pitch-note
+                                         (ly:pitch-alteration 
entered-pitch)))))
+              (set! previous-pitch (ly:music-property m 'pitch))))
+        m))
+    music))
+               
+#(define (parallel-music parser location sequence-ids music relative?)
+   (let* ((sequences (apply circular-list (make-list (length sequence-ids) 
(list))))
+          (current-sequences sequences)
+          (current-sequence (list)))
     ;;
     ;; utilities
     (define (push-music m)
       "Push the music expression into the current sequence"
       (set! current-sequence (cons m current-sequence)))
-    (define (change-voice)
-      "Stores the previously built sequence into the current voice and
-       change to the following voice."
-      (list-set! current-voices 0 (cons (make-music 'SequentialMusic 
+    (define (change-sequence)
+      "Stores the previously built sequence into the current sequence and
+       change to the following sequence."
+      (list-set! current-sequences 0 (cons (make-music 'SequentialMusic 
                                          'elements (reverse! current-sequence))
-                                        (car current-voices)))
+                                        (car current-sequences)))
       (set! current-sequence (list))
-      (set! current-voices (cdr current-voices)))
+      (set! current-sequences (cdr current-sequences)))
     (define (bar-check? m)
       "Checks whether m is a bar check."
       (eq? (ly:music-property m 'name) 'BarCheck))
@@ -368,48 +374,91 @@
                                                       (ly:music-property music 
'elements)))))
                         (and (not (null? origins)) (car origins)))))))
     ;;
-    ;; first, split the music and fill in voices
+    ;; first, split the music and fill in the sequences
     (map-in-order (lambda (m)
                     (push-music m)
-                    (if (bar-check? m) (change-voice)))
+                    (if (bar-check? m) (change-sequence)))
                   (ly:music-property music 'elements))
-    (if (not (null? current-sequence)) (change-voice))
-    ;; un-circularize `voices' and reorder the voices
-    (set! voices (map-in-order (lambda (dummy seqs)
+    (if (not (null? current-sequence)) (change-sequence))
+    ;; un-circularize `sequences' and reorder the seqs
+    (set! sequences (map-in-order (lambda (dummy seqs)
                                  (reverse! seqs))
-                               voice-ids voices))
+                               sequence-ids sequences))
     ;;
-    ;; set origin location of each sequence in each voice
+    ;; If in relative mode, set octaves accordingly
+    (if relative?
+        (for-each (lambda (seqs)
+                    (for-each (lambda (seq)
+                                (relativize-music! seq #f))
+                              seqs))
+                  sequences))
+    ;;
+    ;; set origin location of each sequence
     ;; for better type error tracking
-    (for-each (lambda (voice)
+    (for-each (lambda (sequence)
                 (for-each (lambda (seq)
                             (set! (ly:music-property seq 'origin)
                                   (or (music-origin seq) location)))
-                          voice))
-              voices)
+                          sequence))
+              sequences)
     ;;
     ;; check sequence length
-    (apply for-each (lambda (. seqs)
+    (apply for-each (lambda* (#:rest seqs)
                       (let ((moment-reference (ly:music-length (car seqs))))
                         (for-each (lambda (seq moment)
                                     (if (not (equal? moment moment-reference))
                                         (ly:music-message seq 
                                          "Bars in parallel music don't have 
the same length")))
                           seqs (map-in-order ly:music-length seqs))))
-           voices)
+           sequences)
    ;;
-   ;; bind voice identifiers to the voices
-   (map (lambda (voice-id voice)
-          (ly:parser-define! parser voice-id 
+   ;; bind sequence identifiers to the sequences
+   (map (lambda (sequence-id sequence)
+          (ly:parser-define! parser sequence-id 
                              (make-music 'SequentialMusic 
                                'origin location
-                               'elements voice)))
-        voice-ids voices))
+                               'elements sequence)))
+        sequence-ids sequences))
  ;; Return an empty sequence. this function is actually a "void" function.
  (make-music 'SequentialMusic 'void #t))
 
+parallelMusic =
+#(define-music-function (parser location sequence-ids music) (list? ly:music?)
+  "Define parallel music sequences, separated by '|' (bar check signs),
+and assign them to the identifiers provided in @var{sequence-ids}.
+
address@hidden: a list of music identifiers (symbols containing only letters)
 
address@hidden: a music sequence, containing BarChecks as limiting expressions.
 
+Example:
+  \\parallelMusic #'(A B C) {
+    c c | d d | e e |
+    d d | e e | f f |
+  }
+<==>
+  A = { c c | d d | }
+  B = { d d | e e | }
+  C = { e e | f f | }
+"
+  (parallel-music parser location sequence-ids music #f))
+
+parallelRelativeMusic =
+#(define-music-function (parser location sequence-ids music) (list? ly:music?)
+  "Same as \parallelMusic, but in relative mode: in each block, the first
+note is entered in absolute pitch, the following ones in relative mode.
+
+Example:
+  \\parallelRelativeMusic #'(A B C) {
+    c'' c | d' d | e e |
+    d'' d | e' e | f f |
+  }
+<==>
+  A = { c'' c'' | d'' d'' | }
+  B = { d'  d'  | e'  e'  | }
+  C = { e   e   | f   f   | }
+"
+  (parallel-music parser location sequence-ids music #t))
 
 %% this is a stub. Write your own to suit the spacing tweak output.
 spacingTweaks =

reply via email to

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