lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Scheme predicative types


From: Martín Rincón Botero
Subject: Re: Scheme predicative types
Date: Fri, 18 Sep 2020 13:40:21 +0200

Thank you very much, Aaron! The \markup \null construction is something that I will have to study carefully in the next few days to fully grasp it. I made some adjustments to the formatting, so that it matches the default \tempo formatting of Lilypond, especially when using a tempo range (Lilypond uses – instead of -, and leaves a space before and after the hyphen, so your added \concat is not required here ;-)), and I made all \tempo text bold by default (as Lilypond does). However, your example made me compare it with Lilypond's formatting and there's still one issue even after fixing the other small details: When the user writes \tempo "Adagio" 4 = 70, he expects the tempo unit and metronome count in parenthesis after the given text. Here I'm absolutely limited by my Scheme ignorance on how to achieve that (somehow combining several conditions and adding \markup {#text  \concat { "(" #tempo-unit } = \concat { #metronome-count ")" } ?).

This is not going to be easy to solve.  You need to know when then
\stopTextSpan occurs so that the \tempo command applies at that moment. 
However that information is entirely unknown at the time of
\tempoTextSpan.

Oh! Right! Then I guess one solution would be to name the function \tempoSpan instead, with a "dummy" variable (for the sake of syntax) startTempoSpan = \startTextSpan and a variable stopTempoSpan, that would have to call the previous obtained values of tempoSpan (that I can't re-use because they're a markup and not a number anymore? Or because I don't know how to call information obtained in other variables? Or both? GUILLE complains of an Unbound variable: tempo-unit and Unbound variable: metronome-count) and would add something like stopTempoSpan = \stopTextSpan \once \omit Score.MetronomeMark \tempo #tempo-unit = #metronome-count. Simulating a rit. and accel. is probably too much to ask. I don't even know how to do that independently of this script.

Anyways, this script is already quite awesome! :-) Thank you!

Here the progress of the script with the small formatting fixes and the new name \tempoSpan in the hope that a \stopTempoSpan as described above can be successfully created:

tempoSpan =
#(define-scheme-function
    (leftmarkup tempo lefthalign righthalign)
    (markup? tempo? number? number?)
    (set! tempo (first (extract-typed-music tempo 'tempo-change-event)))
    (let ((tempo-unit (ly:prob-property tempo 'tempo-unit #f))
          (metronome-count (ly:prob-property tempo 'metronome-count #f))
          (text (ly:prob-property tempo 'text #f))
          )
      (set! tempo-unit
        (if (ly:duration? tempo-unit)
            #{ \markup {
              \note #(ly:duration->string tempo-unit) #UP
                } #}
            #{ \markup \null #} ))
      (set! metronome-count
        (cond ((number-pair? metronome-count)
               #{ \markup { =
                  #(format #f "~d" (car metronome-count)) –
                  #(format #f "~d" (cdr metronome-count)) } #})
              ((number? metronome-count)
               #{ \markup { =
                  #(format #f "~d" metronome-count) } #})
              (else #{ \markup \null #})))
      (set! text
        (if (markup? text)
            #{ \markup \bold \abs-fontsize #11 \upright #text #}
            #{ \markup \null #}))
      #{
\once \override TextSpanner.bound-details.left-broken.text = ##f
\once \override TextSpanner.bound-details.right-broken.text = ##f
\once \override TextSpanner #'(bound-details left text) =  \markup \halign #lefthalign \abs-fontsize #11 #leftmarkup
\once \override TextSpanner #'(bound-details right text) = \markup \halign #righthalign \line { #text \abs-fontsize #10 \general-align #Y #DOWN #tempo-unit
\abs-fontsize #11 \upright #metronome-count }
      #}))

Best regards,
Martín.

Am Fr., 18. Sept. 2020 um 12:16 Uhr schrieb Aaron Hill <lilypond@hillvisions.com>:
On 2020-09-18 2:01 am, Martín Rincón Botero wrote:
> [ . . . ] The thing I couldn't adapt from your script
> is the Text part, when the user writes a new tempo with a construction
> like
> \tempo "Allegro". I suppose I have to somehow put my \once \override
> TextSpanner #'(bound-details right text) in some sort of conditional so
> that when the user puts a text, it displays a text, when it's a
> metronome,
> a metronome :-), but I couldn't figure out how to adapt what you
> already
> had.

You could do things with conditionals, but it might make better sense to
simply use a null markup when an element is not present.  Consider:

%%%%
\version "2.20.0"

#(define (tempo? arg)
    (and (ly:music? arg)
         (not (null? (extract-typed-music arg 'tempo-change-event)))))

tempoTextSpan =
#(define-scheme-function
    (leftmarkup tempo lefthalign righthalign)
    (markup? tempo? number? number?)
    (set! tempo (first (extract-typed-music tempo 'tempo-change-event)))
    (let ((tempo-unit (ly:prob-property tempo 'tempo-unit #f))
          (metronome-count (ly:prob-property tempo 'metronome-count #f))
          (text (ly:prob-property tempo 'text #f))
          )
      (set! tempo-unit
        (if (ly:duration? tempo-unit)
            #{ \markup {
              \note #(ly:duration->string tempo-unit) #UP
                } #}
            #{ \markup \null #} ))
      (set! metronome-count
        (cond ((number-pair? metronome-count)
               #{ \markup { = \concat {
                  #(format #f "~d" (car metronome-count)) -
                  #(format #f "~d" (cdr metronome-count)) } } #})
              ((number? metronome-count)
               #{ \markup { =
                  #(format #f "~d" metronome-count) } #})
              (else #{ \markup \null #})))
      (set! text
        (if (markup? text)
            #{ \markup \abs-fontsize #11 \upright #text #}
            #{ \markup \null #}))
      #{
\once \override TextSpanner.bound-details.left-broken.text = ##f
\once \override TextSpanner.bound-details.right-broken.text = ##f
\once \override TextSpanner #'(bound-details left text) =  \markup
\halign
#lefthalign \abs-fontsize #11 #leftmarkup
\once \override TextSpanner #'(bound-details right text) = \markup
\halign
#righthalign \line { #text \abs-fontsize #10 \general-align #Y #DOWN
#tempo-unit
\abs-fontsize #11 \upright #metronome-count }
      #}))

{
   \tempoTextSpan "accel." \tempo 4 = 80 #LEFT #RIGHT
   c'4\startTextSpan 4 4 4 2 2 d'1\stopTextSpan R1
   \tempoTextSpan "rall." \tempo "Adagio" 4 = 65-70 #LEFT #CENTER
   d'4\startTextSpan 4 4 4 2 2 e'1\stopTextSpan R1
   \tempoTextSpan "rit." \tempo \markup \box "Grave" #LEFT #LEFT
   e'4\startTextSpan 4 4 4 2 2 f'1\stopTextSpan R1 \bar "|."
}
%%%%

The advantage of the above approach is that the final markup is really
nothing more than a concatenation of the elements.


> I also wasn't successful in adding \once \omit Score.MetronomeMark
> \tempo #tempo-unit = #metronome-count, so that the MIDI can pick up the
> new
> tempo mark, if a metronome is given (probably because the new tempo is
> converted to a markup and can't be used as a "real" tempo definition
> anymore?).

This is not going to be easy to solve.  You need to know when then
\stopTextSpan occurs so that the \tempo command applies at that moment. 
However that information is entirely unknown at the time of
\tempoTextSpan.

I would suggest handling MIDI tempo manually, that way you can issue as
many \tempo commands as needed to properly simulate the accel, rall, and
rit instructions.

Otherwise, this whole thing really looks like a job for a custom
engraver/performer.


-- Aaron Hill


--
www.martinrinconbotero.com

reply via email to

[Prev in Thread] Current Thread [Next in Thread]