----- 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

Reply via email to