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

Reply via email to