diff --git a/blue-shift.ly b/blue-shift.ly new file mode 100644 index 0000000..f2551e5 --- /dev/null +++ b/blue-shift.ly @@ -0,0 +1,66 @@ +\version "2.18.2" +\language "english" +\include "lib/guitar-bend.ily" + +\header { + title = "Blue Shift" + composer = "Tommy Montgomery" + copyright = "(c) 2009 Tommy Montgomery" +} + +globalConfig = { + \key b \mixolydian + \time 4/4 + \numericTimeSignature + \tempo 4 = 90 +} + +rhythmGuitar = \new Staff \with { + instrumentName = "Rhythm Guitar" +} { + \globalConfig + \clef treble \relative c' { + \repeat unfold 3 { b16 fs' a fs a( b) fs a fs a( b) fs c' fs, b( a) | } + b,16 fs' a fs a( b) fs a \times 4/6 { c( b a) g( fs e) } \times 4/6 { ds( e fs) e( ds) c } | + + \repeat unfold 3 { b16 fs' a fs a( b) fs a fs a( b) fs c' fs, b( a) | } + b,16 fs' a fs a( b) fs a \times 4/6 { c( b a) g( fs e) } \times 4/6 { ds( e fs) e( ds) c } | + } +} + +leadGuitarOne = { + \relative c'' { + \set TabStaff.minimumFret = #8 + \set TabStaff.restrainOpenStrings = ##t + \omit Voice.StringNumber + + r1 | r1 | r1 | + r2 \times 4/6 { c16\2( b a) g\3( fs e) } \times 4/6 { ds( e fs) e( ds) c } | + + \repeat unfold 3 { b16 fs' a fs a( b) fs a fs a( b) fs c'\2 fs, b( a) | } + b,16 fs' a fs a( b) fs a \times 4/6 { c\2( b a) g( fs e) } \times 4/6 { ds( e fs) e( ds) c } | + + fs4. b,8 ~ b2 \grace { b16 ds fs\2 b\1 } | + c8( b\1) g d\3 ~ d4. d16\3( e) | + \bendGrace e( fs4.) \bendGrace e8( fs\harmonic) ~ fs8 e d\3 e ~ | + e cs4\3 a8\4 ~ a4 a16\4 cs\3 e cs\3 | + + } +} + +\score { + << + \new Staff \with { \clef "G_8" instrumentName = "Lead I" } { + \globalConfig + \leadGuitarOne + } + \new TabStaff { \leadGuitarOne } + \rhythmGuitar + + >> + \layout { + \context { + \Staff \RemoveEmptyStaves + } + } +} \ No newline at end of file diff --git a/blue-shift.pdf b/blue-shift.pdf new file mode 100644 index 0000000..16e5538 Binary files /dev/null and b/blue-shift.pdf differ diff --git a/lib/guitar-bend.ily b/lib/guitar-bend.ily new file mode 100644 index 0000000..0534c77 --- /dev/null +++ b/lib/guitar-bend.ily @@ -0,0 +1,443 @@ +\version "2.16.2" % absolutely necessary! + +\header { + snippet-title = "Guitar string bending notation" + snippet-author = "Marc Hohl" + snippet-source = "http://code.google.com/p/lilypond/issues/detail?id=1196" + snippet-description = \markup { + This snippet allows to typeset bend symbols - + typically used on guitar - on Staff and TabStaff. + While issue 1196 aims to create a specific engraver + for bends, this snippet leverages the slur engraver. + } + % add comma-separated tags to make searching more effective: + tags = "guitar, bend, string bending" + % is this snippet ready? See meta/status-values.md + status = "undocumented" +} + +% TODO: +% - draw dashed line for \holdBend +% - enable consecutive bend ups +% - simplify \preBend and \holdBend usage +% - ... + +#(display "\nbend.ly ─ 2011-03-11 (revised: 2013-07-16)\n\n") + +%%% sizes and values (to be changed/adapted): + +#(define bend-line-thickness 0.1) + +#(define bend-arrow-curvature-factor 0.35) + +#(define y-distance-from-tabstaff-to-arrow-tip 2.75) + +#(define consecutive-bends-arrow-height 2.75) + +#(define bend-arrowhead-height 1.25) + +#(define bend-arrowhead-width 0.8) + +#(define y-distance-from-staffline-to-arrow 0.35) + +%%% internal commands +#(define (quarterdiff->string quarterdiff) + (let ((wholesteps (floor (/ quarterdiff 4)))) + + (string-append (case wholesteps + ((0) "") + (else (number->string wholesteps))) + (case (modulo quarterdiff 4) + ((1) "¼") + ((2) "½") + ((3) "¾") + (else ""))))) + +%%% markup commands + +#(define-markup-command (pointedSlur layout props thickness bx by mx my ex ey) + (number? number? number? number? number? number? number?) + (interpret-markup layout props + (markup #:postscript + (ly:format "~f setlinewidth + ~f ~f moveto + ~f ~f lineto + ~f ~f lineto stroke" thickness bx by mx my ex ey)))) + +#(define-markup-command (drawBendArrow layout props + thickness begin-x middle-x end-x begin-y end-y arrow-lx arrow-rx arrow-y outstring) + (number? number? number? number? number? number? number? number? number? string?) + (interpret-markup layout props + (markup #:postscript + (ly:format "~f setlinewidth + ~f ~f moveto + ~f ~f lineto + ~f ~f ~f ~f ~f ~f curveto + stroke + ~f ~f moveto + ~f ~f lineto + ~f ~f lineto + closepath fill" +thickness +begin-x begin-y +middle-x begin-y +middle-x begin-y end-x begin-y end-x arrow-y +arrow-lx arrow-y +end-x end-y +arrow-rx arrow-y) + #:hspace 0 + #:translate (cons (- end-x 1.2) (+ end-y 0.5)) + #:fontsize -2 + #:bold + ;; changed: + ;#:center-column (outstring) + outstring + ))) +#(define-markup-command (drawHoldBendWithArrow layout props + thickness begin-x begin-y end-x end-y arrow-lx arrow-rx arrow-y outstring) + (number? number? number? number? number? number? number? number? string?) + (interpret-markup layout props + (markup #:postscript + (ly:format "~f setlinewidth + ~f ~f moveto + ~f ~f lineto + stroke + ~f ~f moveto + ~f ~f lineto + ~f ~f lineto + closepath fill + ~f ~f moveto + ~f ~f lineto + stroke" +thickness +begin-x begin-y +begin-x arrow-y +arrow-lx arrow-y +begin-x end-y +arrow-rx arrow-y +begin-x end-y +end-x end-y) + #:hspace 0 + #:translate (cons (- begin-x 1.2) (+ end-y 0.5)) + #:fontsize -2 + ;; Why does it work here?? + #:bold #:center-column (outstring)))) + +#(define-markup-command (drawHoldBendArrowOnly layout props + thickness begin-x begin-y end-x end-y arrow-lx arrow-rx arrow-y outstring) + (number? number? number? number? number? number? number? number? string?) + (interpret-markup layout props + (markup #:postscript + (ly:format "~f setlinewidth + ~f ~f moveto + ~f ~f lineto + stroke + ~f ~f moveto + ~f ~f lineto + ~f ~f lineto + closepath fill" +thickness +begin-x begin-y +begin-x arrow-y +arrow-lx arrow-y +begin-x end-y +arrow-rx arrow-y) + #:hspace 0 + #:translate (cons (- begin-x 1.2) (+ end-y 0.5)) + #:fontsize -2 + ;; Why does it work here?? + #:bold #:center-column (outstring)))) + +%% The markup-command 'draw-dashed-line' was implemented with version 2.17.x +%% TODO: use 'draw-dashed-line' instead. See also 'tie::draw-hold-bend' below. +#(define-markup-command (drawDashedLine layout props + thickness begin-x end-x line-y) + (number? number? number? number?) + ;; TODO: draws a full line instead of a dashed line + (interpret-markup layout props + (markup #:postscript + (ly:format "~f setlinewidth + ~f ~f moveto + ~f ~f lineto + stroke" +thickness begin-x line-y end-x line-y)))) + +%%% callbacks + +#(define (slur::draw-pointed-slur grob) + (let* ((control-points (ly:grob-property grob 'control-points)) + (direction (ly:grob-property grob 'direction)) + (first-point (car control-points)) + (second-point (cadr control-points)) + (third-point (caddr control-points)) + (forth-point (cadddr control-points)) + (first-x (+ (car first-point) 0.125)) ;; due to David's proposals + (first-y (cdr first-point)) + (second-x (car second-point)) + (second-y (cdr second-point)) + (third-x (car third-point)) + (third-y (cdr third-point)) + (forth-x (- (car forth-point) 0.125)) + (forth-y (cdr forth-point)) + + (middle-x (/ (+ third-x second-x) 2)) + (middle-y (/ (+ third-y second-y) 2))) + + (grob-interpret-markup grob + (make-pointedSlur-markup bend-line-thickness + first-x first-y middle-x middle-y forth-x forth-y)))) + +#(define (slur::draw-bend-arrow grob) + (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)) + (left-bound (ly:spanner-bound grob LEFT)) + (right-bound (ly:spanner-bound grob RIGHT)) + (left-tab-note-head (ly:grob-property left-bound 'cause)) + (right-tab-note-head (ly:grob-property right-bound 'cause)) + (control-points (ly:grob-property grob 'control-points)) + ;;changed: car and cadddr changed to: first and last + (left-point (first control-points)) + (right-point (last control-points)) + (left-pitch (ly:event-property (event-cause left-bound) 'pitch)) + (right-pitch (ly:event-property (event-cause right-bound) 'pitch)) + (quarterdiff (- (ly:pitch-quartertones right-pitch) + (ly:pitch-quartertones left-pitch))) + (begin-x (car left-point)) + (begin-y (+ (* (/ (ly:grob-property left-tab-note-head 'staff-position) 2) + staff-space) + y-distance-from-staffline-to-arrow)) + ;; cdr left-point doesn't work, because invisible stems are included + (end-x (car right-point)) + (end-y (+ (* (/ (- line-count 1) 2) staff-space) y-distance-from-tabstaff-to-arrow-tip)) + (arrow-lx (- end-x (/ bend-arrowhead-width 2))) + (arrow-rx (+ end-x (/ bend-arrowhead-width 2))) + (arrow-y (- end-y bend-arrowhead-height)) + (middle-x (+ begin-x (* bend-arrow-curvature-factor (- end-x begin-x)))) + (bend-amount (quarterdiff->string quarterdiff))) + + (if (< quarterdiff 0) + ;; bend down + (let* ((y-offset (cdr (ly:grob-extent left-tab-note-head left-tab-note-head Y))) + (temp begin-y)) + (set! begin-y end-y) ;; swap begin-y/end-y + (set! end-y (+ temp y-offset)) + (set! arrow-y (+ end-y bend-arrowhead-height)) + (set! bend-amount "") + (ly:grob-set-property! right-tab-note-head 'display-cautionary #t) + (ly:grob-set-property! right-tab-note-head 'stencil tab-note-head::print)) + ;; bend up + (let* ((x-offset (/ (cdr (ly:grob-extent left-tab-note-head left-tab-note-head X)) + 2))) + + (set! begin-x (+ begin-x x-offset)) + (ly:grob-set-property! right-tab-note-head 'transparent #t))) + + ;; draw resulting bend arrow + (grob-interpret-markup grob + (make-drawBendArrow-markup + bend-line-thickness + begin-x middle-x end-x begin-y end-y + arrow-lx arrow-rx arrow-y + bend-amount)))) + + +#(define (slur::draw-shifted-bend-arrow grob) + (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)) + (left-bound (ly:spanner-bound grob LEFT)) + (right-bound (ly:spanner-bound grob RIGHT)) + (left-tab-note-head (ly:grob-property left-bound 'cause)) + (right-tab-note-head (ly:grob-property right-bound 'cause)) + (control-points (ly:grob-property grob 'control-points)) + (left-point (car control-points)) + (right-point (cadddr control-points)) + (left-pitch (ly:event-property (event-cause left-bound) 'pitch)) + (right-pitch (ly:event-property (event-cause right-bound) 'pitch)) + (quarterdiff (- (ly:pitch-quartertones right-pitch) + (ly:pitch-quartertones left-pitch))) + (begin-x (car left-point)) + (begin-y (+ (* (/ (ly:grob-property left-tab-note-head 'staff-position) 2) + staff-space) + y-distance-from-tabstaff-to-arrow-tip)) + ;; cdr left-point doesn't work, because invisible stems are included + (end-x (car right-point)) + (end-y (+ (* (/ (- line-count 1) 2) staff-space) y-distance-from-tabstaff-to-arrow-tip consecutive-bends-arrow-height)) + (arrow-lx (- end-x (/ bend-arrowhead-width 2))) + (arrow-rx (+ end-x (/ bend-arrowhead-width 2))) + (arrow-y (- end-y bend-arrowhead-height)) + (middle-x (+ begin-x (* bend-arrow-curvature-factor (- end-x begin-x)))) + (bend-amount (quarterdiff->string quarterdiff))) + (if (< quarterdiff 0) + ;; bend down + (let* ((y-offset (cdr (ly:grob-extent left-tab-note-head left-tab-note-head Y))) + (temp begin-y)) + + (set! begin-y end-y) ;; swap begin-y/end-y + (set! end-y (+ temp y-offset)) + (set! arrow-y (+ end-y bend-arrowhead-height)) + (set! bend-amount "") + (ly:grob-set-property! right-tab-note-head 'stencil + (lambda (grob) (parenthesize-tab-note-head grob)))) + ;; bend up + (ly:grob-set-property! right-tab-note-head 'transparent #t)) + ;; draw resulting bend arrow + (grob-interpret-markup grob + (make-drawBendArrow-markup + bend-line-thickness + begin-x middle-x end-x begin-y end-y + arrow-lx arrow-rx arrow-y + bend-amount)))) + +#(define (slur::draw-pre-bend-hold grob) + (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)) + (left-bound (ly:spanner-bound grob LEFT)) + (right-bound (ly:spanner-bound grob RIGHT)) + (left-tab-note-head (ly:grob-property left-bound 'cause)) + (right-tab-note-head (ly:grob-property right-bound 'cause)) + (control-points (ly:grob-property grob 'control-points)) + (left-point (car control-points)) + (right-point (cadddr control-points)) + (left-pitch (ly:event-property (event-cause left-bound) 'pitch)) + (right-pitch (ly:event-property (event-cause right-bound) 'pitch)) + (quarterdiff (- (ly:pitch-quartertones right-pitch) + (ly:pitch-quartertones left-pitch))) + (begin-x (car left-point)) + (y-offset (cdr (ly:grob-extent left-tab-note-head left-tab-note-head Y))) + (begin-y (+ (* (/ (ly:grob-property left-tab-note-head 'staff-position) + 2) + staff-space) + y-offset)) + ;; cdr left-point doesn't work, because invisible stems are included + (end-x (car right-point)) + (end-y (+ (* (/ (- line-count 1) 2) staff-space) y-distance-from-tabstaff-to-arrow-tip)) + (arrow-lx (- begin-x (/ bend-arrowhead-width 2))) + (arrow-rx (+ begin-x (/ bend-arrowhead-width 2))) + (arrow-y (- end-y bend-arrowhead-height)) + (bend-amount (quarterdiff->string quarterdiff))) + + (ly:grob-set-property! right-tab-note-head 'transparent #t) + ;; draw resulting bend arrow + (grob-interpret-markup grob + (make-drawHoldBendWithArrow-markup + bend-line-thickness + begin-x begin-y + end-x end-y + arrow-lx arrow-rx arrow-y + bend-amount)))) + +#(define (slur::draw-pre-bend-only grob) + (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)) + (left-bound (ly:spanner-bound grob LEFT)) + (right-bound (ly:spanner-bound grob RIGHT)) + (left-tab-note-head (ly:grob-property left-bound 'cause)) + (right-tab-note-head (ly:grob-property right-bound 'cause)) + (control-points (ly:grob-property grob 'control-points)) + (left-point (car control-points)) + (right-point (cadddr control-points)) + (left-pitch (ly:event-property (event-cause left-bound) 'pitch)) + (right-pitch (ly:event-property (event-cause right-bound) 'pitch)) + (quarterdiff (- (ly:pitch-quartertones right-pitch) + (ly:pitch-quartertones left-pitch))) + (begin-x (car left-point)) + (y-offset (cdr (ly:grob-extent left-tab-note-head left-tab-note-head Y))) + (begin-y (+ (* (/ (ly:grob-property left-tab-note-head 'staff-position) + 2) + staff-space) + y-offset)) + ;; cdr left-point doesn't work, because invisible stems are included + (end-x (car right-point)) + (end-y (+ (* (/ (- line-count 1) 2) staff-space) y-distance-from-tabstaff-to-arrow-tip)) + (arrow-lx (- begin-x (/ bend-arrowhead-width 2))) + (arrow-rx (+ begin-x (/ bend-arrowhead-width 2))) + (arrow-y (- end-y bend-arrowhead-height)) + (bend-amount (quarterdiff->string quarterdiff))) + + (ly:grob-set-property! right-tab-note-head 'transparent #t) + ;; draw resulting bend arrow + (grob-interpret-markup grob + (make-drawHoldBendArrowOnly-markup + bend-line-thickness + begin-x begin-y + end-x end-y + arrow-lx arrow-rx arrow-y + bend-amount)))) + +#(define (tie::draw-hold-bend grob) + (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)) + (left-tab-note-head (ly:spanner-bound grob LEFT)) + (right-tab-note-head (ly:spanner-bound grob RIGHT)) + (control-points (ly:grob-property grob 'control-points)) + (left-point (car control-points)) + (right-point (cadddr control-points)) + (begin-x (car left-point)) + (end-x (car right-point)) + (line-y (+ (* (/ (- line-count 1) 2) staff-space) y-distance-from-tabstaff-to-arrow-tip))) + + (ly:grob-set-property! right-tab-note-head 'transparent #t) + (grob-interpret-markup grob + (make-drawDashedLine-markup + bend-line-thickness + begin-x end-x line-y) + ;; with 2.17.21 one could use: + ;(make-translate-markup (cons 0 line-y) + ; (make-override-markup '(on . 0.3) + ; (make-draw-dashed-line-markup + ; (cons end-x 0)))) + ))) + +%%% music functions + +bendOn = { + \override Voice.Slur #'stencil = #slur::draw-pointed-slur + \override TabVoice.Slur #'stencil = #slur::draw-bend-arrow +} + +bendOff = { + \revert Voice.Slur #'stencil + \override TabVoice.Slur #'stencil = #slur::draw-tab-slur +} + +bendGrace = +#(define-music-function (parser location note) (ly:music?) + #{ + \once \override Voice.Stem #'stencil = #point-stencil + \once \override Voice.Flag #'stencil = ##f + \once \override Voice.Stem #'direction = #DOWN + \once \override Voice.Slur #'direction = #UP + \grace #note + #}) + +preBendHold = +#(define-music-function (parser location note) (ly:music?) + #{ + \once \override TabVoice.Slur #'stencil = #slur::draw-pre-bend-only + \once \override TabStaff.ParenthesesItem #'transparent = ##t + <>\noBeam \parenthesize #note + #}) + +preBendRelease = +#(define-music-function (parser location note) (ly:music?) + #{ + \once \override TabVoice.Slur #'stencil = #slur::draw-pre-bend-hold + \once \override TabStaff.ParenthesesItem #'transparent = ##t + \once \override Voice.Slur #'direction = #DOWN + <>\noBeam \parenthesize #note + #}) + +holdBend = +#(define-music-function (parser location) () + #{ + \once \override TabVoice.Tie #'stencil = #tie::draw-hold-bend + #}) + +shiftBend = { + \once \override TabVoice.Slur #'stencil = #slur::draw-shifted-bend-arrow +}