<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.lilypond.community/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Masterpaster</id>
	<title>LilyPond wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.lilypond.community/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Masterpaster"/>
	<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/wiki/Special:Contributions/Masterpaster"/>
	<updated>2026-05-01T13:00:53Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5988</id>
		<title>Time mark engraver</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5988"/>
		<updated>2025-12-27T22:29:13Z</updated>

		<summary type="html">&lt;p&gt;Masterpaster: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When working with LilyPond’s MIDI output it can be tedious to find the exact ‘elapsed time from the start of the score to an arbitrary point’ – especially when the music contains multiple tempo changes. Counting measures and doing tempo math is error-prone; inspecting the MIDI file manually is possible but time consuming.&lt;br /&gt;
&lt;br /&gt;
This snippets introduces a Scheme engraver that allows you to insert time marks directly into the music. At any point in the score you can add &amp;lt;code&amp;gt;\timeMark&amp;lt;/code&amp;gt;, and LilyPond computes the elapsed time up to that position and displays it (for example, ‘2m15s’).&lt;br /&gt;
&lt;br /&gt;
This is useful when you need to&lt;br /&gt;
&lt;br /&gt;
* align score events with audio or video cues,&lt;br /&gt;
* locate timestamps for MIDI-driven playback or mockups,&lt;br /&gt;
* find “time since start” at a few musical key positions without counting or math, or&lt;br /&gt;
* work reliably across complex tempo maps (rit., accel., metric modulations, etc.).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Upgrade notice&#039;&#039;: This snippet needs proper convert-ly conversion for &amp;gt;=2.25 ( &amp;lt;code&amp;gt;&#039;tempoWholesPerMinute&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;&#039;tempoWholesPerMinuteAsMoment&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lilypond version=&amp;quot;2.24&amp;quot;&amp;gt;&lt;br /&gt;
% LSR source: https://lists.gnu.org/archive/html/lilypond-user/2024-03/msg00127.html&lt;br /&gt;
% LSR credits: 2024 - Jean Abou Samra&lt;br /&gt;
&lt;br /&gt;
#(define (Elapsed_time_engraver context)&lt;br /&gt;
   (define (format-time seconds) ; example: 2m15s&lt;br /&gt;
     (let ((minutes (euclidean-quotient seconds 60))&lt;br /&gt;
           (rest (euclidean-remainder seconds 60)))&lt;br /&gt;
       (string-append (if (zero? minutes) &amp;quot;&amp;quot; (format #f &amp;quot;~am&amp;quot; minutes))&lt;br /&gt;
                      (format #f &amp;quot;~as&amp;quot; (round rest)))))&lt;br /&gt;
&lt;br /&gt;
   (let ((wholes-per-minute 15)&lt;br /&gt;
         (last-time ZERO-MOMENT)&lt;br /&gt;
         (total-time 0)&lt;br /&gt;
         (marks &#039;()))&lt;br /&gt;
     (make-engraver&lt;br /&gt;
      ((process-music engraver)&lt;br /&gt;
       (let* ((new-time (ly:context-current-moment context))&lt;br /&gt;
              (time-delta (ly:moment-main&lt;br /&gt;
                           (ly:moment-sub new-time last-time)))&lt;br /&gt;
              (new-wholes-per-minute&lt;br /&gt;
               (and=&amp;gt; (ly:context-property context&lt;br /&gt;
                                           &#039;tempoWholesPerMinute #f)&lt;br /&gt;
                      ly:moment-main)))&lt;br /&gt;
         (set! total-time&lt;br /&gt;
               (+ total-time (* 60 (/ time-delta wholes-per-minute))))&lt;br /&gt;
         (set! last-time new-time)&lt;br /&gt;
         (when new-wholes-per-minute&lt;br /&gt;
           (set! wholes-per-minute new-wholes-per-minute))))&lt;br /&gt;
&lt;br /&gt;
      (acknowledgers&lt;br /&gt;
       ((text-mark-interface engraver grob source-engraver)&lt;br /&gt;
        (set! marks (cons grob marks))))&lt;br /&gt;
&lt;br /&gt;
      ((process-acknowledged engraver)&lt;br /&gt;
       (for-each (lambda (grob)&lt;br /&gt;
                   (when (assq-ref (ly:grob-property grob &#039;details)&lt;br /&gt;
                                   &#039;time-mark)&lt;br /&gt;
                     (ly:grob-set-property!&lt;br /&gt;
                      grob &#039;text (format-time total-time))))&lt;br /&gt;
                 marks)&lt;br /&gt;
       (set! marks &#039;())))))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
\layout {&lt;br /&gt;
  \context {&lt;br /&gt;
    \Score&lt;br /&gt;
    \consists #Elapsed_time_engraver&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
% The argument of the `\textEndMark` here is just a placeholder&lt;br /&gt;
% that the engraver replaces with a time stamp (because the&lt;br /&gt;
% `time-mark` subproperty is set).&lt;br /&gt;
timeMark = \tweak details.time-mark ##t&lt;br /&gt;
           \tweak color &amp;quot;red&amp;quot;&lt;br /&gt;
           \textEndMark &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  c&#039;1 | \timeMark&lt;br /&gt;
  \tempo 4 = 120 c&#039;4 8. 16 2 | \timeMark&lt;br /&gt;
  \tempo 4 = 180 \repeat unfold 4 c&#039;2 | \timeMark&lt;br /&gt;
  \repeat unfold 180 c&#039;4 | \timeMark&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lilypond&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Automatic notation]]&lt;br /&gt;
[[Category:Contexts and engravers]]&lt;br /&gt;
[[Category:Editorial annotations]]&lt;br /&gt;
[[Category:Midi]]&lt;br /&gt;
[[Category:Scheme]]&lt;br /&gt;
[[Category:Snippet]]&lt;/div&gt;</summary>
		<author><name>Masterpaster</name></author>
	</entry>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5987</id>
		<title>Time mark engraver</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5987"/>
		<updated>2025-12-27T22:26:22Z</updated>

		<summary type="html">&lt;p&gt;Masterpaster: Upgrade (convert-ly) notice&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When working with LilyPond’s MIDI output it can be tedious to find the exact ‘elapsed time from the start of the score to an arbitrary point’ – especially when the music contains multiple tempo changes. Counting measures and doing tempo math is error-prone; inspecting the MIDI file manually is possible but time consuming.&lt;br /&gt;
&lt;br /&gt;
This snippets introduces a Scheme engraver that allows you to insert time marks directly into the music. At any point in the score you can add &amp;lt;code&amp;gt;\timeMark&amp;lt;/code&amp;gt;, and LilyPond computes the elapsed time up to that position and displays it (for example, ‘2m15s’).&lt;br /&gt;
&lt;br /&gt;
This is useful when you need to&lt;br /&gt;
&lt;br /&gt;
* align score events with audio or video cues,&lt;br /&gt;
* locate timestamps for MIDI-driven playback or mockups,&lt;br /&gt;
* find “time since start” at a few musical key positions without counting or math, or&lt;br /&gt;
* work reliably across complex tempo maps (rit., accel., metric modulations, etc.).&lt;br /&gt;
&lt;br /&gt;
{{Warning|This snippet needs proper convert-ly conversion for &amp;gt;=2.25. ( &amp;lt;code&amp;gt;&#039;tempoWholesPerMinute&amp;lt;/code&amp;gt; -&amp;gt; &amp;lt;code&amp;gt;&#039;tempoWholesPerMinuteAsMoment&amp;lt;/code&amp;gt;)}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lilypond version=&amp;quot;2.24&amp;quot;&amp;gt;&lt;br /&gt;
% LSR source: https://lists.gnu.org/archive/html/lilypond-user/2024-03/msg00127.html&lt;br /&gt;
% LSR credits: 2024 - Jean Abou Samra&lt;br /&gt;
&lt;br /&gt;
#(define (Elapsed_time_engraver context)&lt;br /&gt;
   (define (format-time seconds) ; example: 2m15s&lt;br /&gt;
     (let ((minutes (euclidean-quotient seconds 60))&lt;br /&gt;
           (rest (euclidean-remainder seconds 60)))&lt;br /&gt;
       (string-append (if (zero? minutes) &amp;quot;&amp;quot; (format #f &amp;quot;~am&amp;quot; minutes))&lt;br /&gt;
                      (format #f &amp;quot;~as&amp;quot; (round rest)))))&lt;br /&gt;
&lt;br /&gt;
   (let ((wholes-per-minute 15)&lt;br /&gt;
         (last-time ZERO-MOMENT)&lt;br /&gt;
         (total-time 0)&lt;br /&gt;
         (marks &#039;()))&lt;br /&gt;
     (make-engraver&lt;br /&gt;
      ((process-music engraver)&lt;br /&gt;
       (let* ((new-time (ly:context-current-moment context))&lt;br /&gt;
              (time-delta (ly:moment-main&lt;br /&gt;
                           (ly:moment-sub new-time last-time)))&lt;br /&gt;
              (new-wholes-per-minute&lt;br /&gt;
               (and=&amp;gt; (ly:context-property context&lt;br /&gt;
                                           &#039;tempoWholesPerMinute #f)&lt;br /&gt;
                      ly:moment-main)))&lt;br /&gt;
         (set! total-time&lt;br /&gt;
               (+ total-time (* 60 (/ time-delta wholes-per-minute))))&lt;br /&gt;
         (set! last-time new-time)&lt;br /&gt;
         (when new-wholes-per-minute&lt;br /&gt;
           (set! wholes-per-minute new-wholes-per-minute))))&lt;br /&gt;
&lt;br /&gt;
      (acknowledgers&lt;br /&gt;
       ((text-mark-interface engraver grob source-engraver)&lt;br /&gt;
        (set! marks (cons grob marks))))&lt;br /&gt;
&lt;br /&gt;
      ((process-acknowledged engraver)&lt;br /&gt;
       (for-each (lambda (grob)&lt;br /&gt;
                   (when (assq-ref (ly:grob-property grob &#039;details)&lt;br /&gt;
                                   &#039;time-mark)&lt;br /&gt;
                     (ly:grob-set-property!&lt;br /&gt;
                      grob &#039;text (format-time total-time))))&lt;br /&gt;
                 marks)&lt;br /&gt;
       (set! marks &#039;())))))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
\layout {&lt;br /&gt;
  \context {&lt;br /&gt;
    \Score&lt;br /&gt;
    \consists #Elapsed_time_engraver&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
% The argument of the `\textEndMark` here is just a placeholder&lt;br /&gt;
% that the engraver replaces with a time stamp (because the&lt;br /&gt;
% `time-mark` subproperty is set).&lt;br /&gt;
timeMark = \tweak details.time-mark ##t&lt;br /&gt;
           \tweak color &amp;quot;red&amp;quot;&lt;br /&gt;
           \textEndMark &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  c&#039;1 | \timeMark&lt;br /&gt;
  \tempo 4 = 120 c&#039;4 8. 16 2 | \timeMark&lt;br /&gt;
  \tempo 4 = 180 \repeat unfold 4 c&#039;2 | \timeMark&lt;br /&gt;
  \repeat unfold 180 c&#039;4 | \timeMark&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lilypond&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Automatic notation]]&lt;br /&gt;
[[Category:Contexts and engravers]]&lt;br /&gt;
[[Category:Editorial annotations]]&lt;br /&gt;
[[Category:Midi]]&lt;br /&gt;
[[Category:Scheme]]&lt;br /&gt;
[[Category:Snippet]]&lt;/div&gt;</summary>
		<author><name>Masterpaster</name></author>
	</entry>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5980</id>
		<title>Time mark engraver</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5980"/>
		<updated>2025-12-27T10:10:02Z</updated>

		<summary type="html">&lt;p&gt;Masterpaster: Undo revision 5979 by Masterpaster (talk)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When working with LilyPond’s MIDI output, it can be tedious to find the exact &#039;&#039;&#039;elapsed time from the start of the score to an arbitrary point&#039;&#039;&#039;—especially when the music contains &#039;&#039;&#039;multiple tempo changes&#039;&#039;&#039;. Counting measures and doing tempo math is error-prone; inspecting the MIDI file manually is possible but time-consuming.&lt;br /&gt;
&lt;br /&gt;
To solve this, Jean wrote a small &#039;&#039;&#039;custom engraver&#039;&#039;&#039; that allows you to insert &#039;&#039;&#039;time marks&#039;&#039;&#039; directly into the music. At any point in the score you can add &amp;lt;code&amp;gt;\timeMark&amp;lt;/code&amp;gt;, and LilyPond will compute the elapsed time up to that position and display it (2m15s e.g.).&lt;br /&gt;
&lt;br /&gt;
=== Use case ===&lt;br /&gt;
This is useful when you need to:&lt;br /&gt;
&lt;br /&gt;
* align score events with audio/video cues,&lt;br /&gt;
* locate timestamps for MIDI-driven playback or mockups,&lt;br /&gt;
* find “time since start” at a few key musical points without counting or math,&lt;br /&gt;
* work reliably across complex tempo maps (rit., accel., metric modulations, etc.).&lt;br /&gt;
&lt;br /&gt;
 \version &amp;quot;2.24.4&amp;quot;&lt;br /&gt;
 % source: https://lists.gnu.org/archive/html/lilypond-user/2024-03/msg00127.html&lt;br /&gt;
 % credits: 2024 - Jean Abou Samra&lt;br /&gt;
 &lt;br /&gt;
 #(define (Custom_engraver!! context)&lt;br /&gt;
    (define (format-time seconds)  ; ex.: 2m15s&lt;br /&gt;
      (let ((minutes (euclidean-quotient seconds 60))&lt;br /&gt;
            (rest (euclidean-remainder seconds 60)))&lt;br /&gt;
        (string-append (if (zero? minutes) &amp;quot;&amp;quot; (format #f &amp;quot;~am&amp;quot; minutes))&lt;br /&gt;
                       (format #f &amp;quot;~as&amp;quot; (round rest)))))&lt;br /&gt;
    (let ((wholes-per-minute 15)&lt;br /&gt;
          (last-time ZERO-MOMENT)&lt;br /&gt;
          (total-time 0)&lt;br /&gt;
          (marks &#039;()))&lt;br /&gt;
      (make-engraver&lt;br /&gt;
       ((process-music engraver)&lt;br /&gt;
        (let* ((new-time (ly:context-current-moment context))&lt;br /&gt;
               (time-delta (ly:moment-main (ly:moment-sub new-time last-time)))&lt;br /&gt;
               (new-wholes-per-minute&lt;br /&gt;
                 (and=&amp;gt; (ly:context-property context &#039;tempoWholesPerMinute #f)&lt;br /&gt;
                        ly:moment-main)))&lt;br /&gt;
          (set! total-time&lt;br /&gt;
                (+ total-time (* 60 (/ time-delta wholes-per-minute))))&lt;br /&gt;
          (set! last-time new-time)&lt;br /&gt;
          (when new-wholes-per-minute&lt;br /&gt;
            (set! wholes-per-minute new-wholes-per-minute))))&lt;br /&gt;
       (acknowledgers&lt;br /&gt;
        ((text-mark-interface engraver grob source-engraver)&lt;br /&gt;
         (set! marks (cons grob marks))))&lt;br /&gt;
       ((process-acknowledged engraver)&lt;br /&gt;
        (for-each (lambda (grob)&lt;br /&gt;
                    (when (assq-ref (ly:grob-property grob &#039;details) &#039;time-mark)&lt;br /&gt;
                      (ly:grob-set-property! grob &#039;text (format-time &lt;br /&gt;
 total-time))))&lt;br /&gt;
                  marks)&lt;br /&gt;
        (set! marks &#039;())))))&lt;br /&gt;
 &lt;br /&gt;
 \layout {&lt;br /&gt;
   \context {&lt;br /&gt;
     \Score&lt;br /&gt;
     \consists #Custom_engraver!!&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 timeMark = \tweak details.time-mark ##t \tweak color &amp;quot;red&amp;quot; \textEndMark &lt;br /&gt;
 &amp;quot;Abracadabra&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
   c&#039;1&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \tempo 4 = 120&lt;br /&gt;
   c&#039;4 8. 16 2&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \tempo 4 = 180&lt;br /&gt;
   c&#039;2 2&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \repeat unfold 180 c&#039;4&lt;br /&gt;
   \timeMark&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Masterpaster</name></author>
	</entry>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5979</id>
		<title>Time mark engraver</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5979"/>
		<updated>2025-12-27T10:09:07Z</updated>

		<summary type="html">&lt;p&gt;Masterpaster: Added link to Jean&amp;#039;s name&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When working with LilyPond’s MIDI output, it can be tedious to find the exact &#039;&#039;&#039;elapsed time from the start of the score to an arbitrary point&#039;&#039;&#039;—especially when the music contains &#039;&#039;&#039;multiple tempo changes&#039;&#039;&#039;. Counting measures and doing tempo math is error-prone; inspecting the MIDI file manually is possible but time-consuming.&lt;br /&gt;
&lt;br /&gt;
To solve this, [[Jean]] wrote a small &#039;&#039;&#039;custom engraver&#039;&#039;&#039; that allows you to insert &#039;&#039;&#039;time marks&#039;&#039;&#039; directly into the music. At any point in the score you can add &amp;lt;code&amp;gt;\timeMark&amp;lt;/code&amp;gt;, and LilyPond will compute the elapsed time up to that position and display it (2m15s e.g.).&lt;br /&gt;
&lt;br /&gt;
=== Use case ===&lt;br /&gt;
This is useful when you need to:&lt;br /&gt;
&lt;br /&gt;
* align score events with audio/video cues,&lt;br /&gt;
* locate timestamps for MIDI-driven playback or mockups,&lt;br /&gt;
* find “time since start” at a few key musical points without counting or math,&lt;br /&gt;
* work reliably across complex tempo maps (rit., accel., metric modulations, etc.).&lt;br /&gt;
&lt;br /&gt;
 \version &amp;quot;2.24.4&amp;quot;&lt;br /&gt;
 % source: https://lists.gnu.org/archive/html/lilypond-user/2024-03/msg00127.html&lt;br /&gt;
 % credits: 2024 - Jean Abou Samra&lt;br /&gt;
 &lt;br /&gt;
 #(define (Custom_engraver!! context)&lt;br /&gt;
    (define (format-time seconds)  ; ex.: 2m15s&lt;br /&gt;
      (let ((minutes (euclidean-quotient seconds 60))&lt;br /&gt;
            (rest (euclidean-remainder seconds 60)))&lt;br /&gt;
        (string-append (if (zero? minutes) &amp;quot;&amp;quot; (format #f &amp;quot;~am&amp;quot; minutes))&lt;br /&gt;
                       (format #f &amp;quot;~as&amp;quot; (round rest)))))&lt;br /&gt;
    (let ((wholes-per-minute 15)&lt;br /&gt;
          (last-time ZERO-MOMENT)&lt;br /&gt;
          (total-time 0)&lt;br /&gt;
          (marks &#039;()))&lt;br /&gt;
      (make-engraver&lt;br /&gt;
       ((process-music engraver)&lt;br /&gt;
        (let* ((new-time (ly:context-current-moment context))&lt;br /&gt;
               (time-delta (ly:moment-main (ly:moment-sub new-time last-time)))&lt;br /&gt;
               (new-wholes-per-minute&lt;br /&gt;
                 (and=&amp;gt; (ly:context-property context &#039;tempoWholesPerMinute #f)&lt;br /&gt;
                        ly:moment-main)))&lt;br /&gt;
          (set! total-time&lt;br /&gt;
                (+ total-time (* 60 (/ time-delta wholes-per-minute))))&lt;br /&gt;
          (set! last-time new-time)&lt;br /&gt;
          (when new-wholes-per-minute&lt;br /&gt;
            (set! wholes-per-minute new-wholes-per-minute))))&lt;br /&gt;
       (acknowledgers&lt;br /&gt;
        ((text-mark-interface engraver grob source-engraver)&lt;br /&gt;
         (set! marks (cons grob marks))))&lt;br /&gt;
       ((process-acknowledged engraver)&lt;br /&gt;
        (for-each (lambda (grob)&lt;br /&gt;
                    (when (assq-ref (ly:grob-property grob &#039;details) &#039;time-mark)&lt;br /&gt;
                      (ly:grob-set-property! grob &#039;text (format-time &lt;br /&gt;
 total-time))))&lt;br /&gt;
                  marks)&lt;br /&gt;
        (set! marks &#039;())))))&lt;br /&gt;
 &lt;br /&gt;
 \layout {&lt;br /&gt;
   \context {&lt;br /&gt;
     \Score&lt;br /&gt;
     \consists #Custom_engraver!!&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 timeMark = \tweak details.time-mark ##t \tweak color &amp;quot;red&amp;quot; \textEndMark &lt;br /&gt;
 &amp;quot;Abracadabra&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
   c&#039;1&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \tempo 4 = 120&lt;br /&gt;
   c&#039;4 8. 16 2&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \tempo 4 = 180&lt;br /&gt;
   c&#039;2 2&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \repeat unfold 180 c&#039;4&lt;br /&gt;
   \timeMark&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Masterpaster</name></author>
	</entry>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5978</id>
		<title>Time mark engraver</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Time_mark_engraver&amp;diff=5978"/>
		<updated>2025-12-27T09:53:38Z</updated>

		<summary type="html">&lt;p&gt;Masterpaster: Page initially created&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When working with LilyPond’s MIDI output, it can be tedious to find the exact &#039;&#039;&#039;elapsed time from the start of the score to an arbitrary point&#039;&#039;&#039;—especially when the music contains &#039;&#039;&#039;multiple tempo changes&#039;&#039;&#039;. Counting measures and doing tempo math is error-prone; inspecting the MIDI file manually is possible but time-consuming.&lt;br /&gt;
&lt;br /&gt;
To solve this, Jean wrote a small &#039;&#039;&#039;custom engraver&#039;&#039;&#039; that allows you to insert &#039;&#039;&#039;time marks&#039;&#039;&#039; directly into the music. At any point in the score you can add &amp;lt;code&amp;gt;\timeMark&amp;lt;/code&amp;gt;, and LilyPond will compute the elapsed time up to that position and display it (2m15s e.g.).&lt;br /&gt;
&lt;br /&gt;
=== Use case ===&lt;br /&gt;
This is useful when you need to:&lt;br /&gt;
&lt;br /&gt;
* align score events with audio/video cues,&lt;br /&gt;
* locate timestamps for MIDI-driven playback or mockups,&lt;br /&gt;
* find “time since start” at a few key musical points without counting or math,&lt;br /&gt;
* work reliably across complex tempo maps (rit., accel., metric modulations, etc.).&lt;br /&gt;
&lt;br /&gt;
 \version &amp;quot;2.24.4&amp;quot;&lt;br /&gt;
 % source: https://lists.gnu.org/archive/html/lilypond-user/2024-03/msg00127.html&lt;br /&gt;
 % credits: 2024 - Jean Abou Samra&lt;br /&gt;
 &lt;br /&gt;
 #(define (Custom_engraver!! context)&lt;br /&gt;
    (define (format-time seconds)  ; ex.: 2m15s&lt;br /&gt;
      (let ((minutes (euclidean-quotient seconds 60))&lt;br /&gt;
            (rest (euclidean-remainder seconds 60)))&lt;br /&gt;
        (string-append (if (zero? minutes) &amp;quot;&amp;quot; (format #f &amp;quot;~am&amp;quot; minutes))&lt;br /&gt;
                       (format #f &amp;quot;~as&amp;quot; (round rest)))))&lt;br /&gt;
    (let ((wholes-per-minute 15)&lt;br /&gt;
          (last-time ZERO-MOMENT)&lt;br /&gt;
          (total-time 0)&lt;br /&gt;
          (marks &#039;()))&lt;br /&gt;
      (make-engraver&lt;br /&gt;
       ((process-music engraver)&lt;br /&gt;
        (let* ((new-time (ly:context-current-moment context))&lt;br /&gt;
               (time-delta (ly:moment-main (ly:moment-sub new-time last-time)))&lt;br /&gt;
               (new-wholes-per-minute&lt;br /&gt;
                 (and=&amp;gt; (ly:context-property context &#039;tempoWholesPerMinute #f)&lt;br /&gt;
                        ly:moment-main)))&lt;br /&gt;
          (set! total-time&lt;br /&gt;
                (+ total-time (* 60 (/ time-delta wholes-per-minute))))&lt;br /&gt;
          (set! last-time new-time)&lt;br /&gt;
          (when new-wholes-per-minute&lt;br /&gt;
            (set! wholes-per-minute new-wholes-per-minute))))&lt;br /&gt;
       (acknowledgers&lt;br /&gt;
        ((text-mark-interface engraver grob source-engraver)&lt;br /&gt;
         (set! marks (cons grob marks))))&lt;br /&gt;
       ((process-acknowledged engraver)&lt;br /&gt;
        (for-each (lambda (grob)&lt;br /&gt;
                    (when (assq-ref (ly:grob-property grob &#039;details) &#039;time-mark)&lt;br /&gt;
                      (ly:grob-set-property! grob &#039;text (format-time &lt;br /&gt;
 total-time))))&lt;br /&gt;
                  marks)&lt;br /&gt;
        (set! marks &#039;())))))&lt;br /&gt;
 &lt;br /&gt;
 \layout {&lt;br /&gt;
   \context {&lt;br /&gt;
     \Score&lt;br /&gt;
     \consists #Custom_engraver!!&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 timeMark = \tweak details.time-mark ##t \tweak color &amp;quot;red&amp;quot; \textEndMark &lt;br /&gt;
 &amp;quot;Abracadabra&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 {&lt;br /&gt;
   c&#039;1&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \tempo 4 = 120&lt;br /&gt;
   c&#039;4 8. 16 2&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \tempo 4 = 180&lt;br /&gt;
   c&#039;2 2&lt;br /&gt;
   \timeMark&lt;br /&gt;
   \repeat unfold 180 c&#039;4&lt;br /&gt;
   \timeMark&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Masterpaster</name></author>
	</entry>
</feed>