Re: calculation of the total duration of a score

2016-09-16 Thread Marc Hohl

Hi Jan-Peter,

Am 16.09.2016 um 08:40 schrieb Jan-Peter Voigt:

Hi Marc,

nice to hear, that you have a workflow. For the record I noted two
things in the file. (And if there's some spare time, I might further
work on it.)


Thanks for the continuing work on that issue!



1. The durations are tagged by score and stored in an a-list, so you
can first collect durations in multiple scores and display them later
with a score-unique tag.


The tagging works fine, but as soon as I have a layout block in the
\score creating the exact midi file, lilypond prints it :-(

Moving the callback from \layout {} to \midi {} yields to

Programming error: Cannot find key `scoreBACH' in alist, setting to `0'.

So I still have to use my solution with the auxiliary files, which is no
problem at all.

> 2. There are acknowledgers for volta-brackets and barlines. It should
> be possible to use that information for acknowledging volta repeats
> and ajusting the duration accordingly. Those grobs are created by
> engravers, but if one creates the barlines *not* with \repeat volta,
> but with \bar ".|:", it should be acknowledged too.

This sounds promising, but IMHO it would be easier to get the engraver 
to work somehow on a \score with a \midi { } block only and transferring 
the duration to another \score.



Cheers,

Marc







Cheers Jan-Peter


Am 15.09.2016 um 08:10 schrieb Marc Hohl:

Am 14.09.2016 um 14:24 schrieb Marc Hohl: [...]

I thought of writing the duration to a external file to be read
from within the markup call in the score to be printed, but did
not follow this route any further yet.


Update: a simple test file shows that this works.

I can

- compute the total duration of a file designed for midi output
only by means of your engraver - write the duration to a file and -
read that string while processing the "print-only" file.

Merging that stuff together with some Makefile should be
straightforward, I hope ;-)

And it has the advantage that some MIDI-related changes do not
appear in the printed score, but the duration will be updated
accordingly.

Cheers,

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




___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-15 Thread Jan-Peter Voigt

Hi Marc,

nice to hear, that you have a workflow.
For the record I noted two things in the file. (And if there's some 
spare time, I might further work on it.)


1. The durations are tagged by score and stored in an a-list, so you can 
first collect durations in multiple scores and display them later with a 
score-unique tag.
2. There are acknowledgers for volta-brackets and barlines. It should be 
possible to use that information for acknowledging volta repeats and 
ajusting the duration accordingly. Those grobs are created by engravers, 
but if one creates the barlines *not* with \repeat volta, but with \bar 
".|:", it should be acknowledged too.


Cheers
Jan-Peter


Am 15.09.2016 um 08:10 schrieb Marc Hohl:

Am 14.09.2016 um 14:24 schrieb Marc Hohl:
[...]

I thought of writing the duration to a external file to be read from
within the markup call in the score to be printed, but did not follow
this route any further yet.


Update: a simple test file shows that this works.

I can

- compute the total duration of a file designed for
  midi output only by means of your engraver
- write the duration to a file and
- read that string while processing the "print-only" file.

Merging that stuff together with some Makefile should be
straightforward, I hope ;-)

And it has the advantage that some MIDI-related changes do not appear in
the printed score, but the duration will be updated accordingly.

Cheers,

Marc


___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


\version "2.19.47"

% 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 scores - set after finalizing
duration = #'()

% markup command to display complete time
#(define-markup-command (duration layout props scoretag)(symbol?)
   (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 (ly:assoc-get scoretag duration 0 #t)))
 )))
  x-ext y-ext)
 ))

calcDuration =
#(define-scheme-function (tag)(symbol?)
   (define (calc-duration 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
(acknowledgers
 ((volta-bracket-interface engraver grob source-engraver)
  (ly:message "saw volta bracket @ ~A" (ly:context-now context)))
 ((bar-line-interface engraver grob source-engraver)
  (let ((bar (ly:context-property context 'whichBar)))
(if (not (equal? "|" bar)) (ly:message "bar ~A" bar))
  ))
 )
(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 (assoc-set! duration tag dur)) ; set global duration (for the markup command)
 (ly:message "duration: ~A final" (format-time dur))
 )
)))
   #{ \with { \consists #calc-duration } #}
   )


% example

% TODO repeats are not included !!

meta = { \tempo 4=90 s1*4 | \tempo 4=120 \repeat volta 3 { s1*4 } \alternative { { s1 } { s1*2 } { \tempo 4=100 s1 } } s1*4 }

\score {
  \new Staff <<
\meta
\repeat unfold 32 \relative c'' { bes4 a c b }
  >>
  \layout {
\context {
  \Score
  \calcDuration scoreBACH
}
  }
  \midi { }
}

\markup {
  \box \duration #'scoreBACH
}
___
lilypond-user mailing list
lilypond-user@gnu.org
https://li

Re: calculation of the total duration of a score

2016-09-14 Thread Marc Hohl

Am 14.09.2016 um 14:24 schrieb Marc Hohl:
[...]

I thought of writing the duration to a external file to be read from
within the markup call in the score to be printed, but did not follow
this route any further yet.


Update: a simple test file shows that this works.

I can

- compute the total duration of a file designed for
  midi output only by means of your engraver
- write the duration to a file and
- read that string while processing the "print-only" file.

Merging that stuff together with some Makefile should be 
straightforward, I hope ;-)


And it has the advantage that some MIDI-related changes do not appear in 
the printed score, but the duration will be updated accordingly.


Cheers,

Marc


___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-14 Thread Marc Hohl

Hi Jan-Peter,

Am 14.09.2016 um 13:18 schrieb Jan-Peter Voigt:

Hi Marc,

I am busy today, so I will look into your example later.


No problem!


In short: Repeats are not taken into account right now.


Yes. Therefore I used the \unfoldRepeats/\midi-combination, but the
duration computed in one \score is not visible in the other one.

I thought of writing the duration to a external file to be read from
within the markup call in the score to be printed, but did not follow
this route any further yet.


I thought of a factor, that is set, when a repeat starts. But I don't
know yet, how to deal with alternatives and repeats with more than
two loops. Probably the engraver might look for barlines. Still it
needs to recognize alternatives with its possible repetitions (e.g.
1-3).


I don't know whether it is doable to implement the stuff that
\unfoldRepeats does within the engraver. Detecting the beginning and the
end of a repeated section should not be that hard, but the bookkeeping
is probably tricky in terms of alternatives, as you pointed out.


We'll crack that nut :-)


Sounds probising, thank you very much!

Marc


Jan-Peter

Am 14. September 2016 12:03:43 MESZ, schrieb Marc Hohl
:

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





 lilypond-user mailing list lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


-- Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9
Mail gesendet.



___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-14 Thread Jan-Peter Voigt
Hi Marc,

I am busy today, so I will look into your example later.
In short: Repeats are not taken into account right now. I thought of a factor, 
that is set, when a repeat starts. But I don't know yet, how to deal with 
alternatives and repeats with more than two loops. Probably the engraver might 
look for barlines. Still it needs to recognize alternatives with its possible 
repetitions (e.g. 1-3).

We'll crack that nut :-)

Jan-Peter 

Am 14. September 2016 12:03:43 MESZ, schrieb Marc Hohl :
>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
>>
>
>
>
>
>
>___
>lilypond-user mailing list
>lilypond-user@gnu.org
>https://lists.gnu.org/mailman/listinfo/lilypond-user

-- 
Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9 Mail gesendet.___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-14 Thread Marc Hohl

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 {  
   

Re: calculation of the total duration of a score

2016-09-13 Thread Marc Hohl

Hi Jan-Peter,

seems to do exactly what I need, so thanks for sharing ... I'll give it 
a try tomorrow, when I have some time to work on my project again.


Cheers,

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




___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-13 Thread 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


\version "2.19.47"

% 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)
 ))

% consist an engraver to collect time
\layout {
  \context {
\Score
\consists
#(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))
   )
  )))
  }
}


% example

% TODO repeats are not included !!

meta = { \tempo 4=90 s1*4 | \tempo 4=120 \repeat volta 2 { s1*4 } }

\score {
  \new Staff <<
\meta
\repeat unfold 8 \relative c'' { bes4 a c b }
  >>
  \layout { }
  \midi { }
}

\markup {
  \box \duration
}
___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-12 Thread Paul

Hi Harm,

On 09/10/2016 02:48 PM, Thomas Morley wrote:

many thanks for looking into it and adding a diff, much easier to
compare the versions. :)


You're welcome!  Thanks for writing the code for me to test out.  :)


Also for the insufficient
   (if duration-marks
which was kept from an earlier version. Ofcourse your correction is
the way to go.


Well, I realized afterwards that
  (pair? lst)
is probably the usual scheme way rather than
  (not (null? lst))
although the latter arguably makes the intention clearer for readers who 
don't know scheme as well.



Well, at first it's a matter of code-hygiene. Those variables were
filled by the engraver doing it's work, why not clear them?
Additional I fear bleeding over, if the same engraver is used while
compiling multiple scores/files. Or if he is put into multiple
contexts of the same score.
Not entirely sure about this, but better be a paranoiac ;)


Indeed!  That sounds good to me.

I incorporated some of your approach into the patch I did for 
lilypond-html-live-score, in case anyone is curious:


https://gitlab.com/sigmate/lilypond-html-live-score/commit/8d1fe4d9f8d39a2849bf737136ee2cca419b9fb6

Cheers,
-Paul


___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-11 Thread Marc Hohl

Am 11.09.2016 um 12:16 schrieb David Kastrup:
[...]

Would this be somehow possible?


I probably lack the imagination for seeing your problem.


I need the total duration in terms of minutes and seconds, taking all 
possible tempo changes etc. into account.



___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-11 Thread David Kastrup
Marc Hohl  writes:

> Hi Harm, hi Paul,
>
> thanks a lot for your code/improvements/discussion to this subject!
>
> Definitively worth to be put in the LSR!
>
> Some remarks from me as a real-life user:
>
> the engraver does not expand repeats, so if there ist some \repeat
> volta ... construct around, the total duration is not only wrong
> (which is clear from the way the engraver works) but somewhat strange.
>
> So my humble question to the scheme wizards out there: is it possible
> to store the total duration in a variable/property to be read
> afterwards?
>
> I think of something like
>
> music = { ... }
>
> \score {
>\new Staff {
>   \music
>   \mark \markup "Duration:
> #(get-total-duration #{ \unfoldRepeats \music #})"
>   \bar "|."
>}
> }
>
> (just pseudo-code, of course)
>
> Would this be somehow possible?

I probably lack the imagination for seeing your problem.

music =
\fixed c'
{ c1 \repeat volta 4 { g1 } \alternative { { c1 g1 } { r1 } } }

\score {
   \new Staff {
  \music
  \mark \markup
  #(format "Duration: ~a"
	(ly:moment-main (ly:music-length #{ \unfoldRepeats \music #})))
  \bar "|."
   }
}


-- 
David Kastrup
___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-11 Thread Marc Hohl

Hi Harm, hi Paul,

thanks a lot for your code/improvements/discussion to this subject!

Definitively worth to be put in the LSR!

Some remarks from me as a real-life user:

the engraver does not expand repeats, so if there ist some \repeat volta 
... construct around, the total duration is not only wrong (which is 
clear from the way the engraver works) but somewhat strange.


So my humble question to the scheme wizards out there: is it possible to 
store the total duration in a variable/property to be read afterwards?


I think of something like

music = { ... }

\score {
   \new Staff {
  \music
  \mark \markup "Duration:
#(get-total-duration #{ \unfoldRepeats \music #})"
  \bar "|."
   }
}

(just pseudo-code, of course)

Would this be somehow possible?

Thanks,

Marc




Am 10.09.2016 um 20:48 schrieb Thomas Morley:

Hi Paul,

many thanks for looking into it and adding a diff, much easier to
compare the versions. :)

2016-09-10 20:08 GMT+02:00 Paul :

On 09/09/2016 05:27 PM, Thomas Morley wrote:


Attached you'll find a different version.



I noticed that text-only tempos (\tempo "Andante") caused problems. See
attached revision which fixes this.


Good catch, I overlooked this.
Also for the insufficient
  (if duration-marks
which was kept from an earlier version. Ofcourse your correction is
the way to go.


It also has improved code for detecting
a missing initial tempo (to then supply the default one).  See attached diff
file for changes.


You asked:
2016-09-10 16:40 GMT+02:00 Paul :


Also, I wonder, where you clear out these variables at the end of the
finalize stage:

 (set! evts '())
 (set! last-evt #f)
 (set! tempo-change-evts '())
 (set! duration-marks '())

Of course, it doesn't hurt, but is it necessary?  If so I need to do that in
my code.


Well, at first it's a matter of code-hygiene. Those variables were
filled by the engraver doing it's work, why not clear them?
Additional I fear bleeding over, if the same engraver is used while
compiling multiple scores/files. Or if he is put into multiple
contexts of the same score.
Not entirely sure about this, but better be a paranoiac ;)


Thanks for your thorough review.
I think I'll follow your suggestion and put it in the LSR.


Best,
  Harm

___
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


Re: calculation of the total duration of a score

2016-09-10 Thread Thomas Morley
Hi Paul,

many thanks for looking into it and adding a diff, much easier to
compare the versions. :)

2016-09-10 20:08 GMT+02:00 Paul :
> On 09/09/2016 05:27 PM, Thomas Morley wrote:
>
>> Attached you'll find a different version.
>
>
> I noticed that text-only tempos (\tempo "Andante") caused problems. See
> attached revision which fixes this.

Good catch, I overlooked this.
Also for the insufficient
  (if duration-marks
which was kept from an earlier version. Ofcourse your correction is
the way to go.

> It also has improved code for detecting
> a missing initial tempo (to then supply the default one).  See attached diff
> file for changes.

You asked:
2016-09-10 16:40 GMT+02:00 Paul :

> Also, I wonder, where you clear out these variables at the end of the
> finalize stage:
>
>  (set! evts '())
>  (set! last-evt #f)
>  (set! tempo-change-evts '())
>  (set! duration-marks '())
>
> Of course, it doesn't hurt, but is it necessary?  If so I need to do that in
> my code.

Well, at first it's a matter of code-hygiene. Those variables were
filled by the engraver doing it's work, why not clear them?
Additional I fear bleeding over, if the same engraver is used while
compiling multiple scores/files. Or if he is put into multiple
contexts of the same score.
Not entirely sure about this, but better be a paranoiac ;)


Thanks for your thorough review.
I think I'll follow your suggestion and put it in the LSR.


Best,
  Harm

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-10 Thread Paul

On 09/09/2016 05:27 PM, Thomas Morley wrote:


Attached you'll find a different version.


I noticed that text-only tempos (\tempo "Andante") caused problems. See 
attached revision which fixes this.  It also has improved code for 
detecting a missing initial tempo (to then supply the default one).  See 
attached diff file for changes.


Cheers,
-Paul
\version "2.19.47"

printScoreDuration = {
  \once \override Score.RehearsalMark.direction = #DOWN
  \once \override Score.RehearsalMark.self-alignment-X = #RIGHT
  \mark "print-score-duration"
}

formatScoreDuration =
#(define-scheme-function (dur)(exact?)
   "Returns the given duration as a formated markup containing minutes and
seconds."
   (let* ((minutes (floor dur))
  ;; Is using floor correct?
  (seconds (floor (* (- dur minutes ) 60)))
  (duration-string
   (format #f "Duration: ~a:~2,,,'0@a" minutes seconds)))
 #{
   \markup \rounded-box \fontsize #-3 #duration-string
 #}))

#(define (get-seconds lst rl)
   "Takes a list of kind
'((# 1/15) 
  (# 1/30) 
  (# 1/15))
Calculates the time passed between each moment.
Returns the addition of it as an exact numerical value.
  "
   (if (null? (cdr lst))
   (apply + rl)
   (get-seconds
(cdr lst)
(cons
 (* (cdr (cadr lst))
   (ly:moment-main (ly:moment-sub (caar lst) (caadr lst
 rl


#(define (score-duration-engraver context)
   (let* ((evts '())
  (last-evt #f)
  (tempo-change-evts '())
  (duration-marks '()))
 (make-engraver
  (listeners
   ((rhythmic-event engraver event)
(set! last-evt (ly:event-property event 'length))
(set! evts (cons (ly:context-current-moment context) evts)))
   ((tempo-change-event engraver event)
(let ((tempo-unit (ly:event-property event 'tempo-unit))
  (metronome-count (ly:event-property event 'metronome-count)))
  ;; Accumulate pairs of "moment when it happens" and
  ;; "quotient of tempo-unit and metronome-count"in `tempo-change-evts'
  ;; for use in `get-seconds'
  ;; text-only tempo changes like \tempo "Andante" have no tempo-unit
  (if (and tempo-unit metronome-count)
  (set! tempo-change-evts
(cons
 (cons
  (ly:context-current-moment context)
  ;; Hmm, ugly code...
  (/ (string->number (ly:duration->string tempo-unit))
metronome-count))
 tempo-change-evts))
  (acknowledgers
   ((mark-interface engraver grob source-engraver)
(let ((mark-text (ly:grob-property grob 'text)))
  (if (and (string? mark-text)
   (string=? mark-text "print-score-duration"))
  (set! duration-marks (cons grob duration-marks))
  ((finalize translator)
   (if (not (null? duration-marks))
   (let* ((moment-zero (ly:make-moment 0))
  ; add default tempo at moment zero, if one does not already exist
  (tempo-changes
   (if (or (null? tempo-change-evts)
   (not (equal? moment-zero
(car (last tempo-change-evts)
   ;; 1/15 is default tempo, could this be accessed somewhere?
   (append tempo-change-evts (list (cons moment-zero 1/15)))
   tempo-change-evts))
  (duration-before-last-tempo-change
   (get-seconds tempo-changes '()))
  (duration-after-last-tempo-change-without-last-dur
   (* (cdr (car tempo-changes))
 (ly:moment-main
  (ly:moment-sub (car evts) (caar tempo-changes)
  (last-ev-duration
   (* (cdar tempo-changes) (ly:moment-main last-evt)))
  (final-duration
   (+
duration-before-last-tempo-change
duration-after-last-tempo-change-without-last-dur
last-ev-duration)))
 (for-each
  (lambda (g)
(ly:grob-set-property! g 'text
  (formatScoreDuration final-duration)))
  duration-marks)
 (set! evts '())
 (set! last-evt #f)
 (set! tempo-change-evts '())
 (set! duration-marks '(

\layout {
  \context {
\Score
\consists \score-duration-engraver
  }
}

%%
%% EXAMPLE
%%

voiceI =
\new Voice {
  \partial 4
  c'4
  \repeat unfold 61 c'4
  \tempo 4=120
  c'2. d'2
  \tempo 8=120
  c'2~ |
  \tuplet 3/2 { c'2 2 2 }
  \tempo "Andante"
  c'2 c'2
}

voiceII = {
  \partial 4
  cis'4
  \printScoreDuration
  \repeat unfold 17 cis'1
  %% fiddling with two simultaneous RehearsalMarks...
  cis'1*31/32
  \printScoreDurati

Re: calculation of the total duration of a score

2016-09-10 Thread Paul

On 09/09/2016 05:27 PM, Thomas Morley wrote:


Attached you'll find a different version.
It avoids creating all those grobs and killing most of them in the
end. Instead a preexisting RehearsalMark (or more of them) is taken
and 'text is reset.
Some other changes for better usability.


Hi Harm,  Nice work!  I'd say this is a good candidate for the LSR, 
particularly because it demonstrates listeners, acknowledgers, and 
finalize in one engraver.


One little thing I noticed is that

  (if duration-marks

should be something like

  (if (not (null? duration-marks))

Because:

  \version "2.19.42"
  #(define empty-list '())
  #(display (if empty-list #t #f))
  % --> #t
  #(display (if (not (null? empty-list)) #t #f))
  % --> #f

Also, I wonder, where you clear out these variables at the end of the 
finalize stage:


 (set! evts '())
 (set! last-evt #f)
 (set! tempo-change-evts '())
 (set! duration-marks '())

Of course, it doesn't hurt, but is it necessary?  If so I need to do 
that in my code.


-Paul

___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-09 Thread Thomas Morley
2016-09-08 14:21 GMT+02:00 Marc Hohl :
> Hi Harm,
>
> thanks a lot for your engraver, works out of the box!
>
> Best regards,
>
> Marc

Hi Marc,

you're welcome.

Attached you'll find a different version.
It avoids creating all those grobs and killing most of them in the
end. Instead a preexisting RehearsalMark (or more of them) is taken
and 'text is reset.
Some other changes for better usability.

HTH,
  Harm
\version "2.19.47"

printScoreDuration = {
  \once \override Score.RehearsalMark.direction = #DOWN
  \once \override Score.RehearsalMark.self-alignment-X = #RIGHT
  \mark "print-score-duration"
}

formatScoreDuration =
#(define-scheme-function (dur)(exact?)
  "Returns the given duration as a formated markup containing minutes and
seconds."
  (let* ((minutes (floor dur))
 ;; Is using floor correct?
 (seconds (floor (* (- dur minutes ) 60)))
 (duration-string 
   (format #f "Duration: ~a:~2,,,'0@a" minutes seconds)))
#{
  \markup \rounded-box \fontsize #-3 #duration-string
#}))

#(define (get-seconds lst rl)
  "Takes a list of kind
'((# 1/15) 
  (# 1/30) 
  (# 1/15))
Calculates the time passed between each moment.
Returns the addition of it as an exact numerical value.
  "
  (if (null? (cdr lst))
  (apply + rl)
  (get-seconds 
(cdr lst)
(cons
  (* (cdr (cadr lst))
 (ly:moment-main (ly:moment-sub (caar lst) (caadr lst
  rl


#(define (score-duration-engraver context)
  (let* ((evts '())
 (last-evt #f)
 (tempo-change-evts '())
 (duration-marks '()))
  (make-engraver
(listeners
  ((rhythmic-event engraver event)
(set! last-evt (ly:event-property event 'length))
(set! evts (cons (ly:context-current-moment context) evts)))
  ((tempo-change-event engraver event)
   (let ((tempo-unit 
   ;; Hmm, ugly code...
   (string->number 
 (ly:duration->string (ly:event-property event 'tempo-unit
 (metronome-count (ly:event-property event 'metronome-count)))
;; Accumulate pairs of "moment when it happens" and 
;; "quotient of tempo-unit and metronome-count"in `tempo-change-evts'
;; for use in `get-seconds'
(set! tempo-change-evts
  (cons
(cons 
  (ly:context-current-moment context) 
  (/ tempo-unit metronome-count))
tempo-change-evts)
(acknowledgers
  ((mark-interface engraver grob source-engraver)
   (let ((mark-text (ly:grob-property grob 'text)))
 (if (and (string? mark-text) 
  (string=? mark-text "print-score-duration"))
 (set! duration-marks (cons grob duration-marks))
((finalize translator)
 (if duration-marks
 (let* (;; default tempo, could this be grapped somewhere?
(default-tempo-setting (cons (ly:make-moment 0) 1/15))
; add default tempo, if not introduced at score-begin 
(tempo-changes
  (if (or (null? tempo-change-evts)
  (not (equal? (last tempo-change-evts) 
   default-tempo-setting)))
  (append 
tempo-change-evts (list default-tempo-setting))
  tempo-change-evts))
(duration-before-last-tempo-change
  (get-seconds tempo-changes '()))
(duration-after-last-tempo-change-without-last-dur
  (* (cdr (car tempo-changes))
 (ly:moment-main 
   (ly:moment-sub (car evts) (caar tempo-changes)
(last-ev-duration
  (* (cdar tempo-changes) (ly:moment-main last-evt)))
(final-duration
  (+
 duration-before-last-tempo-change
 duration-after-last-tempo-change-without-last-dur
 last-ev-duration)))
 (for-each
   (lambda (g)
 (ly:grob-set-property! g 'text 
(formatScoreDuration final-duration)))
   duration-marks)
 (set! evts '())
 (set! last-evt #f)
 (set! tempo-change-evts '())
 (set! duration-marks '(
 
\layout {
  \context { 
  	  \Score
  	  \consists \score-duration-engraver
  }
}

%%
%% EXAMPLE
%%

voiceI =
  \new Voice { 
\partial 4 
c'4
\repeat unfold 61 c'4 
\tempo 4=120
c'2. d'2
\tempo 8=120
c'2~ |
\tuplet 3/2 { c'2 2 2 }
  }
  
voiceII = { 
  \partial 4 
  cis'4 
  \printScoreDuration
  \repeat unfold 17 cis'1 
  %% fiddling with two simultaneous RehearsalMarks...
  cis'1*31/32
  \printScoreDuration
  s1*1/32
  \mark \default
  
}

\score {
  <<
  	\voiceI
  	\voiceII
  >>
  \layout { }
  \midi {}
}
___
lilypond-use

Re: calculation of the total duration of a score

2016-09-09 Thread Marc Hohl

Hi Paul,


Am 08.09.2016 um 19:28 schrieb Paul:

Hi Marc,

Well, looks like I sent the file too soon before testing it for this use
case.  It looks like the html-live-score is using different units of
time somehow?  I haven't had a chance to look into it or figure out the
difference.


Ok, no problem, thanks for clarification!

Marc


___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-08 Thread Paul

Hi Marc,

Well, looks like I sent the file too soon before testing it for this use 
case.  It looks like the html-live-score is using different units of 
time somehow?  I haven't had a chance to look into it or figure out the 
difference.


Anyway, the attached file will report the correct total duration, thanks 
to some help from looking at Harm's code.  (But I think this version 
will probably not work with the code for html-live-score...)


Anyway, you're probably better off using Harm's code since it was 
written for calculating the total duration.


Cheers,
-Paul



On 09/08/2016 06:10 AM, Marc Hohl wrote:

Hi Paul,

thanks for the file. It lookes quite promising, but a quick test shows 
some strange numbers I do not understand:


test.ly ---

\version "2.19.47"

\include "grob-meta-data-engraver.ily"

\score {
  \new Staff {
 \tempo 4 = 60
 \repeat unfold 60 c'4
   }
   \layout { }
   \midi { }
 }

Processing this file yields to:

GNU LilyPond 2.19.48
»test.ly« wird verarbeitet
Analysieren...
Interpretation der Musik...[8][16][16]3.75
Vorverarbeitung der grafischen Elemente...
Interpretation der Musik...
MIDI-Ausgabe nach »test.midi«...
Ideale Seitenanzahl wird gefunden...
Musik wird auf eine Seite angepasst...
Systeme erstellen...
Layout nach »/tmp/lilypond-pgKSZe« ausgeben...
Konvertierung nach »test.pdf«...
Löschen von »/tmp/lilypond-pgKSZe«...
Kompilation erfolgreich beendet

marc@olivia ~/engraver$ timidity test.midi
Playing test.midi
MIDI file: test.midi
Format: 1  Tracks: 2  Divisions: 384
Sequence:
Text: creator:
Text: GNU LilyPond 2.19.48
Playing time: ~64 seconds
Notes cut: 0
Notes lost totally: 0

It shows a duration of 3.75 in line 4.

A timidity call plays the file in about 64 seconds
(even strange, 60 notes with tempo 4 = 60 should have a total duration 
of 60 seconds).


What does 3.75 mean?

Marc


Am 08.09.2016 um 05:39 schrieb Paul:

On 09/05/2016 05:01 AM, Marc Hohl wrote:


Has someone else already done something like this? I have no experience
in writing scheme engravers, so any hint would be highly appreciated.


lilypond-html-live-score does something like this by post-processing an
SVG with python to add meta data to the grobs in the SVG file:
https://gitlab.com/sigmate/lilypond-html-live-score/blob/master/make-live-score#L88 




I was working on porting part of that to scheme so it could be done
directly.  I've attached my include file.  It will currently display the
total duration to the log.  It could be simplified in various ways if it
was calculating just the total duration and not adding timing info to
every grob.

It's still a work in progress and only lightly tested.

-Paul



___
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.42"

#(define Grob_meta_data_engraver
   (lambda (context)

 (define (get-tempo-change metronome-mark-grob)
   "Returns a pair (moment-fraction . new-tempo-rate) or #f."
   (let*
((grob-cause (ly:grob-property metronome-mark-grob 'cause))
 (metronome-count (ly:event-property grob-cause 'metronome-count))
 (tempo-unit (ly:event-property grob-cause 'tempo-unit))
 (moment (grob::when metronome-mark-grob)))
(if (and metronome-count tempo-unit)
(cons
 (ly:moment-main moment)
 ;; calculate the new tempo rate
 (/ (string->number
 (ly:duration->string tempo-unit))
   metronome-count))
#f)))


 (define (recurse prev-moment prev-time prev-rate grobs tempo-changes)
   "Recursive function to calculate and set timing data for grobs.
Calculates the actual timing of grobs, honoring tempo changes.
Returns the total time for the score."
   (let* ((grob (car grobs))
  (moment (ly:moment-main (grob::when grob)))
  (rate-change (if (pair? tempo-changes)
   (> moment (caar tempo-changes))
   #f))
  (rate (if rate-change
(cdr (car tempo-changes))
prev-rate))
  (time (if (= moment prev-moment)
prev-time
(+ prev-time (* rate (- moment prev-moment)
  (id-string (string-append
  (ly:format "class:ly grob ~a" (grob::name grob))
  (ly:format ";data-moment:~a" (exact->inexact moment))
  (ly:format ";data-measure:~a" (car 
(grob::rhythmic-location grob)))
  (ly:format ";data-real-time:~a" time)
  )))

 ;; (display id-string)(newline)
 (ly:grob-set-property! grob 'id id-string)

 ;; r

Re: calculation of the total duration of a score

2016-09-08 Thread Marc Hohl

Hi Harm,

thanks a lot for your engraver, works out of the box!

Best regards,

Marc

Am 08.09.2016 um 10:02 schrieb Thomas Morley:

2016-09-08 5:39 GMT+02:00 Paul :

On 09/05/2016 05:01 AM, Marc Hohl wrote:


Has someone else already done something like this? I have no experience
in writing scheme engravers, so any hint would be highly appreciated.



lilypond-html-live-score does something like this by post-processing an SVG
with python to add meta data to the grobs in the SVG file:
https://gitlab.com/sigmate/lilypond-html-live-score/blob/master/make-live-score#L88

I was working on porting part of that to scheme so it could be done
directly.  I've attached my include file.  It will currently display the
total duration to the log.  It could be simplified in various ways if it was
calculating just the total duration and not adding timing info to every
grob.

It's still a work in progress and only lightly tested.

-Paul




Hi,

I've seen Paul answered already, had no time to look into his code, though.

Below my own approach.
Disadvantage: The duration-indication is bound to the last seen event.
This may result in different positions of the RehearsalMark, which I
prefered over TextScript (but this special problem would happen for
both)

\version "2.19.47"

#(define (get-seconds lst rl)
  "Takes a list of kind
'((# 1/15)
  (# 1/30)
  (# 1/15))
Calculates the time passed between each moment.
Returns the addition of it as an exact numerical value.
  "
  (if (null? (cdr lst))
  (apply + rl)
  (get-seconds
(cdr lst)
(cons
  (* (cdr (cadr lst))
 (ly:moment-main (ly:moment-sub (caar lst) (caadr lst
  rl


#(define (score-duration-engraver context)
  (let* ((evts '())
 (last-evt #f)
 (grobs '())
 (tempo-change-evts '()))
  (make-engraver
(listeners
  ((rhythmic-event engraver event)
(set! last-evt (ly:event-property event 'length))
(set! evts (cons (ly:context-current-moment context) evts))
;; TODO creating RehearsalMarks at every rhythmic-event looks like
;; a huge waste. How to do it better?
(set! grobs
  (cons
(ly:engraver-make-grob engraver 'RehearsalMark event)
grobs)))
  ((tempo-change-event engraver event)
   (let ((tempo-unit
   ;; Hmm, ugly code...
   (string->number
 (ly:duration->string (ly:event-property event 'tempo-unit
 (metronome-count (ly:event-property event 'metronome-count)))
;; Accumulate pairs of "moment when it happens" and
;; "quotient of tempo-unit and metronome-count"in `tempo-change-evts'
;; for use in `get-seconds'
(set! tempo-change-evts
  (cons
(cons
  (ly:context-current-moment context)
  (/ tempo-unit metronome-count))
tempo-change-evts)
((finalize translator)
 (let* (;; add default tempo, if not introduced at score-begin
(tempo-changes
  (if (null? tempo-change-evts)
  (list (cons (ly:make-moment 0) 1/15))
  (if (not
(equal? (ly:make-moment 0)
(car (last tempo-change-evts
  (append
tempo-change-evts (list (cons (ly:make-moment 0) 1/15)))
  tempo-change-evts)))
(duration-before-last-tempo-change
  (get-seconds tempo-changes '()))
(duration-after-last-tempo-change-without-last-dur
  (* (cdr (car tempo-changes))
 (ly:moment-main
   (ly:moment-sub (car evts) (caar tempo-changes)
(last-ev-duration
  (* (cdar tempo-changes) (ly:moment-main last-evt)))
(final-duration
  (+
 duration-before-last-tempo-change
 duration-after-last-tempo-change-without-last-dur
 last-ev-duration))
(minutes (floor final-duration))
;; Is using floor correct?
(seconds (floor (* (- final-duration minutes ) 60)))
(duration-string
  (format #f "Duration: ~a:~2,,,'0@a" minutes seconds)))
 ;; Only keep the last created RehearsalMark, suicide the others
 (for-each ly:grob-suicide! (cdr grobs))
 (ly:grob-set-property! (first grobs) 'direction DOWN)
 (ly:grob-set-property! (first grobs) 'text
;; a little custom-formatting
(markup #:rounded-box #:fontsize -3 duration-string))
 (set! evts '())
 (set! last-evt #f)
 (set! grobs '())
 (set! tempo-change-evts '()))

\layout {
  \context {
\Score
\consists \score-duration-engraver
  }
}

%%
%% EXAMPLE
%%

voiceI =
  \new Voice {
\partial 4
c'4
\repeat unfold 61 c'4
\tempo 4=120
c'2. d'2
\tempo 8=120

Re: calculation of the total duration of a score

2016-09-08 Thread Marc Hohl

Hi Paul,

thanks for the file. It lookes quite promising, but a quick test shows 
some strange numbers I do not understand:


test.ly ---

\version "2.19.47"

\include "grob-meta-data-engraver.ily"

\score {
  \new Staff {
 \tempo 4 = 60
 \repeat unfold 60 c'4
   }
   \layout { }
   \midi { }
 }

Processing this file yields to:

GNU LilyPond 2.19.48
»test.ly« wird verarbeitet
Analysieren...
Interpretation der Musik...[8][16][16]3.75
Vorverarbeitung der grafischen Elemente...
Interpretation der Musik...
MIDI-Ausgabe nach »test.midi«...
Ideale Seitenanzahl wird gefunden...
Musik wird auf eine Seite angepasst...
Systeme erstellen...
Layout nach »/tmp/lilypond-pgKSZe« ausgeben...
Konvertierung nach »test.pdf«...
Löschen von »/tmp/lilypond-pgKSZe«...
Kompilation erfolgreich beendet

marc@olivia ~/engraver$ timidity test.midi
Playing test.midi
MIDI file: test.midi
Format: 1  Tracks: 2  Divisions: 384
Sequence:
Text: creator:
Text: GNU LilyPond 2.19.48
Playing time: ~64 seconds
Notes cut: 0
Notes lost totally: 0

It shows a duration of 3.75 in line 4.

A timidity call plays the file in about 64 seconds
(even strange, 60 notes with tempo 4 = 60 should have a total duration 
of 60 seconds).


What does 3.75 mean?

Marc


Am 08.09.2016 um 05:39 schrieb Paul:

On 09/05/2016 05:01 AM, Marc Hohl wrote:


Has someone else already done something like this? I have no experience
in writing scheme engravers, so any hint would be highly appreciated.


lilypond-html-live-score does something like this by post-processing an
SVG with python to add meta data to the grobs in the SVG file:
https://gitlab.com/sigmate/lilypond-html-live-score/blob/master/make-live-score#L88


I was working on porting part of that to scheme so it could be done
directly.  I've attached my include file.  It will currently display the
total duration to the log.  It could be simplified in various ways if it
was calculating just the total duration and not adding timing info to
every grob.

It's still a work in progress and only lightly tested.

-Paul



___
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


Re: calculation of the total duration of a score

2016-09-08 Thread Thomas Morley
2016-09-08 5:39 GMT+02:00 Paul :
> On 09/05/2016 05:01 AM, Marc Hohl wrote:
>
>> Has someone else already done something like this? I have no experience
>> in writing scheme engravers, so any hint would be highly appreciated.
>
>
> lilypond-html-live-score does something like this by post-processing an SVG
> with python to add meta data to the grobs in the SVG file:
> https://gitlab.com/sigmate/lilypond-html-live-score/blob/master/make-live-score#L88
>
> I was working on porting part of that to scheme so it could be done
> directly.  I've attached my include file.  It will currently display the
> total duration to the log.  It could be simplified in various ways if it was
> calculating just the total duration and not adding timing info to every
> grob.
>
> It's still a work in progress and only lightly tested.
>
> -Paul



Hi,

I've seen Paul answered already, had no time to look into his code, though.

Below my own approach.
Disadvantage: The duration-indication is bound to the last seen event.
This may result in different positions of the RehearsalMark, which I
prefered over TextScript (but this special problem would happen for
both)

\version "2.19.47"

#(define (get-seconds lst rl)
  "Takes a list of kind
'((# 1/15)
  (# 1/30)
  (# 1/15))
Calculates the time passed between each moment.
Returns the addition of it as an exact numerical value.
  "
  (if (null? (cdr lst))
  (apply + rl)
  (get-seconds
(cdr lst)
(cons
  (* (cdr (cadr lst))
 (ly:moment-main (ly:moment-sub (caar lst) (caadr lst
  rl


#(define (score-duration-engraver context)
  (let* ((evts '())
 (last-evt #f)
 (grobs '())
 (tempo-change-evts '()))
  (make-engraver
(listeners
  ((rhythmic-event engraver event)
(set! last-evt (ly:event-property event 'length))
(set! evts (cons (ly:context-current-moment context) evts))
;; TODO creating RehearsalMarks at every rhythmic-event looks like
;; a huge waste. How to do it better?
(set! grobs
  (cons
(ly:engraver-make-grob engraver 'RehearsalMark event)
grobs)))
  ((tempo-change-event engraver event)
   (let ((tempo-unit
   ;; Hmm, ugly code...
   (string->number
 (ly:duration->string (ly:event-property event 'tempo-unit
 (metronome-count (ly:event-property event 'metronome-count)))
;; Accumulate pairs of "moment when it happens" and
;; "quotient of tempo-unit and metronome-count"in `tempo-change-evts'
;; for use in `get-seconds'
(set! tempo-change-evts
  (cons
(cons
  (ly:context-current-moment context)
  (/ tempo-unit metronome-count))
tempo-change-evts)
((finalize translator)
 (let* (;; add default tempo, if not introduced at score-begin
(tempo-changes
  (if (null? tempo-change-evts)
  (list (cons (ly:make-moment 0) 1/15))
  (if (not
(equal? (ly:make-moment 0)
(car (last tempo-change-evts
  (append
tempo-change-evts (list (cons (ly:make-moment 0) 1/15)))
  tempo-change-evts)))
(duration-before-last-tempo-change
  (get-seconds tempo-changes '()))
(duration-after-last-tempo-change-without-last-dur
  (* (cdr (car tempo-changes))
 (ly:moment-main
   (ly:moment-sub (car evts) (caar tempo-changes)
(last-ev-duration
  (* (cdar tempo-changes) (ly:moment-main last-evt)))
(final-duration
  (+
 duration-before-last-tempo-change
 duration-after-last-tempo-change-without-last-dur
 last-ev-duration))
(minutes (floor final-duration))
;; Is using floor correct?
(seconds (floor (* (- final-duration minutes ) 60)))
(duration-string
  (format #f "Duration: ~a:~2,,,'0@a" minutes seconds)))
 ;; Only keep the last created RehearsalMark, suicide the others
 (for-each ly:grob-suicide! (cdr grobs))
 (ly:grob-set-property! (first grobs) 'direction DOWN)
 (ly:grob-set-property! (first grobs) 'text
;; a little custom-formatting
(markup #:rounded-box #:fontsize -3 duration-string))
 (set! evts '())
 (set! last-evt #f)
 (set! grobs '())
 (set! tempo-change-evts '()))

\layout {
  \context {
\Score
\consists \score-duration-engraver
  }
}

%%
%% EXAMPLE
%%

voiceI =
  \new Voice {
\partial 4
c'4
\repeat unfold 61 c'4
\tempo 4=120
c'2. d'2
\tempo 8=120
c'2~ |
c'1
  }

voiceII = { \partial 4 cis'4 \repeat unfold 18 cis'1 }

\score {
  <<
  \voi

Re: calculation of the total duration of a score

2016-09-07 Thread Paul

On 09/05/2016 05:01 AM, Marc Hohl wrote:


Has someone else already done something like this? I have no experience
in writing scheme engravers, so any hint would be highly appreciated.


lilypond-html-live-score does something like this by post-processing an 
SVG with python to add meta data to the grobs in the SVG file:

https://gitlab.com/sigmate/lilypond-html-live-score/blob/master/make-live-score#L88

I was working on porting part of that to scheme so it could be done 
directly.  I've attached my include file.  It will currently display the 
total duration to the log.  It could be simplified in various ways if it 
was calculating just the total duration and not adding timing info to 
every grob.


It's still a work in progress and only lightly tested.

-Paul

\version "2.19.42"

#(define Grob_meta_data_engraver
   (lambda (context)

 (define (get-tempo-change metronome-mark-grob)
   "Returns a pair (moment-fraction . new-tempo-rate) or #f."
   (let*
((grob-cause (ly:grob-property metronome-mark-grob 'cause))
 (metronome-count (ly:event-property grob-cause 'metronome-count))
 (tempo-unit (ly:event-property grob-cause 'tempo-unit))
 (moment (grob::when metronome-mark-grob)))
(if (and metronome-count tempo-unit)
(cons
 (ly:moment-main moment)
 ;; calculate the new tempo rate
 (/ 60 (* metronome-count
 (string->number
  (ly:duration->string tempo-unit)
#f)))


 (define (recurse prev-moment prev-time prev-rate grob grobs tempo-changes)
   "Recursive function to calculate and set timing data for grobs.
Calculates the actual timing of grobs, honoring tempo changes.
Returns the total time for the score."
   (let* ((moment (ly:moment-main (grob::when grob)))
  (rate-change (if (pair? tempo-changes)
   (>= moment (caar tempo-changes))
   #f))
  (rate (if rate-change
(cdr (car tempo-changes))
prev-rate))
  (time (if (= moment prev-moment)
prev-time
(+ prev-time (* rate (- moment prev-moment)
  (id-string (string-append
  (ly:format "class:ly grob ~a" (grob::name grob))
  (ly:format ";data-moment:~a" (exact->inexact moment))
  (ly:format ";data-measure:~a" (car 
(grob::rhythmic-location grob)))
  (ly:format ";data-real-time:~a" time)
  )))

 ;; (display id-string)(newline)
 (ly:grob-set-property! grob 'id id-string)

 ;; recurse or return total time if we are done
 (if (null? grobs)
 time
 (recurse moment time rate (car grobs) (cdr grobs) (if rate-change
   (cdr 
tempo-changes)
   
tempo-changes)


 ;; an engraver with a closure
 (let ((grobs '())
   (metronome-mark-grobs '())
   (note-head-grobs '()))
   (make-engraver

;; acknowledgers collect grobs
(acknowledgers
 ((grob-interface engraver grob source-engraver)
  (set! grobs (cons grob grobs)))

 ((metronome-mark-interface engraver grob source-engraver)
  (set! metronome-mark-grobs (cons grob metronome-mark-grobs)))

 ((note-head-interface engraver grob source-engraver)
  (set! note-head-grobs (cons grob note-head-grobs

;; finalize stage, calculate and store data on grobs
((finalize translator)
 (let*
  ((tempo-changes (filter pair? (map get-tempo-change 
metronome-mark-grobs)))

   (tempo-changes-sorted (sort-list! tempo-changes
   (lambda (a b) (< (car a) (car b)

   (grobs-sorted (sort-list! (filter grob::name grobs)
   (lambda (a b)
 (ly:momentinexact total-time))

  ;; add additional data for MetronomeMark grobs
  (for-each (lambda (metronome-mark-grob)
  (let* ((grob-cause (ly:grob-property metronome-mark-grob 
'cause))
 (text-prop (ly:event-property grob-cause 'text))
 (text-string (if (not (null? text-prop))
  (ly:format ";data-text:~a" 
text-prop)
  ""))
 (id-string (ly:grob-property metronome-mark-grob 
'id)))
(ly:grob-set-property! metronome-mark-grob 'id
  (string-append id-string text-string
metronome-mark-grobs)

  ;; add additional data for NoteHead grobs

Re: calculation of the total duration of a score

2016-09-06 Thread Marc Hohl

Am 05.09.2016 um 11:54 schrieb Federico Bruni:

Il giorno lun 5 set 2016 alle 11:01, Marc Hohl  ha
scritto:

[...]

I have not tried, but maybe python-ly is able to give what you want?
http://python-ly.readthedocs.io/en/latest/ly.music.html


Thanks for the link.

If I haven't overlooked an important detail, python-ly does not provide 
this function out-of-the-box.


Moreover, a scheme-ish solution allows for direct generation of a markup 
to be placed at the final bar line.


Marc





___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user


Re: calculation of the total duration of a score

2016-09-05 Thread Federico Bruni
Il giorno lun 5 set 2016 alle 11:01, Marc Hohl  ha 
scritto:
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.


I have not tried, but maybe python-ly is able to give what you want?
http://python-ly.readthedocs.io/en/latest/ly.music.html



___
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user