lilypond-user
[Top][All Lists]
Advanced

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

Re: Combine Text/Lyrics with bass figures


From: Moritz Heffter
Subject: Re: Combine Text/Lyrics with bass figures
Date: Fri, 26 Jun 2020 13:26:24 +0200

Hi Urs, hi Lukas,

That looks very good, Lukas. And thank for coming up with the idea of integrating arabic scale degree numbers in lilypond, Urs. I’ll join the lobby team if you want :).

For the usage of the numbers I just have two remarks, that might be far from what is currently discussed. But I think it might be good to think about the requirements for the arabic numbers.

Just two thoughts on that:
(1) I wonder if it’s good to combine the arabic scale degrees with the figured bass in one layer. There might be reasons to put figure bass numbers above the bass line. I’m not so deep in the figured bass mode in lilypond (only use one layer to write the numbers) but I think in order to be flexibel in layout and in keeping information not too nestled it might be good, to separate these information.

(2) There might also be cases where you have more that one row of arabic numbers to indicate other options. My first intention here would be to have a single layer for every key, that is used in the analysis. If there’s an option to hide the layer where it is not used.

I hope I’m not making things more complicated and got the intention right :).

Best,
Moritz


Am 26.06.2020 um 12:36 schrieb Urs Liska <lists@openlilylib.org>:

Hi Lukas,

that's great, and I hope you'll stick with me when I try to work that
out into a generally usable (i.e. sufficiently flexible) solution to
lobby with the GMTH ;-)

Am Freitag, den 26.06.2020, 10:07 +0200 schrieb Lukas-Fabian Moser:
Hi Urs,

Hey, that looks promising - I didn't know that.
Now I'd only need a way to properly do the vertical alignment
against 
the baseline of the lowest markup:

\figures {
 <6 4 \markup { \circle \number 5 }>
 <3+ \markup { \circle \number 6 }>
}

This might be achieved using an inversed stacking direction. 

Great.

Harm's 
figure reversal function can then be used to enable the user to
still 
enter bass figures in the "usual" way.

With a bit of syntactic sugar, this might look as below.

I've started working on that, see below ...


Problems so far:

1) The figures are still down-aligned. This might be remedied for 
instance by defining a "maximal" number of figures for which to
leave 
space and inserting placeholders. (This reminds me of one of my 
long-time wishes, namely to have a dedicated "empty" figure for use
in 
FiguredBass, which is sometimes needed to leave space for figures
that 
are added later in a chord. I once patched my LilyPond to allow for 
this, but this was an ugly hack involving transparent figures...)

I have *not* started working on this yet. I don't find transparent
markups that offensive. It's a commonplace approach also for achieving
consistent baselines for strings without as/descenders.

However, what we *actually* want is a common number of items *per
system*, not for the whole score. What if we determine maximum number
of entries of 3 and have many systems only use one - that would make
for ugly whitespace all over the place.

The only remedy I can see right now would be to deal with this in an
after-line-breaking stencil. From there we could iterate over the whole
system and check the maximum number of actually used layers. The result
should be cached so this process is done only once per system.
However, this won't always work because the context may not have been
pushed sufficiently far down in situations like the attached example.


2) The "get-current-duration" function is simply awful: I didn't
know 
how to find out which duration the parser would assign to a 
duration-less note/bass figure, so I just let it create a note and
see 
what its duration becomes. There must be a decent way to achieve
this. 
(I need to give the bassStufe-function a duration because otherwise
it 
does not work with figure \none.)

I've made a number of improvements to your code:

1)
reverseFigures creates a new music _expression_, from which you later
retrieve the 'elements, which is unnecessary. (I renamed it to parse-
signature

2)
The figures do have their durations included, so we can retrieve them
*here* and reuse that information later when generating the
BassFigureEvent for the bass step markup.

2a)
Instead of \none I rewrote \scaledeg to accept either a figure
signature or a duration. This gives a nice interface where you can just
specify a duration for an empty figure.

Apart from that I've just added a few predicates to make the input more
reliable and have typecheck warnings.

I think this is going into a nice direction!

Best
Urs

\version "2.20.0"

\layout {
 \override BassFigureAlignment.stacking-dir = #UP
}

#(define (parse-signature sig) ; based on \reverseFigures by Harm
  (if
   ;; sig is either an EventChord (music) or a duration
   (ly:music? sig)
   (let*
    ((reversed
      (reverse
       (map
        (lambda (e)
          (cond ((and
                  (eq? #t (ly:music-property e 'bracket-start))
                  (eq? #t (ly:music-property e 'bracket-stop)))
                 '())
            ((eq? #t (ly:music-property e 'bracket-start))
             (begin
              (ly:music-set-property! e 'bracket-start '())
              (ly:music-set-property! e 'bracket-stop #t)))
            ((eq? #t (ly:music-property e 'bracket-stop))
             (begin
              (ly:music-set-property! e 'bracket-stop '())
              (ly:music-set-property! e 'bracket-start #t))))
          e)
        (ly:music-property sig 'elements))))
     (duration (ly:music-property (first reversed) 'duration)))
    (cons duration reversed))
   (cons sig '())
   ))

#(define (scale-degree degree duration)
  (let
   ((step-markup
     (if (eqv? degree 0)
         (markup #:null)
         (markup #:circle #:small #:number (number->string degree)))))
   (make-musics
    'BassFigureEvent
    'duration
    duration
    'text
    (markup #:with-dimensions '(0 . 1) '(0 . 5) step-markup))
   ))

#(define (bass-degree? obj)
  "A bass degree is either a number between 1 and 7 or 0 (eqv. to
nothing)!"
  (and (integer? obj) (> 8 obj) (< -1 obj)))

#(define (figure-signature? obj)
  "A figure signature is either an EventChord music or a duration."
  (or
   (and
    (ly:music? obj)
    (music-is-of-type? obj 'event-chord))
   (ly:duration? obj)))

scaledeg =
#(define-music-function (num signature) ((bass-degree? 0) figure-
signature?)
  (let*
   ((props (parse-signature signature))
    (duration (car props))
    (used-signature (cdr props)))
   (make-music
    'EventChord
    'elements
    (cons (scale-degree num duration)
      used-signature))))

<<
 \new Staff { \clef bass d2 e4 fis g2 a b cis' d' g2 fis1 }
 \figures {
   \scaledeg 1 <5 3>2
   \scaledeg 2 <6>4
   \scaledeg 3 <6>4
   \scaledeg 4 <6 5>2
   \scaledeg 5 2
   \scaledeg 6 <6>2
   \scaledeg 7 <6>4
   \scaledeg <6 5>
   \scaledeg 1 <5 3>2
   \scaledeg 4 <4 2>
   \scaledeg 3 <6>1
 }



Best
Lukas



\version "2.20.0"

\layout {
  \override BassFigureAlignment.stacking-dir = #UP
}

reverseFigures = % by Harm
#(define-music-function (mus)(ly:music?)
   (music-map
    (lambda (m)
      (if (music-is-of-type? m 'event-chord)
          (let ((ev-chrd-elts (ly:music-property m 'elements)))
            (ly:music-set-property! m 'elements
                                    (reverse
                                     (map
                                      (lambda (e)
                                        (cond ((and (eq? #t 
(ly:music-property e 'bracket-start))
                                                    (eq? #t 
(ly:music-property e 'bracket-stop)))
                                               '())
                                              ((eq? #t 
(ly:music-property e 'bracket-start))
                                               (begin
(ly:music-set-property! e 'bracket-start '())
(ly:music-set-property! e 'bracket-stop #t)))
                                              ((eq? #t 
(ly:music-property e 'bracket-stop))
                                               (begin
(ly:music-set-property! e 'bracket-stop '())
(ly:music-set-property! e 'bracket-start #t))))
                                        e)
                                      ev-chrd-elts)))
            m)
          m))
    mus))

get-current-duration =
#(define-scheme-function () ()
   (let* ((tempmusic #{ {a} #})
          (els (ly:music-property tempmusic 'elements)))
     (ly:music-property (car els) 'duration)))

bassStufe =
#(define-music-function (num) (integer?)
   (let ((scale-markup
          (if (> num 0)
              #{ \markup \circle \small \number #(number->string
num) #}
              (markup #:null))))

     (make-music
      'BassFigureEvent
      'duration
      (get-current-duration)
      'text
      #{ \markup
         \with-dimensions #'(0 . 1) #'(0 . 5)
         #scale-markup
      #})))

scaledeg =
#(define-music-function (num signatur) ((integer? 0) ly:music?)
   (let ((signatur-reversed (reverseFigures signatur)))
     (make-music
      'EventChord
      'elements
      (cons (bassStufe num)
            (ly:music-property signatur-reversed 'elements)))))

none = {}

<<
  \new Staff { \clef bass d2 e4 fis g2 a b cis' d' g2 fis1 }
  \figures {
    \scaledeg 1 <5 3>2
    \scaledeg 2 <6>4
    \scaledeg 3 <6>
    \scaledeg 4 <6 5>2
    \scaledeg 5 \none
    \scaledeg 6 <6>2
    \scaledeg 7 <6>4
    \scaledeg <6 5>
    \scaledeg 1 <5 3>2
    \scaledeg 4 <4 2>
    \scaledeg 3 <6>1
  }




<scaledegrees.png>


reply via email to

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