lilypond-user
[Top][All Lists]
Advanced

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

Re: roman numerals


From: Curt
Subject: Re: roman numerals
Date: Wed, 21 Nov 2012 00:05:25 -0800

Yes, this is what I ended up using.  Works pretty well, a couple of images attached.  It'd be nice if lilypond supported this natively someday.  Most of what I need could be accomplished just by by chord mode allowing roman numerals as well as note names.  Doesn't need to support transposition since they'd be the same in all keys.




On Nov 20, 2012, at 11:58 PM, "address@hidden" <address@hidden> wrote:

On 21 nov. 2012, at 08:43, Michael Rivers <address@hidden> wrote:

As far as I know, Lilypond doesn't support Roman numeral analysis. I can't
find it anywhere in the documentation, at least. Somebody please correct me
if I'm wrong, because I would love to be able to do it.

The snippet posted in the original post doesn't work for me. I don't think
\rN is a real command. I can't get 2.16.1 to recognize it.

I have tried to add Roman numerals to figured bass in Lilypond with \markup
commands, but it looks very wrong.



Dunno who I stole this from, but I've used it a lot...

Cheers,
MS

\version "2.17.5"
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% A function to create Roman numerals for harmonic analysis.
%%
%% Syntax: \markup \rN { ...list of symbols... }
%%
%% List symbols in this order (as needed): Roman numeral, quality, top number of
%% inversion symbol, bottom number, "/" (if secondary function), Roman numeral.
%%
%% "bVII" creates flat VII; "svi" creates sharp vi; "Ab" creates A-flat; "As" A-sharp
%%
%% Qualities: use "o" for diminished, "h" for half-diminished,
%% "+" for augmented, "b" for flat.  Use any combination of "M" and "m":
%% M, m, MM7, Mm, mm, Mmm9, etc. Added-note chords: add, add6, etc.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#(define rN-size -1) %% change to vary size of numerals

#(define scaling (magstep rN-size))

%%% change constant to adjust distance between characters
#(define X-separation (* scaling 0.2))

%%% symmetrical distance between inversion figures and midline
#(define inversion-Y-separation (* scaling 0.1))

#(define dim
  (markup
   #:override `(thickness . ,scaling)
   #:draw-circle (* scaling 0.25) (* scaling 0.1) #f))

#(define half-dim
  (markup
   #:override `(thickness . ,scaling)
   #:combine
   (#:combine dim
              #:draw-line `(,(* scaling -0.3) . ,(* scaling -0.3)))
   #:draw-line `(,(* scaling 0.3) . ,(* scaling 0.3))))

#(define augmented
  (markup
   #:override `(thickness . ,scaling)
   #:combine
   (#:combine #:draw-line `(,(* scaling -0.25) . 0)
              #:draw-line `(0 . ,(* scaling -0.25)))
   (#:combine #:draw-line `(,(* scaling 0.25) . 0)
              #:draw-line `(0 . ,(* scaling 0.25)))))

#(define (acc? str num) (string? number?)
  (eq? num (string-index str (char-set #\b #\s #\n)))) %% checks for accidental

#(define acc `((#\b . ,(markup #:flat))
              (#\s . ,(markup #:sharp))
              (#\n . ,(markup #:natural))))

#(define-markup-command (rN layout props symbols) (markup-list?)
  ;; isolate and normalize segment of list before slash (if any)
  (let* ((up-to-slash (car (split-list-by-separator symbols (lambda (x) (equal? x "/")))))
         (first-part (append up-to-slash (make-list (- 4 (length up-to-slash)) "")))
         (normalized
          (if (or (string-index (cadr first-part) (string->char-set "mMaAdD"))
                  (not (null? (lset-intersection equal? '("o" "h" "+" "b") (cdr first-part)))))
              first-part
              (list (car first-part) "" (cadr first-part) (caddr first-part))))
         (base (car normalized))
         (quality (cadr normalized))
         (quality-marker
          (cond ((equal? "o" quality) (markup #:raise (* 0.5 scaling) dim))
                ((equal? "h" quality) (markup #:raise (* 0.5 scaling) half-dim))
                ((equal? "+" quality) (markup #:raise (* 0.5 scaling) augmented))
                ((equal? "b" quality) (markup #:raise (* 0.5 scaling) #:flat))
                ((equal? "" quality) (markup #:null))
                (else (markup quality))))
         (upper (caddr normalized))
         (lower (cadddr normalized))
         ;; isolate slash and what follows
         (second-part (if (member "/" symbols) (member "/" symbols) '("" "")))
         (rN-two (cadr second-part))
         (base-stencil
          (interpret-markup layout
                            (cons (list `(word-space . ,X-separation) `(font-size . ,rN-size)) props)
                            (markup base)))
         ;; calculate Y midpoint of base (for positioning quality and inversion)
         (vertical-offset (/ (interval-length (ly:stencil-extent base-stencil Y)) 2))
         (inversion-stencil
          (if (equal? lower "")
              (ly:stencil-translate-axis (interpret-markup layout
                                                           (cons (list `(word-space . ,X-separation)) props)
                                                           (markup #:fontsize (- rN-size 5) upper))
                                         inversion-Y-separation Y)

              (ly:stencil-aligned-to
               (ly:stencil-combine-at-edge
                (interpret-markup layout
                                  (cons (list `(word-space . ,X-separation)) props)
                                  (markup #:fontsize (- rN-size 5) upper))
                Y DOWN
                (interpret-markup layout
                                  (cons (list `(word-space . ,X-separation)) props)
                                  (markup #:fontsize (- rN-size 5) lower))
                (* 2 inversion-Y-separation))
               Y CENTER)))
         (quality-marker-stencil
          (ly:stencil-translate-axis (interpret-markup layout
                                                       (cons (list `(word-space . ,X-separation)) props)
                                                       (markup #:fontsize (- rN-size 5) quality-marker))
                                     inversion-Y-separation Y))

         ;; base, quality marker, and inversion
         (one
          (ly:stencil-combine-at-edge

           (ly:stencil-combine-at-edge
            (interpret-markup layout
                              (cons (list `(word-space . ,X-separation)) props)
                              ;; accommodates an accidental either before or after
                              (cond ((acc? base 0)
                                     (markup #:fontsize (- rN-size 4)
                                             #:raise (* 2 vertical-offset) #:vcenter
                                             (assoc-ref acc (string-ref base 0))
                                             #:fontsize rN-size (substring base 1)))

                                    ((acc? base (1- (string-length base)))
                                     (markup #:fontsize rN-size
                                             (substring base 0 (1- (string-length base)))
                                             #:fontsize (- rN-size 4) #:raise (/ scaling 2)
                                             (assoc-ref acc (string-ref base (1- (string-length base))))))

                                    (else (markup #:fontsize rN-size base))))
            X RIGHT
            (ly:stencil-translate-axis quality-marker-stencil vertical-offset Y)
            (if (equal? "" quality) 0 X-separation))

           X RIGHT
           (ly:stencil-translate-axis inversion-stencil vertical-offset Y)
           (if (equal? "" upper) 0 X-separation)))

         ;; slash and after
         (two
          (ly:stencil-combine-at-edge
           (interpret-markup layout
                             (cons (list `(word-space . ,X-separation) `(font-size . ,rN-size)) props)
                             (if (equal? "" lower)
                                 (markup (car second-part))
                                 (markup #:hspace X-separation (car second-part))))
           X RIGHT
           (interpret-markup layout
                             (cons (list `(word-space . ,X-separation)) props)
                             (cond ((acc? rN-two 0)
                                    (markup #:fontsize (- rN-size 4)
                                            #:raise scaling (assoc-ref acc (string-ref rN-two 0))
                                            #:fontsize rN-size (substring rN-two 1)))

                                   ((acc? rN-two (1- (string-length rN-two)))
                                    (markup #:fontsize rN-size
                                            (substring rN-two 0 (1- (string-length rN-two)))
                                            #:fontsize (- rN-size 4) #:raise (/ scaling 2)
                                            (assoc-ref acc (string-ref rN-two (1- (string-length rN-two))))))

                                   (else (markup #:fontsize rN-size rN-two))))
           X-separation)))

    (if (equal? rN-two "")
        one
        (ly:stencil-combine-at-edge one X RIGHT two 0))))

bassline = \relative c' {
 \clef bass
 \key g \major
 \time 3/4
 g4 fis f
 e es es
 d2 d,4
 g2.
 \bar "||"
}

analysis = \lyricmode {
 \set stanza = #"G:     " % use spaces to adjust position of key indication
 \markup \rN { I } \markup \rN { V 6 5 } \markup \rN { vii o 4 3 / IV }
 \markup \rN { IV 6 } \markup \rN { ii h 4 3 } \markup \rN { Fr + 6 }
 \markup \rN { I 6 4 } \markup \rN { V 7 }
 \markup \rN { I }
}

\score {
 \new Staff <<
   \new Voice = "bass" { \bassline }
   \new Lyrics \lyricsto "bass" { \analysis }

 \layout {
   \context {
     %\Score
     %\override SpacingSpanner #'shortest-duration-space = #5
   }
 }
}


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


reply via email to

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