Here is a possible solution for the problem you get when you put all your
\repeat volta structure in a separate variable (often named global) and
then you want unfold all your music (for MIDI output for
example).
.
The "globalizeMusic.ly" (see joined files ) proposes a function
\globalizeMusic that can be used like this :
%%
\globalizeMusic \global
\new StaffGroup
{<<
\new Staff \musicA
\new Staff \musicB
>>}
%%
it will have the same effects than
%%
\new StaffGroup
{<<
\new Staff <<\global \musicA>>
\new Staff <<global \musicB>>
>>}
%%
BUT all the \repeat volta .. will be copied inside each Staff
so that you 'll get the right music when you call \unfoldRepeats.
Hope it will be usefull.
Gilles
NB
"globalizeMusic.ly" uses "extractMusic.ly" described here :
http://lsr.dsi.unimi.it/LSR/Item?id=542
#(use-modules (srfi srfi-39))
#(define *current-moment* (make-parameter (ly:make-moment 0 1 0 1)))
#(define moment-null (ly:make-moment 0 1 0 1))
#(define (music-has-no-lenght? music)
"Is music empty of notes, rests or skips ?"
(equal? (ly:music-length music) moment-null))
#(define (simultaneous? music )
(memq (ly:music-property music 'name)
(list 'SimultaneousMusic 'EventChord)))
#(define (defined-music? music)
(not (eq? 'Music (ly:music-property music 'name))))
#(define (chord-event? music )
(eq? 'EventChord (ly:music-property music 'name)))
#(define (get-duration music )
(ly:music-property music 'duration))
#(define (moment>=? momentA momentB )
(not (ly:moment<? momentA momentB)))
#(define (moment-inside? moment from-moment to-moment)
(and
(moment>=? moment from-moment)
(ly:moment<? moment to-moment)))
#(define (whole-music-inside? begin-music end-music left-range right-range)
(and (moment>=? begin-music left-range)
(moment>=? right-range end-music )
(not (equal? begin-music right-range))))
#(define (whole-music-outside? begin-music end-music left-range right-range)
(or (moment>=? left-range end-music)
(moment>=? begin-music right-range )))
#(define (moment->duration moment) ;% see duration.cc in Lilypond sources (Duration::Duration)
(let* ((p (ly:moment-main-numerator moment))
(q (ly:moment-main-denominator moment))
(k (- (ly:intlog2 q) (ly:intlog2 p)))
(dots 0))
(if (< (ash p k) q) (set! k ( 1+ k))) ;% (ash p k) = p * 2^k
(set! p (- (ash p k) q))
(while (begin (set! p (ash p 1))(>= p q))
(set! p (- p q))
(set! dots (1+ dots)))
(if (> k 6)
(ly:make-duration 6 0)
(ly:make-duration k dots))
))
#(define (set-rest-duration moment)
(ly:make-duration 0
0
(ly:moment-main-numerator moment)
(ly:moment-main-denominator moment)))
#(define (extract-music music from to)
"Keeps only music beetween `from' and `to', `from' and `to' as moment"
(let ((begin-pos (*current-moment*))
(end-pos (ly:moment-add (*current-moment*) (ly:music-length music))))
(cond
((whole-music-inside? begin-pos end-pos from to)
(*current-moment* end-pos)
music)
((whole-music-outside? begin-pos end-pos from to)
(*current-moment* end-pos)
(make-music 'Music))
(else ;% the intervals [begin-pos end-pos][from to] overlaps
(cond ;% inside a chords or for multiRest events
((ly:duration? (get-duration music))
(if (moment-inside? begin-pos from to)
(set! end-pos to)
(begin
(set! begin-pos from)
(if (not (moment-inside? end-pos from to))(set! end-pos to))))
(ly:music-set-property! music 'duration
(if (eq? 'MultiMeasureRestMusic (ly:music-property music 'name))
(set-rest-duration (ly:moment-sub end-pos begin-pos))
(moment->duration (ly:moment-sub end-pos begin-pos))))
(*current-moment* end-pos)
music)
(else ;% for containers of chords
(let ((elts (ly:music-property music 'elements))
(elt (ly:music-property music 'element)))
(if (ly:music? elt)
(ly:music-set-property! music 'element (extract-music elt from to)))
(if (pair? elts)
(cond
((simultaneous? music) ;% simultaneous music OR EventChords
(ly:music-set-property! music 'elements (filter
(lambda (evt)
(or (music-has-no-lenght? evt) ;% i.e for 'VoiceSeparator
(begin
(*current-moment* begin-pos) ;% restore *current-moment*
(set! evt (extract-music evt from to))
(defined-music? evt))))
elts))
(*current-moment* end-pos))
(else ;% sequential music
(ly:music-set-property! music 'elements (filter
(lambda (evt)
(set! evt (extract-music evt from to))
(defined-music? evt))
elts)))))
music)))))))
%%%%%%%%%%%%%%%%%%%%%% the main function %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
extractMusic =#(define-music-function (parser location music from during)
(ly:music? ly:music? ly:music?)
(let* ((from-length (ly:music-length from))
(during-length (ly:music-length during))
(to-length (ly:moment-add during-length from-length)))
(parameterize ((*current-moment* (ly:make-moment 0 1 0 1)))
(extract-music music from-length to-length))))
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% derived functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
extractBegin =#(define-music-function (parser location music during)( ly:music? ly:music?)
#{ \extractMusic $music s16*0 $during #})
extractEnd =#(define-music-function (parser location music from)( ly:music? ly:music?)
#{ \extractMusic $music $from s16*1000 #})
insertMusic =#(define-music-function (parser location music where musicToInsert )
(ly:music? ly:music? ly:music?)
#{
\extractBegin $music $where
$musicToInsert
\extractEnd $music $where
#})
remplaceMusic =#(define-music-function (parser location music where musicToRemplace)
(ly:music? ly:music? ly:music?)
#{
\extractBegin $music $where
$musicToRemplace
\extractEnd $music { $where $musicToRemplace }
#})
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%% shortcuts %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(define eM extractMusic)
#(define eB extractBegin)
#(define eE extractEnd)
#(define iM insertMusic)
#(define rM remplaceMusic)
\include "extractMusic.ly"
#(define (extract-during music from during)
(parameterize ((*current-moment* (ly:make-moment 0 1 0 1)))
(extract-music
(ly:music-deep-copy music)
from
(ly:moment-add from during))))
%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(define (get-volta-info-list music current-list)
(let ((elts (ly:music-property music 'elements))
(elt (ly:music-property music 'element))
(duration? (ly:duration? (get-duration music)))
(volta-music? (eq? 'VoltaRepeatedMusic (ly:music-property music 'name))))
(if volta-music?
(set! current-list (append current-list (list (append
(list (*current-moment*)
(ly:music-length elt)
(ly:music-property music 'repeat-count))
(map ly:music-length elts))))))
(if (or volta-music? duration?)
(*current-moment* (ly:moment-add
(*current-moment*)
(ly:music-length music)))
(begin
(if (pair? elts)
(map
(lambda (x)
(set! current-list (get-volta-info-list x current-list)))
elts)
(if (ly:music? elt) (set! current-list (get-volta-info-list elt current-list))))))
current-list))
%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(define (global->list music )
(parameterize ((*current-moment* (ly:make-moment 0 1 0 1)))
(get-volta-info-list music '())))
%%%%%%%%%%%%%%%%%%%%%%%%%%%
#(define (copy-volta-repeats global music)
(let ((repeat-list (global->list global))
(begin-sequence moment-null)
(end-sequence moment-null))
;%(display repeat-list)(newline)
(make-simultaneous-music (list
global
(make-sequential-music (append
(map
(lambda (info)
(let*((begin-elt (car info))
(end-elt (cadr info))
(elt (extract-during music begin-elt end-elt))
(count (car (cddr info)))
(elts (if (< (length info) 4)
'()
(begin
(set! end-sequence (ly:moment-add begin-elt end-elt))
(map (lambda (during)
(let ((save-moment end-sequence))
(set! end-sequence (ly:moment-add end-sequence during))
(extract-during music save-moment during)))
(list-tail info 3)))))
(before-volta (extract-during music begin-sequence
(ly:moment-sub begin-elt begin-sequence)))
(volta-music (make-music 'VoltaRepeatedMusic
'elements elts 'repeat-count count 'element elt )))
(set! begin-sequence end-sequence)
(make-sequential-music (list
before-volta
volta-music))))
repeat-list)
(list (extract-during music begin-sequence (ly:make-moment 10000000 1 0 1)))))
))))
%%%%%%%%%%%%%%%%%%%%%%%%%
#(define (globalize-music global music)
(let ((elts (ly:music-property music 'elements))
(elt (ly:music-property music 'element))
(staff? (and
(eq? (ly:music-property music 'name) 'ContextSpeccedMusic)
(eq? (ly:music-property music 'context-type) 'Staff))))
(if staff?
(ly:music-set-property! music 'element (copy-volta-repeats global elt))
(begin
(if (ly:music? elt)(ly:music-set-property! music 'element (globalize-music global elt)))
(if (pair? elts)(ly:music-set-property! music 'elements
(map (lambda (evt)(globalize-music global evt))
elts)))))
music
))
%%%%%%%%%%%%%%%%%%%%%%%%%%% the main function %%%%%%%%%%%%%%%%%%
globalizeMusic = #(define-music-function (parser location global music)(ly:music? ly:music?)
(globalize-music global music))
\include "globalizeMusic.ly"
#(set-global-staff-size 16)
musicA = \relative {e1 e e e f1 f f g g a a
b1 c c c d1 e e f f g g}
musicB = \relative {c1 c c c d1 d d e e f f
g a a a b c c d d e e }
global = {
s1*4
\repeat "volta" 2 { s1*3^"A" }
\alternative {
{ s1*2 }
{ s1 }}
s1^"B"
s1*4
\repeat "volta" 2 { s1*3^"C" }
\alternative {
{ s1*2 }
{ s1 }}
s1
}
scoreOld =\new StaffGroup
{<<
\new Staff <<\global \musicA >>
\new Staff <<\global \musicB>>
>>}
scoreNew = \globalizeMusic \global
\new StaffGroup
{<<
\new Staff \musicA
\new Staff \musicB
>>}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\score { \scoreOld
\header { piece = "Repeats - traditionnal way"}
}
\score { \scoreNew
\header { piece = "Repeats - with \\globalizeMusic (same result)"}
}
\score { \unfoldRepeats \scoreOld
\header { piece = "unfoldRepeats - traditionnal way (problems...)"}
}
\score { \unfoldRepeats \scoreNew
\header { piece = "unfoldRepeats with \\globalizeMusic"}
}
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
http://lists.gnu.org/mailman/listinfo/lilypond-user