lilypond-user
[Top][All Lists]
Advanced

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

Re: roman numerals


From: address@hidden
Subject: Re: roman numerals
Date: Wed, 21 Nov 2012 08:58:05 +0100

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
    }
  }
}




reply via email to

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