[Top][All Lists]
[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 =