----- Original Message ----- From: "Thomas Morley" <thomasmorle...@gmail.com> To: "Trevor Daniels" <t.dani...@treda.co.uk> Cc: "Lily-Devel List" <lilypond-devel@gnu.org> Sent: Sunday, September 04, 2016 7:28 AM Subject: Re: Help with Scheme engraver please
> 2016-09-03 19:29 GMT+02:00 Thomas Morley <thomasmorle...@gmail.com>: > >> I've put some work on it. See attached duration-as-markup-5b-harm.ly >> The general work should be clear from comments and descriptions. >> There's some ugly code in it, although it works so far, wide room for >> improvements still there. >> Nevertheless it works now even in polyphonic. > > Please replace the coding in `stop-translation-timestep' with: > [snip] > > This will cure a bug with last notes starting at some moment, but with > different durations. Thanks Harm, for this and the preceding mail. I've found them very helpful. In particular, a simpler way to set stringTuning and how to set persistent variables within engravers. But I don't understand why you used a rather complicated procedure to obtain durations. Could you not simply extract the durations from note events? Actually I'd got quite a bit further than the simple example I posted, and my current state is attached, extracting durations and pitches from note-events, and detecting the start of bars by acknowledging barline grobs. This version draws duration grobs whenever the duration changes, and at the start of every bar, bass course grobs below the tab, adds fingering and laissez vibrer slurs (I think that's what they are used for.) There's quite a lot still wrong with this example, although it works in simple cases. You can see these problems listed in the TODOs. And the code needs some tidying up too as bits of it are rather messy (to say the least!). And it would probably be better to separate the generation of the two types of grobs into two engravers. You'll see I use the Fronimo glyphs for the bass course indications, and mensural flags for the durations. These are just for demonstration: we'd need a set of lute tab glyphs of our own to be defined at some stage. But this is now pretty close to Phase I which I defined in the note dated 22 Nov 2009, in this thread: http://lilypond-s-support-for-tablatures.3383434.n2.nabble.com/Baroque-lute-tablature-td4008032.html I probably will be somewhat unresponsive for 10 days or so, as we are away on a belated summer break next week. Trevor
\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. <a-\RF #1 >8 <e-1-\RF #5 > a | <f d-\RF #5 >4. <f-\RF #1 >8 < g-2 e-1 >4 | <a f f\5-\RF #5 >4_( <a f-\RF #1 > d8) <g,-1-\RF #5 > | <cis-4 a-3\4-\RF #5 >4 <a,\6>8 <g'-1-\RF #1 > <f> <e-1-\RF #1 > <d' a d,,>4 <e-2-\RF #2 >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) <f-\RF #1 >16 \glissando <e-2-\RF #1 > <f-\RF #2 >8 <d,-\RF #5 > } \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 <a d' f' a' d'' f''> % 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 %}
_______________________________________________ lilypond-devel mailing list lilypond-devel@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-devel