[Top][All Lists]

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

eps, markup and adding hammer-on/pull-off to tablature

From: Federico Bruni
Subject: eps, markup and adding hammer-on/pull-off to tablature
Date: Wed, 22 Jul 2009 22:54:40 +0200
User-agent: Thunderbird (X11/20090608)

Hi all,

I'm trying to add hammer-on and pull-off to a tablature.
These are not supported by, so I was told to use an .eps file and \markup to get what I want.

I need your help to understand how to do it actually.
Please direct me to a place of the manual where this issue is discussed.
So far, I've seen this example but I don't know how to implement it:

I attach the .eps file, a simple example and the file (which is needed...for those who don't have and want to try..).

Could you give me some hint?
I don't know hot to go on..

Thanks in advance,

%%%% source file of the GNU LilyPond music typesetter
%%%% (c) 2009 Marc Hohl <address@hidden>

% some publications use the triangle-shaped note head
% for palm mute, so here we go:
palmMuteOn = { 
  \override NoteHead #'style = #'do
palmMuteOff = {
  \revert NoteHead #'style
% for single notes (even in chord constructs <...>),
% or grouped notes in {...}
palmMute =
#(define-music-function (parser location note) (ly:music?)
  ;; are we inside a <...>?
  (if (eq? (ly:music-property note 'name) 'NoteEvent)
      ;; yes -> add a tweak
      (begin (set! (ly:music-property note 'tweaks)
                    (acons 'style 'do (ly:music-property note 'tweaks)))
      ;; no -> use predefined commands to switch to triangle-shaped note heads

% x-tab-format uses a "x" instead of the fret number:
#(define (x-tab-format str context event)
      (markup #:musicglyph "noteheads.s2cross"))))

% dead notes are marked with a cross-shape note head,
% both in normal notation and in tablature:
deadNotesOn = {
  \set tablatureFormat = #x-tab-format
  \override NoteHead #'style = #'cross
deadNotesOff = {
  \unset tablatureFormat
  \revert NoteHead #'style
% for single notes (even in chord constructs <...>),
% or grouped notes in {...}
deadNote =
#(define-music-function (parser location note) (ly:music?)
  ;; are we inside a <...>?
  (if (eq? (ly:music-property note 'name) 'NoteEvent)
      ;; yes -> add a tweak
      (begin (set! (ly:music-property note 'tweaks)
                    (acons 'glyph-name "2cross"
                     (acons 'style 'special
                      (ly:music-property note 'tweaks))))
       ;; no -> use predefined commmands for changing
       ;; note head and tablature fret signs

% To distinguish between palm mute and dead notes, we have to
% check whether the grob-property 'style is set; if it is,
% then we want to draw a "whiteout" cross for the tab note head:
#(define (tab-note-head::whiteout-if-style-set grob)
  (let ((style (ly:grob-property grob 'style)))

       (if (and (symbol? style)
                (string=? (symbol->string style) "special"))
           (stencil-whiteout (ly:note-head::print grob))
           (ly:text-interface::print grob))))

% definitions for the "moderntab" clef:
% the "moderntab" clef will be added to the list of known clefs,
% so it can be used as any other clef:
% \clef "moderntab"
#(add-new-clef "moderntab" "markup.moderntab" 0 0 0)

% this function decides which clef to take
#(define (clef::print-modern-tab-if-set grob)
  (let ((glyph (ly:grob-property grob 'glyph)))
       ;; which clef is wanted?
       (if (string=? glyph "markup.moderntab")
           ;; if it is "moderntab", we'll draw it
           (let* ((staff-symbol (ly:grob-object grob 'staff-symbol))
                  (line-count   (ly:grob-property staff-symbol 'line-count))
                  (staff-space  (ly:grob-property staff-symbol 'staff-space 1)))
                 (grob-interpret-markup grob (make-customTabClef-markup 
line-count staff-space)))
           ;; otherwise, we simply use the default printing routine
           (ly:clef::print grob))))

% define sans serif-style tab-Clefs as a markup:
#(define-markup-command (customTabClef layout props num-strings staff-space) 
(integer? number?)
  (define (square x) (* x x))
  (let* ((scale-factor (/ staff-space 1.5))
         (font-size (- (* num-strings 1.5 scale-factor) 7))
         (base-skip (* (square (+ (* num-strings 0.195) 0.4)) scale-factor)))

        (interpret-markup layout props
           (markup #:vcenter #:bold
                   #:override (cons 'font-family 'sans)
                   #:fontsize font-size
                   #:override (cons 'baseline-skip base-skip)
                   #:left-align #:center-column ("T" "A" "B")))))

% if the stems are drawn, it is nice to have a double stem for
% (dotted) half notes to distinguish them from quarter notes:
#(define-public (tabvoice::draw-double-stem-for-half-notes grob)
  (let ((stem (ly:stem::print grob)))

       ;; is the note a (dotted) half note?
       (if (= 1 (ly:grob-property grob 'duration-log))
           ;; yes -> draw double stem
           (ly:stencil-combine-at-edge stem X RIGHT stem 0.5)
           ;; no -> draw simple stem

% as default, the glissando line between fret numbers goes
% upwards, here we have a function to correct this behavior:
#(define-public (glissando::calc-tab-extra-dy grob)
  (let* ((original (ly:grob-original grob))
         (left-bound (ly:spanner-bound original LEFT))
         (right-bound (ly:spanner-bound original RIGHT))
         (left-pitch (ly:event-property (event-cause left-bound) 'pitch))
         (right-pitch (ly:event-property (event-cause right-bound) 'pitch)))

    (if (< (ly:pitch-semitones right-pitch) (ly:pitch-semitones left-pitch))

% for ties in tablature, fret numbers that are tied to should be invisible,
% except for 'tied to' numbers after a line break; these will be parenthesized
% (thanks to Neil for his solution):
#(define (parenthesize-fret-nr grob)   
  ;; Helper function to parenthesize tab noteheads,
  ;; since we can't use ParenthesesItem at this stage
  ;; This is basically the same as the C++ function
  ;; in, converted to Scheme
  (let* ((font (ly:grob-default-font grob))
         (open (stencil-whiteout (ly:font-get-glyph font 
         (close (stencil-whiteout (ly:font-get-glyph font 
         (me (ly:text-interface::print grob)))

% ParenthesesItem doesn't work very well for TabNoteHead, since
% the parentheses are too small and clash with the staff-lines
% Define a callback for the 'stencils property which will tweak
% the parentheses' appearance for TabNoteHead
#(define (parentheses-item::calc-tabstaff-parenthesis-stencils grob)
   ;; the grob we want to parenthesize
   (let ((victim (ly:grob-array-ref (ly:grob-object grob 'elements) 0)))
     ;; check whether it's a notehead
     (if (grob::has-interface victim 'note-head-interface)
           ;; tweak appearance before retrieving list of stencils '(left-paren 
           (ly:grob-set-property! grob 'font-size -2)
           (ly:grob-set-property! grob 'padding 0)
           ;; apply whiteout to each element of the list
           (map stencil-whiteout (parentheses-item::calc-parenthesis-stencils 
         (parentheses-item::calc-parenthesis-stencils grob))))

% the handler for ties in tablature; split ties yield in a parenthesized
% fret number, otherwise the fret number will be invisible.
#(define (tie::handle-tab-tie grob)
   (let* ((original (ly:grob-original grob))
          (tied-tabnotehead (ly:spanner-bound grob RIGHT))
          (siblings (if (ly:grob? original)
                        (ly:spanner-broken-into original) '())))

     (if (and (>= (length siblings) 2)
              (eq? (car (last-pair siblings)) grob))
         ;; tie is split -> parenthesize
         (ly:grob-set-property! tied-tabnotehead 'stencil
                                (lambda (grob) (parenthesize-fret-nr grob)))

         ;; tie is not split -> make fret number invisible
         (ly:grob-set-property! tied-tabnotehead 'transparent #t))))

% repeat ties occur within alternatives in a repeat construct;
% the correspondig fret numbers are shown in parentheses:
#(define (repeat-tie::parenthesize-tab grob)
  (let ((tied-tabnotehead (ly:grob-object grob 'note-head)))

        (ly:grob-set-property! tied-tabnotehead 'stencil
                               (lambda (grob) (parenthesize-fret-nr grob)))))

% This allows to hide the fret numbers also in a RepeatTie.
% It can be called using this line:
% \override RepeatTie #'after-line-breaking = #repeat-tie::erase-tab
#(define (repeat-tie::erase-tab grob)
 (let ((tied-tabnotehead (ly:grob-object grob 'note-head)))

(ly:grob-set-property! tied-tabnotehead 'transparent #t)))

% a command for switching to the (improved) full notation
tabFullNotation = {
  % time signature
  \revert TabStaff.TimeSignature #'stencil
  % stems (the half note gets a double stem)
  \override TabVoice.Stem #'stencil = #tabvoice::draw-double-stem-for-half-notes
  % beams, dots
  \revert TabVoice.Beam #'stencil
  \revert TabVoice.Dots #'stencil
  \revert TabVoice.Tie #'stencil
  \revert TabVoice.Tie #'after-line-breaking
  \revert TabVoice.RepeatTie #'stencil
  \revert TabVoice.RepeatTie #'after-line-braking
  \revert TabVoice.LaissezVibrerTie #'stencil
  \revert TabVoice.Slur #'stencil
  \revert PhrasingSlur #'stencil
  % tuplet stuff
  \revert TabVoice.TupletBracket #'stencil
  \revert TabVoice.TupletNumber #'stencil
  % dynamic signs
  \revert DynamicText #'transparent
  \override DynamicTextSpanner #'stencil = ##f
  \revert TabVoice.DynamicTextSpanner #'stencil
  \revert TabVoice.Hairpin #'transparent
  % rests
  \revert TabVoice.Rest #'stencil
  \revert TabVoice.MultiMeasureRest #'stencil
  % markups
  \revert TabVoice.Script #'stencil
  \revert TabVoice.TextScript #'stencil

% the defaults for tablature:
\layout {
  \context {
    % the clef handler
    \override Clef #'stencil = #clef::print-modern-tab-if-set
    % no time signature
    \override TimeSignature #'stencil = ##f
    % better parentheses in a TabStaff
    \override ParenthesesItem #'stencils = 
  \context {
    % remove stems, beams, dots and rests ...
    \override Stem #'stencil = ##f
    \override Beam #'stencil = ##f
    \override Dots #'stencil = ##f
    \override Rest #'stencil = ##f
    \override MultiMeasureRest #'stencil = ##f
    % ... all kinds of ties/slurs
    \override Tie  #'stencil = ##f
    \override RepeatTie #'stencil = ##f
    \override LaissezVibrerTie #'stencil = ##f
    \override Slur #'stencil = ##f
    \override PhrasingSlur #'stencil = ##f
    % 'tied to' fret numbers become invisible or parenthesized, respectively)
    \override Tie #'after-line-breaking = #tie::handle-tab-tie
    \override RepeatTie #'after-line-breaking = #repeat-tie::parenthesize-tab
    % ... and all kinds of markups, spanners etc.
    \override TupletBracket #'stencil = ##f
    \override TupletNumber #'stencil = ##f
    \override DynamicText #'transparent = ##t 
    \override DynamicTextSpanner #'stencil = ##f
    \override TextSpanner #'stencil = ##f
    \override Hairpin #'transparent = ##t
    \override Script #'stencil = ##f
    \override TextScript #'stencil = ##f
    % the direction for glissando lines will be automatically corrected
    \override Glissando #'extra-dy = #glissando::calc-tab-extra-dy
    % dead notes in tablature and within chord constructs
    %\override TabNoteHead #'glyph-name = #note-head::calc-glyph-name
    \override TabNoteHead #'stencil = #tab-note-head::whiteout-if-style-set
\version "2.12.1"
\include ""
\include ""

upper = \relative c {
        \time 4/4
        \key g \major
        g'8(  a)  b(  c  b) ~  b4.

lower = \relative c {
        \time 4/4
        \key g \major
        g4  d'2.

\score {
   \new StaffGroup  <<
        \new Staff = "guitar" <<
          \context Voice = "upper guitar" { \clef "G_8" \voiceOne  \upper }
          \context Voice = "lower guitar" { \clef "G_8" \voiceTwo  \lower } >>
        \new TabStaff = "tab" <<
          \context TabVoice = "upper tab" { \clef "moderntab" \voiceOne \upper }
          \context TabVoice = "lower tab" { \clef "moderntab" \voiceTwo \lower 
} >>



reply via email to

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