2

The end goal is to have some function that takes a rest and optional text and outputs the rest with a fermata, boxed "vocals", and the optional key words.

Inspired by this question, I was able to make the following function. It somewhat works.

vocal-cue = #(define-music-function
           (parser location rest key-phrase)
           (ly:music? markup?)
           (make-relative (rest) rest
                          #{
                            $rest _\markup \center-column {
                              \box { Vocals }
                              \line \smaller { $key-phrase }
                            }^\fermata #}))

HOWEVER,

  1. The markup alignment is all wrong. Even if I \center-align the markup, it still is not correctly centered.
  2. The primary use case will be on full-measure rests (though there are one or two cues that last less than a full measure). Using \vocal-cue R1 "something" instead of \vocal-cue r1 "this somewhat works" puts the fermata and markup into the bar AFTER the rest it's supposed to annotate (but the markup is centered correctly relative to the fermata that time)
  3. (related to 2) When using R1, I get warning: Unattached TextScriptEvent in the console; using r1 gives no warnings or errors.

How can I make this have correct alignment and play nicely with full-bar rests?

1 Answer 1

3

First of all: Is there a good reason for using a make-relative?

Then:

  1. If you use center-column every line of the column is centered within the column. The column itself is not centered. Using center-align does so, as well as tweaking self-alignment-X to #CENTER (which is the same as 0). This is not exactly centered because the markup is aligned to the left edge of the rest. To change this tweak parent-alignment-X to #CENTER. (This does not apply to MM Rests, as these center by default.)

  2. The reason why this does not work with multimeasure rests is that these think differently internally, as can be seen with \displayMusic r1^"abc" and \displayMusic R1^"abc". But this something done by the Lilypond parser. With your syntax the parser does not know you’re creating a multimeasure rest, and thus create a regular TextScript event. This then leads to 3), as Lilypond has nothing to do with this TextScript event.

Note that your method does assume that the argument is a rest, but does not enforce it. You could add a check for MM Rests and handle these cases differently. Generally what you’re doing could be done from pure scheme (basically adding a TextScriptEvent or a MultiMeasureTextEvent to the articulation property).

But if you plan to do this only with rests I’d suggest you to instead use a syntax like this:

vocalCue =
#(define-music-function (duration key-phrase) ((ly:duration? #f) markup?)
   (if duration
       #{
         r $duration
         -\tweak self-alignment-X #CENTER -\tweak parent-alignment-X #CENTER
         _\markup\center-column { \box "Vocals" \smaller #key-phrase } ^\fermata
       #}
       #{
         r
          -\tweak self-alignment-X #CENTER -\tweak parent-alignment-X #CENTER
          _\markup\center-align\center-column { \box "Vocals" \smaller #key-phrase } ^\fermata
       #}))

MMvocalCue =
#(define-music-function (duration key-phrase) ((ly:duration? #f) markup?)
   (if duration
       
       #{
         R $duration _\markup \center-column { \box "Vocals" \smaller #key-phrase } ^\fermata
       #}
       #{
         R _\markup \center-column { \box "Vocals" \smaller #key-phrase } ^\fermata
       #}))

{
  2 \vocalCue "something" % no duration specified, use previous duration
  4 \vocalCue 2. "else" % with duration specified
  \MMvocalCue 1*2 "whatever" % MM rest
}

A different option (if we want to be more flexible) would be to use a post event notation like this:

vocalCue =
#(define-music-function (key-phrase) (markup?)
   #{
     -\tweak self-alignment-X #CENTER -\tweak parent-alignment-X #CENTER
     _\markup\center-align\center-column { \box "Vocals" \smaller #key-phrase } ^\fermata
   #})

{
  \textLengthOn
  r1-\vocalCue"something" R1-\vocalCue"different" s1-\vocalCue"or like this?" c'1-\vocalCue"or this?"
}
3
  • The reason for make-relative was because it was in the example I modified. This one worked, thanks. I've found the Lilypond documentation to be superb when I can find the relevant section, but the problem is knowing the correct keywords.
    – cjm
    Commented Sep 14, 2022 at 21:13
  • @cjm Added a different suggestion for how to do this.
    – Lazy
    Commented Sep 14, 2022 at 22:34
  • @cjm The make-relative was used in the linked example to allow for duplication of the argument note without \relative making problems. In your case this is not relevant.
    – Lazy
    Commented Sep 14, 2022 at 22:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.