[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Another time model (related to the usability thread)
From: |
Keith OHara |
Subject: |
Re: Another time model (related to the usability thread) |
Date: |
Mon, 30 Dec 2013 19:15:56 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
Kieren MacMillan <kieren_macmillan <at> sympatico.ca> writes:
> > If you insert a bar, you'd have to change R1*32 to R1*33 by hand. Or,
if you
> > change the 10th out of the 32 bars into a 3/4 measure, I believe you
would
> > then have to change R1*32 to "R1*9 R2. R1*22" -- highly error prone.
>
> \pushToTag was designed (by David K, and paid for in part by a bounty
from me) to solve exactly that problem.
> Now all one needs is a function to take skips (e.g., from a global
variable) and turn them into
> multi-measure-rests — which is probably relatively easy to do — and
there's no more problem. =)
>
The \pushToTag function does not insert skips of the correct length.
It inserts existing pieces of music into other music without adjusting
lengths, nor computing any lengths.
It would be helpful for LilyPond to compute rest-lengths for us.
I am playing around with the idea of eventually making R1\until#'coda
repeat itself until LilyPond sees 'coda somewhere in the score.
Here is a toy version, using the existing input R1\tag#'coda
It requires "\alignTo \global {..}" where \global contains a
sequence with the tags at the desired times.
global = << {
\tag #'intro \mark"intro"
\time 4/4 \repeat unfold 5 s1
\bar"||" \time 3/4 s4*3*5
\tag #'verse \mark"verse"
\bar"||" \time 2/4 s4*2*5
\tag #'bridge \mark"bridge"
\bar"||" \time 2/2 s1*5
\tag #'coda \mark"coda"
\bar"||" \time 9/8 s8*9*5
\bar "|." }
\relative c'' {
\repeat unfold 65 c4
\repeat unfold 15 c4.
} >>
<<\new Staff \global
\new Staff \alignTo \global \transpose c c' {
\repeat unfold 3 b1
R1\tag#'verse
b2 b2
R2\tag#'bridge
c'1
R1\tag#'coda
d'2. d'4. R1 } >>
%=====with this included before the input above=========
\version "2.16"
% vim: filetype=lilypond:
alignTo = #(define-music-function
(parser location conductor music) (ly:music? ly:music?)
"Lengthen any note or rest in the sequence MUSIC just before each tag
that matches a tag in the sequence CONDUCTOR, so that the tags occur
at the same times from to the beginnings of MUSIC and CONDUCTOR."
(define (find-sequence music)
(or (fold-some-music
(lambda (x) (music-is-of-type? x 'sequential-music))
(lambda (x e1) (or e1 ; use the first nonempty sequence
(let ((es (ly:music-property x 'elements)))
(if (null? es) #f es))))
#f
music)
(begin
(ly:input-warning (ly:music-property music 'origin)
"alignTo: cannot find sequential music")
'())))
(let loop ((aligner (find-sequence conductor))
(alignee (find-sequence music))
(time-left (ly:music-length conductor)))
(case (length alignee)
((0) music)
((1) (ly:music-set-property! (car alignee) 'duration
(make-duration-of-length time-left))
music)
(else
(let* ((a (first alignee)) ; music that might be lengthened,
(b (second alignee)) ; if this music is tagged
(tag (ly:music-property b 'tags))
(tail (and (not (null? tag))
(find-tail
(lambda (x)
(not (null? (lset-intersection
eq? tag
(ly:music-property x 'tags)))))
aligner))))
(if tail
(let ((tail-length (ly:music-length
(make-sequential-music tail))))
(if (ly:moment<? time-left tail-length)
(ly:input-warning (ly:music-property b 'origin)
"alignTo: already beyond conductor's tag ~a"
(lset-intersection
eq? tag
(ly:music-property (car tail) 'tags)))
(ly:music-set-property!
a 'duration (make-duration-of-length
(ly:moment-sub time-left
tail-length))))))
(loop (or tail aligner)
(cdr alignee)
(ly:moment-sub time-left
(ly:music-length a))))))))