\version "2.19.46" % Example of using Scheme engravers to add markup based on % note duration and pitch % Avoids repeated durations on both chords and consecutive notes % Always prints duration at start of bar % Adds dots % Adds string indication in bar 3 % Adds stroke finger indications % Makes dots height not vary with duration % Adds glyphs for minims and semibreves % Fixes error message with avoid-slur % Adds string finger indications % Adds glissando to show repeated finger % (not good - each has to be positioned) % Removes debugging printouts in Lute_tab_duration_engraver % Uses note names in stringTuning (thanks Harm) % Places persistent variables inside engraver (thanks Harm) % Adds bass courses %{ TODO Error when finger is specified with slur Warning when bass course pitch is specified Handle notes with different durations at one musical moment better Need better way of linking notes with repeated right finger could this be detected and added automatically? Bass course pitches should not be hard-coded %} #(define (t->m t) "Return the current moment of translator object @var{t}." (ly:context-current-moment (ly:translator-context t))) #(define (duration-markup duration) "Returns flags corresponding to duration as markup, avoiding repeated symbol if duration has not changed." (define flag-glyph "") (define dots-glyph "") (let ((duration-log (ly:duration-log duration)) (duration-dots (ly:duration-dot-count duration))) ; obtain flag glyph (case duration-log ; TODO: replace with more suitable glyphs ((0) (set! flag-glyph (markup #:note "1" UP))) ((1) (set! flag-glyph (markup #:note "2" UP))) ((2) (set! flag-glyph (markup #:musicglyph "rests.M2mensural"))) ((3) (set! flag-glyph (markup #:musicglyph "flags.mensuralu03"))) ((4) (set! flag-glyph (markup #:musicglyph "flags.mensuralu04"))) ((5) (set! flag-glyph (markup #:musicglyph "flags.mensuralu05"))) ((6) (set! flag-glyph (markup #:musicglyph "flags.mensuralu06"))) (else (begin (ly:warning "Duration glyph not available for duration-log of ~a" duration-log) (set! flag-glyph " ")))) ; obtain dots glyph (while (> duration-dots 0) (set! dots-glyph (markup #:musicglyph "dots.dot" dots-glyph)) (set! duration-dots (1- duration-dots))) ; combine flag and dots, lowering dots more on high flags (markup flag-glyph #:lower (- duration-log 1.5) dots-glyph))) Lute_tab_engraver = #(begin ; Define persistent variables (define start-of-bar #f) ; set when barline seen (define duration-grob-made #f) ; set when duration grob made (define course-grob-made #f) ; set when bass course grob made (define previous-duration-log 999) ; to suppress repeated durations (define note-ev #f) ; note event (define en #f) ; engraver (make-engraver ((start-translation-timestep translator) (set! start-of-bar #f) (set! duration-grob-made #f) (set! course-grob-made #f) (set! note-ev #f) (set! en #f)) (listeners ((note-event engraver event) ; Save just the last event at each timestep (if (and note-ev (not (eqv? (ly:duration-log (ly:event-property event 'duration)) (ly:duration-log (ly:event-property note-ev 'duration))))) (ly:warning "Polyphony is not supported in lute tab")) (set! note-ev event) (set! en engraver))) (acknowledgers ((bar-line-interface engraver grob source-engraver) (set! start-of-bar #t))) ((process-acknowledged translator) (if note-ev (begin (let ((duration-log (ly:duration-log (ly:event-property note-ev 'duration)))) (if (and (not duration-grob-made) (or start-of-bar (not (eqv? duration-log previous-duration-log)))) (let ((duration-grob (ly:engraver-make-grob en 'TextScript note-ev))) (ly:grob-set-property! duration-grob 'direction UP) (ly:grob-set-property! duration-grob 'text (duration-markup (ly:event-property note-ev 'duration))) (set! start-of-bar #f) (set! duration-grob-made #t) (set! previous-duration-log duration-log)))) (let ((mark (course-markup (ly:event-property note-ev 'pitch)))) (if (and mark (not course-grob-made)) (let ((course-grob (ly:engraver-make-grob en 'TextScript note-ev))) (ly:grob-set-property! course-grob 'direction DOWN) (ly:grob-set-property! course-grob 'text mark) (set! course-grob-made #t))))))) ((stop-translation-timestep translator) (set! duration-grob-made #f)))) #(define (course-markup pitch) "Make markup for bass courses." ;; TODO Pitches should not be hard-coded (case (ly:pitch-semitones pitch) ((-5) (markup #:override '(font-name . "Fronimo Gavotta") "a")) ; G - a ((-7) (markup #:override '(font-name . "Fronimo Gavotta") "A")) ; F - /a ((-8) (markup #:override '(font-name . "Fronimo Gavotta") "B")) ; E - //a ((-10) (markup #:override '(font-name . "Fronimo Gavotta") "C")) ; D - ///a ((-12) (markup #:override '(font-name . "Fronimo Gavotta") "4")) ; C - 4 ((-13) (markup #:override '(font-name . "Fronimo Gavotta") "5")) ; B - 5 ((-15) (markup #:override '(font-name . "Fronimo Gavotta") "6")) ; A - 6 (else #f))) RF = \rightHandFinger \etc notes = { \relative c'' { \time 3/4 \partial 4. 8 a | 4. 8 < g-2 e-1 >4 | 4_( d8) | 4 8 4 8 \once \override Glissando.bound-details.left.Y = 2.3 \once \override Glissando.bound-details.right.Y = 1.3 \once \override Glissando.extra-offset = #'(-0.5 . 0) 16 \glissando 8 } \relative c' { \break \time 4/4 c1 | cis2 d4 ees8 e16 f32 fis64 g64 | gis16 a16 bes8.. c32 cis8 d ees e f | fis g gis a bes b c cis | } } \score { << \new Staff { \new Voice { \override StrokeFinger #'digit-names = ##("1" "2" "3" "4" "0") \notes } } \new TabStaff \with { % Use letters to indicate frets tablatureFormat = #fret-letter-tablature-format % Usual string tuning for 6-course Baroque lute stringTunings = \stringTuning % Choose a suitable font for fret letters \override TabNoteHead.font-name = #"Fronimo Gavotta" % \override Flag.style = #'straight \revert TextScript.stencil % need to display TextScript } { \new TabVoice \with { \consists \Lute_tab_engraver \consists "Bar_engraver" % need to acknowledge barline % Need both right and left hand fingering \consists "Fingering_engraver" \consists "New_fingering_engraver" % \consists \Lute_tab_course_engraver % Baroque tab uses slurs \revert Slur #'stencil % Set and reposition symbols for right hand finger indications \override StrokeFinger.digit-names = ##("." ".." "..." "...." "|") \override StrokeFinger.side-axis = 0 \override StrokeFinger.avoid-slur = #'inside \override StrokeFinger.extra-offset = #'(0 . -0.7) % Don't want string numbers above tab staff \omit StringNumber \override StringNumber.side-axis = 0 % Avoid error messages fingeringOrientations = #'(left) \override Fingering.font-encoding = ##f \override Fingering.font-name = #"roman" \override Fingering.font-size = #-7 \override Fingering.font-shape = #'italic % has no effect \override Fingering.side-axis = #0 % Avoid error messages \override Fingering.extra-offset = #'(-0.7 . 0) } { \textLengthOn \notes } } >> } %{ convert-ly.py (GNU LilyPond) 2.19.43 convert-ly.py: Processing `'... Applying conversion: 2.13.10, 2.13.16, 2.13.18, 2.13.20, 2.13.27, 2.13.29, 2.13.31, 2.13.36, 2.13.39, 2.13.40, 2.13.42, 2.13.44, 2.13.46, 2.13.48, 2.13.51, 2.14.0, 2.15.7, 2.15.9, 2.15.10, 2.15.16, 2.15.17, 2.15.18, 2.15.19, 2.15.20, 2.15.25, 2.15.32, 2.15.39, 2.15.40, 2.15.42, 2.15.43, 2.16.0, 2.17.0, 2.17.4, 2.17.5, 2.17.6, 2.17.11, 2.17.14, 2.17.15, 2.17.18, 2.17.19, 2.17.20, 2.17.25, 2.17.27, 2.17.29, 2.17.97, 2.18.0, 2.19.2, 2.19.7, 2.19.11, 2.19.16, 2.19.22, 2.19.24, 2.19.28, 2.19.29, 2.19.32, 2.19.40 %}