I had started a thread about a month ago about harmonica tab. Mark's
demonstration file has helped me understand how define-music-funciton
can be used here.

I've attached an iteration with unicode arrows to indicate breath
direction (blow or draw) and holes for a standard C-tuning diatonic
harmonica. I also included horizontal bars to indicate half-step
bends. I'm not completely happy with the arrows and how they compose
with horizontal lines (probably manually specifying lines to draw the
arrows would be better).

The other issue that I'm not happy about is how ties are handled.
Ideally a tab marking would not be present when a there is not a new
note being sounded. Alternatively, I guess tie events could be
captured and some notation made in the tab line.

Also, note that it is important to use "\harmonicaTab \relative c' {
}" rather than "\relative c' \harmonicaTab { }" so that tab numbers
are in the appropriate octave.

-- Bradford Powell
-- [email protected]
\version "2.12.3"

#(define (NoteEvent? music)
   (equal? (ly:music-property music 'name) 'NoteEvent))

#(define (EventChord? music)
   (equal? (ly:music-property music 'name) 'EventChord))

#(define* (blow hole #:optional (bends 0))
  (case bends
    ((0) (markup #:center-column (#:simple hole #:huge "↑")))
    ((1) (markup #:center-column (#:simple hole #:huge (#:combine "↑" "–"))))
    ((2) (markup #:center-column (#:simple hole #:huge (#:combine "↑" "="))))
    ((3) (markup #:center-column (#:simple hole #:huge (#:combine "↑" "≡"))))
    (else (markup #:simple " "))))
#(define* (draw hole #:optional (bends 0))
  (case bends
    ((0) (markup #:center-column (#:simple hole #:huge "↓")))
    ((1) (markup #:center-column (#:simple hole #:huge (#:combine "↓" "–"))))
    ((2) (markup #:center-column (#:simple hole #:huge (#:combine "↓" "="))))
    ((3) (markup #:center-column (#:simple hole #:huge (#:combine "↓" "≡"))))
    (else (markup #:simple " "))))

#(define (get-harmonica-tab NoteEvent)
   (case (ly:pitch-semitones (ly:music-property NoteEvent 'pitch))
    ((-12) (blow "1"))
    ((-11) (draw "1" 1))
    ((-10) (draw "1"))
    ;((-9) (overblow "1"))
    ((-8) (blow "2"))
    ((-7) (draw "2" 2))
    ((-6) (draw "2" 1))
    ((-5) (draw "2"))
    ;((-5) (blow "3"))
    ((-4) (draw "3" 3))
    ((-3) (draw "3" 2))
    ((-2) (draw "3" 1))
    ((-1) (draw "3"))
    ((0) (blow "4"))
    ((1) (draw "4" 1))
    ((2) (draw "4"))
    ;((3) (overblow "4"))
    ((4) (blow "5"))
    ((5) (draw "5"))
    ;((6) (overblow "5"))
    ((7) (blow "6"))
    ((8) (draw "6" 1))
    ((9) (draw "6"))
    ;((10) (overblow "6"))
    ((11) (draw "7"))
    ((12) (blow "7"))
    ;((13) (overdraw "7"))
    ((14) (draw "8"))
    ((15) (blow "8" 1))
    ((16) (blow "8"))
    ((17) (draw "9"))
    ((18) (blow "9" 1))
    ((19) (blow "9"))
    ;((20) (overdraw "9"))
    ((21) (draw "10"))
    ((22) (blow "10" 2))
    ((23) (blow "10" 1))
    ((24) (blow "10"))
    (else (markup #:simple " "))))

#(define (make-textscript dir txt)
   (make-music 'TextScriptEvent
               'direction dir
               'text txt))

#(define (make-tab-number NoteEvent)
   (make-textscript
     UP
     (get-harmonica-tab NoteEvent)))

#(define (make-tab-numbers EventChord)
   (let ((elts (ly:music-property EventChord 'elements)))
     (map make-tab-number (filter NoteEvent? elts))))

#(define (add-tab-numbers music)
   (if (EventChord? music)
       (set! (ly:music-property music 'elements)
             (append (ly:music-property music 'elements)
                     (make-tab-numbers music))))
    music)

harmonicaTab =
#(define-music-function
  (parser location music)
  (ly:music?)
  (music-map add-tab-numbers music))

\harmonicaTab \relative c' {
  c <d f> <c e> d ~ | d e f a | c e g b |
}
_______________________________________________
lilypond-user mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to