Hi Jan-Peter,
ok, so I played around with your engraver. It does exactly what it needs
to do, but somehow I am not able to get everything to work.
I'll try to explain:
Let's say that I have some music:
music = {
...stuff...
\repeat volta 2 { ... more stuff ... }
}
and want it displayed nicely:
\score {
\new Staff { \music }
}
If I include your engraver here, the calculated time is wrong, because
the repeats are not taken into account.
So I go for the midi-block
\score {
\new Staff { \unfoldRepeats \music }
\midi {
\context {
\Score
\consists ...your code here ...
}
}
}
But it looks like the duration variable is visible within its score
only, see the attached compilable example.
How can I obtain the correct duration in combination with a compact score?
Thanks in advance,
Marc
Am 13.09.2016 um 10:24 schrieb Jan-Peter Voigt:
Hi Marc,
you already received some solutions, but I stumbled across this thread
and just want to quickly show my engraver - perhaps it also helps.
It doesn't read repeats right now, but this may be solved with
\unfoldRepeats and the engraver placed in the midi-block.
The duration-markup-command relies on a global variable and a delayed
stencil - this will not work with multiple scores, as only the duration
of the last score will be displayed. But that is manageable, if needed.
HTH
Jan-Peter
Am 05.09.2016 um 11:01 schrieb Marc Hohl:
Hi list,
I have a couple of songs in my latest theatre project. It would be nice
to have something like "duration: 3'22''" at the end of each song.
Doing this by hand is straightforward:I generate a midi file that sounds
accurate and let it play by timidity – but IMHO it would be less tedious
and less error-prone if lilypond were capable of doing these
calculations itself.
Tempo indications and meter changes have to be taken into account, so
this is probably doable with a special engraver only IIUC.
Has someone else already done something like this? I have no experience
in writing scheme engravers, so any hint would be highly appreciated.
Thanks in advance,
Marc
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user
\version "2.19.47"
%%% engraver definitions
% format seconds as min:sec
#(define-public (format-time dur)
(let* ((minutes (floor (/ dur 60)))
(seconds (round (- dur (* 60 minutes)) ) ))
(format "~2'0d:~2'0d" (inexact->exact minutes) (inexact->exact seconds))
))
% complete duration of score - set after finalizing
duration = 0
% markup command to display complete time
#(define-markup-command (duration layout props)()
(let* ((gauge-stencil (interpret-markup layout props "00:00"))
(x-ext (ly:stencil-extent gauge-stencil X))
(y-ext (ly:stencil-extent gauge-stencil Y)))
(ly:make-stencil
`(delay-stencil-evaluation
,(delay (ly:stencil-expr
(interpret-markup layout props (format-time duration))
)))
x-ext y-ext)
))
calc-duration-engraver =
#(lambda (context)
(let ((dur 0) ; duration in seconds
(start (ly:make-moment 0)) ; last calc-time the duration was calculated
)
; function to calculate duration in seconds since last calc-time
(define (calc-dur)
(let ((diff (ly:moment-sub (ly:context-now context) start) ) ; moment since last calc-time
(tempo (ly:context-property context 'tempoWholesPerMinute (ly:make-moment 60/4)) )) ; current tempo
(set! start (ly:context-now context)) ; set calc-time
(set! dur ; add 60*(diff/tempo) to duration
; if tempo is 120 BPM and 120/4 elapsed,
; we have 60 * 120/4 * 4/120 = 60 seconds
(+ dur
(* 60
(exact->inexact (ly:moment-main (ly:moment-div diff tempo)))
)))
dur
))
(make-engraver
(listeners
((tempo-change-event engraver event)
(calc-dur) ; calculate duration on every tempo-change-event (new tempo will be set after we listened to the event)
(ly:message "duration: ~A" (format-time dur))
)
) ; listeners
((finalize trans)
(calc-dur) ; last calculation of duration
(set! duration dur) ; set global duration (for the markup command)
(ly:message "duration: ~A final" (format-time dur))
)
)))
%%% actual music example
music = {
\tempo 4 = 60
c'4 c' c' c'
\repeat volta 2 { d'2 d' | e' e' }
\tempo 4 = 90
c'4 c' c' c'
}
%%% scores
\score {
\new Staff { \unfoldRepeats \music }
\midi {
\context {
\Score
\consists \calc-duration-engraver
}
}
}
\score {
\new Staff {
\music
\mark \markup { \box \duration }
\bar "|."
}
}
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user