LSR/1043

< LSR
Zur Navigation springen Zur Suche springen
PD Der Inhalt dieser Seite wurde aus dem LilyPond Snippet Repository übernommen und steht unter folgender Lizenz: CC0.
See Public Domain Help Pages for more info.
PD
Drawing an accordion standard stradella bass system

LSR Snippet Nr. 1043

Beschreibung

Lilypond has amazing drawing capabilities. This example demonstrates how to draw a Stradella bass system as described here Stradella bass system.

The Buttons Ab , C and E are marked. To mark a specific button by outlining it, enter its row and column number: first number: column (0=Beses , 19=A#) Second number: row (1=diminished chord, 2=7th chord, 3=minor chord, 4=major chord, 5=root note, 6=counter bass note) If the parameters are outside this range no button is outlined. Change the scale factor to a number you like. Usage: \markup \scale #'(0.75 . 0.75) \accordion-bass #4 #2

auto
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% LSR workaround:
#(set! paper-alist (cons '("snippet" . (cons (* 160 mm) (* 155 mm))) paper-alist))
\paper {
  #(set-paper-size "snippet")
  tagline = ##f
}

\markup\vspace #.5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Drawing a standard Stradella Accordion Bass
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#(define (create-pitch-list by-pitch result count)
"@var{result}is supposed to be a list containing a single pitch. 
A list of pitches is returned.  Each pitch is transposed by @var{by-pitch} in 
relation to the previous transposed pitch.
This is done @var{count} times.
Finally each calculated pitches pitch-ocatave is set zero.
Example:
(create-pitch-list (ly:make-pitch 0 1 0) (list (ly:make-pitch 0 0 0)) 2)
-> 
'(#<Pitch c' > #<Pitch d' > #<Pitch e' >)"
  (if (zero? count)
      (map 
        (lambda (p)
          (ly:make-pitch
            0
            (ly:pitch-notename p)
            (ly:pitch-alteration p)))
        (reverse result))
      (create-pitch-list
        by-pitch
        (cons (ly:pitch-transpose (car result) by-pitch) result)
        (1- count))))

#(define cycle-of-fifths ;; define circle of fifths as pitchlist
  (create-pitch-list (ly:make-pitch 0 4 0) (list (ly:make-pitch 0 6 -1)) 19))

#(define counter-basses ;; define counter bass notes as pitchlist
  (create-pitch-list (ly:make-pitch 0 4 0) (list (ly:make-pitch 0 1 -1/2)) 19))

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% pitch+music functions and definitions
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#(define (pitch-equals? p1 p2)
  (and
    (= (ly:pitch-alteration p1) (ly:pitch-alteration p2))
    (= (ly:pitch-notename p1) (ly:pitch-notename p2))))

#(define (note-name->string pitch)
  (let* ((a (ly:pitch-alteration pitch))
         (n (ly:pitch-notename pitch)))
    (make-concat-markup
      (list
        (make-simple-markup
          (vector-ref #("C" "D" "E" "F" "G" "A" "B") n))
        (if (= a 0)
            (make-line-markup (list empty-markup))
            (make-line-markup
              (list
                (alteration->text-accidental-markup a)
                (make-hspace-markup 0.1))))))))
  
#(define (chord-superscript n)
  ;; get the superscript for row n
  ;; counter bass notes and root notes have no superscript
  (cond
   ((= n 2) "M")
   ((= n 3) "m")
   ((= n 4) "7")
   ((= n 5) "o")
   (else "")))
   
#(define (get-index p)
  ;; get the index of a pitch p in the circle of fifths
  ;; this number is needed to create the labels of the bass buttons
  (list-index (lambda (x) (pitch-equals? x p)) cycle-of-fifths))

#(define (chord-name->markup p n)
  ;; make the name from a chord with pitch p in row n
  ;; you get an error when the pitch is not in the circle of fifths
  (let* ((i (get-index p))
         (terz (note-name->string (list-ref counter-basses i)))
         (bas (note-name->string (list-ref cycle-of-fifths i)))
         ;; root name of the button
         (simple
          (if (= n 0) terz bas)))
    (make-concat-markup
     (list
      simple
      (make-smaller-markup
       (make-raise-markup 0.6 (make-simple-markup (chord-superscript n))))))))
  
#(define-markup-command (accordion-bass layout props i-col i-row)
   (index? index?)
  ;; draw a standard stradella accordion bass with 120 buttons
  ;; mark the button in column i-col and i-row in a different color
  ;; column 1: B doubleflat, col 10: C, col 20: A#
  ;; the rows: 1=diminished chord, 2=7th chord,
  ;;           3=minor chord, 4=major chord, 5=root note, 6=counter bass note
  
  #:properties ((font-size 0) (thickness 2.5) (offset 3.5)(circle-padding 0.2))
  (let* ((ref-mrkp (interpret-markup layout props
                ;; This markup should have the largest extension and will serve
                ;; as a reference to calculate the largest circle diameter 
                ;; needed for button labels, checking out the horizontal extent 
                ;; of B DOUBLEFLAT sup M
                #{ 
                  \markup 
                    \fontsize #font-size \concat { 
                      "B" 
                      \musicglyph #"accidentals.flatflat" 
                      \smaller \raise #0.6 "M" 
                  } 
                #}))
         (ref-mrkp-x-ext (ly:stencil-extent ref-mrkp X))
         ;; calculating padding from circle-padding
         (pad (* (magstep font-size) circle-padding 2))
         ;; adding pad to extent of widest button label
         ;; don't mess radius with diameter!
         (dm-circle (+ (/ (cdr ref-mrkp-x-ext) 2) pad)) 
         ;; distance between two buttons in a row
         (col-dist (+ (* 2 dm-circle) pad)) 
         ;; you can vary the distance between the button rows
         (row-y-dist 0.95) 
         ;; horizontal shifting of the botton rows
         (h-shift (+ dm-circle pad)) 
         (thick 
           (* (magstep font-size) 
              (ly:output-def-lookup layout 'line-thickness)))
         (my-circle (make-circle-stencil dm-circle thick #f))
         (default-marked-button-stencil-proc
           (lambda (val)
             (ly:stencil-add
              (ly:stencil-in-color 
                (make-circle-stencil dm-circle 0 #t)
                1 1 1)
              (make-circle-stencil 
                (- dm-circle (* 5 thick)) (* val thick) #f)))))
    (apply ly:stencil-add
      empty-stencil
      (map
       (lambda (z)
         (ly:stencil-translate
          (apply ly:stencil-add
            empty-stencil
            (map
             (lambda (x)
               (let* ((chord-name-mrkp 
                        (chord-name->markup (list-ref cycle-of-fifths x) z))
                      (init-m 
                        (interpret-markup layout props
                          (if (= z 0)
                              (make-override-markup 
                                `(thickness . ,(* 10 thick))
                                (make-underline-markup chord-name-mrkp))
                              chord-name-mrkp)))
                      (m
                        (ly:make-stencil
                          (ly:stencil-expr init-m)
                          (ly:stencil-extent init-m X)
                          (ly:stencil-extent 
                            ;; stencil of a simple ref-markup to get correct
                            ;; baseline for all chord-name-markups
                            (interpret-markup layout props "B") 
                            Y))))
                 (ly:stencil-translate-axis
                   (ly:stencil-add
                     ;; mark C-Button
                     (if (and (= 1 z)(= 9 x))
                         (default-marked-button-stencil-proc 5)
                         empty-stencil)
                     ;; mark Ab- and E-Buttons
                     (if (and (= 1 z)(or (= 5 x)(= 13 x)))
                         (default-marked-button-stencil-proc 2.5)
                         empty-stencil)
                     ;; mark Button in column i-col and row i-row
                     ;; (some calculation is done because we draw row 6 first
                     ;;and work our way upwards)
                     (if (and (= (- 6 i-row) z)(= (1- i-col) x))
                         (make-circle-stencil dm-circle 0.7 #f)
                         empty-stencil)
                     ;; this is our chord name as button label
                     ;; underlined if counter bass note
                     (centered-stencil m)
                     ;; this is the button
                     my-circle)
                   (* x col-dist) 
                   X)))
             ;; loop through all columns
             (iota 20 0)))
          ;; calculate horizontal and vertical shift relative to the leftmost 
          ;; button in the row with the diminished chords
          (cons (* z h-shift) (* z col-dist (- row-y-dist)))))
       ;; loop through all rows
       (iota 6)))))
  
\markup \column {
  \vspace #2
  "Draw a standard Accordion bass system using Markup-funcions of Lilypond."
  \line { "The Buttons A" \flat ", C and E are marked." }
  "It's possible to mark a specific button, entering its row and column number"
  "Example:"
  \line { 
    \underline "first number:" 
    "column (1=B" 
      \concat {
      \hspace #-0.5 \super \fontsize #1 \doubleflat 
      ", 20=A" 
    }
    \hspace #-0.5 \super \sharp 
    ")" 
  }
  \line { 
    \underline "second number:" 
    "row (1=diminished chord, 2=7th chord, " 
  }
  "   3=minor chord, 4=major chord, 5=root note, 6=counter bass note)"
  "If the parameters are outside this range no button is colored."
  "Change the scale factor to a number you like."
  \line { 
    "Usage:" 
    \bold " \markup \scale #'(0.75 . 0.75) \accordion-bass #4 #2" 
  }
  \vspace #1
}

\markup \scale #'(0.75 . 0.75) \accordion-bass #5 #1
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% LSR workaround:
#(set! paper-alist (cons '("snippet" . (cons (* 160 mm) (* 155 mm))) paper-alist))
\paper {
  #(set-paper-size "snippet")
  tagline = ##f
}

\markup\vspace #.5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Drawing a standard Stradella Accordion Bass
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#(define (create-pitch-list by-pitch result count)
"@var{result}is supposed to be a list containing a single pitch. 
A list of pitches is returned.  Each pitch is transposed by @var{by-pitch} in 
relation to the previous transposed pitch.
This is done @var{count} times.
Finally each calculated pitches pitch-ocatave is set zero.
Example:
(create-pitch-list (ly:make-pitch 0 1 0) (list (ly:make-pitch 0 0 0)) 2)
-> 
'(#<Pitch c' > #<Pitch d' > #<Pitch e' >)"
  (if (zero? count)
      (map 
        (lambda (p)
          (ly:make-pitch
            0
            (ly:pitch-notename p)
            (ly:pitch-alteration p)))
        (reverse result))
      (create-pitch-list
        by-pitch
        (cons (ly:pitch-transpose (car result) by-pitch) result)
        (1- count))))

#(define cycle-of-fifths ;; define circle of fifths as pitchlist
  (create-pitch-list (ly:make-pitch 0 4 0) (list (ly:make-pitch 0 6 -1)) 19))

#(define counter-basses ;; define counter bass notes as pitchlist
  (create-pitch-list (ly:make-pitch 0 4 0) (list (ly:make-pitch 0 1 -1/2)) 19))

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% pitch+music functions and definitions
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#(define (pitch-equals? p1 p2)
  (and
    (= (ly:pitch-alteration p1) (ly:pitch-alteration p2))
    (= (ly:pitch-notename p1) (ly:pitch-notename p2))))

#(define (note-name->string pitch)
  (let* ((a (ly:pitch-alteration pitch))
         (n (ly:pitch-notename pitch)))
    (make-concat-markup
      (list
        (make-simple-markup
          (vector-ref #("C" "D" "E" "F" "G" "A" "B") n))
        (if (= a 0)
            (make-line-markup (list empty-markup))
            (make-line-markup
              (list
                (alteration->text-accidental-markup a)
                (make-hspace-markup 0.1))))))))
  
#(define (chord-superscript n)
  ;; get the superscript for row n
  ;; counter bass notes and root notes have no superscript
  (cond
   ((= n 2) "M")
   ((= n 3) "m")
   ((= n 4) "7")
   ((= n 5) "o")
   (else "")))
   
#(define (get-index p)
  ;; get the index of a pitch p in the circle of fifths
  ;; this number is needed to create the labels of the bass buttons
  (list-index (lambda (x) (pitch-equals? x p)) cycle-of-fifths))

#(define (chord-name->markup p n)
  ;; make the name from a chord with pitch p in row n
  ;; you get an error when the pitch is not in the circle of fifths
  (let* ((i (get-index p))
         (terz (note-name->string (list-ref counter-basses i)))
         (bas (note-name->string (list-ref cycle-of-fifths i)))
         ;; root name of the button
         (simple
          (if (= n 0) terz bas)))
    (make-concat-markup
     (list
      simple
      (make-smaller-markup
       (make-raise-markup 0.6 (make-simple-markup (chord-superscript n))))))))
  
#(define-markup-command (accordion-bass layout props i-col i-row)
   (index? index?)
  ;; draw a standard stradella accordion bass with 120 buttons
  ;; mark the button in column i-col and i-row in a different color
  ;; column 1: B doubleflat, col 10: C, col 20: A#
  ;; the rows: 1=diminished chord, 2=7th chord,
  ;;           3=minor chord, 4=major chord, 5=root note, 6=counter bass note
  
  #:properties ((font-size 0) (thickness 2.5) (offset 3.5)(circle-padding 0.2))
  (let* ((ref-mrkp (interpret-markup layout props
                ;; This markup should have the largest extension and will serve
                ;; as a reference to calculate the largest circle diameter 
                ;; needed for button labels, checking out the horizontal extent 
                ;; of B DOUBLEFLAT sup M
                #{ 
                  \markup 
                    \fontsize #font-size \concat { 
                      "B" 
                      \musicglyph #"accidentals.flatflat" 
                      \smaller \raise #0.6 "M" 
                  } 
                #}))
         (ref-mrkp-x-ext (ly:stencil-extent ref-mrkp X))
         ;; calculating padding from circle-padding
         (pad (* (magstep font-size) circle-padding 2))
         ;; adding pad to extent of widest button label
         ;; don't mess radius with diameter!
         (dm-circle (+ (/ (cdr ref-mrkp-x-ext) 2) pad)) 
         ;; distance between two buttons in a row
         (col-dist (+ (* 2 dm-circle) pad)) 
         ;; you can vary the distance between the button rows
         (row-y-dist 0.95) 
         ;; horizontal shifting of the botton rows
         (h-shift (+ dm-circle pad)) 
         (thick 
           (* (magstep font-size) 
              (ly:output-def-lookup layout 'line-thickness)))
         (my-circle (make-circle-stencil dm-circle thick #f))
         (default-marked-button-stencil-proc
           (lambda (val)
             (ly:stencil-add
              (ly:stencil-in-color 
                (make-circle-stencil dm-circle 0 #t)
                1 1 1)
              (make-circle-stencil 
                (- dm-circle (* 5 thick)) (* val thick) #f)))))
    (apply ly:stencil-add
      empty-stencil
      (map
       (lambda (z)
         (ly:stencil-translate
          (apply ly:stencil-add
            empty-stencil
            (map
             (lambda (x)
               (let* ((chord-name-mrkp 
                        (chord-name->markup (list-ref cycle-of-fifths x) z))
                      (init-m 
                        (interpret-markup layout props
                          (if (= z 0)
                              (make-override-markup 
                                `(thickness . ,(* 10 thick))
                                (make-underline-markup chord-name-mrkp))
                              chord-name-mrkp)))
                      (m
                        (ly:make-stencil
                          (ly:stencil-expr init-m)
                          (ly:stencil-extent init-m X)
                          (ly:stencil-extent 
                            ;; stencil of a simple ref-markup to get correct
                            ;; baseline for all chord-name-markups
                            (interpret-markup layout props "B") 
                            Y))))
                 (ly:stencil-translate-axis
                   (ly:stencil-add
                     ;; mark C-Button
                     (if (and (= 1 z)(= 9 x))
                         (default-marked-button-stencil-proc 5)
                         empty-stencil)
                     ;; mark Ab- and E-Buttons
                     (if (and (= 1 z)(or (= 5 x)(= 13 x)))
                         (default-marked-button-stencil-proc 2.5)
                         empty-stencil)
                     ;; mark Button in column i-col and row i-row
                     ;; (some calculation is done because we draw row 6 first
                     ;;and work our way upwards)
                     (if (and (= (- 6 i-row) z)(= (1- i-col) x))
                         (make-circle-stencil dm-circle 0.7 #f)
                         empty-stencil)
                     ;; this is our chord name as button label
                     ;; underlined if counter bass note
                     (centered-stencil m)
                     ;; this is the button
                     my-circle)
                   (* x col-dist) 
                   X)))
             ;; loop through all columns
             (iota 20 0)))
          ;; calculate horizontal and vertical shift relative to the leftmost 
          ;; button in the row with the diminished chords
          (cons (* z h-shift) (* z col-dist (- row-y-dist)))))
       ;; loop through all rows
       (iota 6)))))
  
\markup \column {
  \vspace #2
  "Draw a standard Accordion bass system using Markup-funcions of Lilypond."
  \line { "The Buttons A" \flat ", C and E are marked." }
  "It's possible to mark a specific button, entering its row and column number"
  "Example:"
  \line { 
    \underline "first number:" 
    "column (1=B" 
      \concat {
      \hspace #-0.5 \super \fontsize #1 \doubleflat 
      ", 20=A" 
    }
    \hspace #-0.5 \super \sharp 
    ")" 
  }
  \line { 
    \underline "second number:" 
    "row (1=diminished chord, 2=7th chord, " 
  }
  "   3=minor chord, 4=major chord, 5=root note, 6=counter bass note)"
  "If the parameters are outside this range no button is colored."
  "Change the scale factor to a number you like."
  \line { 
    "Usage:" 
    \bold " \markup \scale #'(0.75 . 0.75) \accordion-bass #4 #2" 
  }
  \vspace #1
}

\markup \scale #'(0.75 . 0.75) \accordion-bass #5 #1

Unterseiten