Hello, our problem here is that such things like the positioning of beams are not known for quite some time. But we could use something like after-line-breaking to adjust the results. Somewhat like here.
Valentin Am Sonntag, 20. Februar 2022, 21:17:31 CET schrieb Luca Fascione: > So... would anybody be able to lend a hand here please? > > Many thanks > Luca > > On Sat, Feb 12, 2022 at 7:49 PM Luca Fascione <[email protected]> wrote: > > Hello, > > sorry for the double-post, I'm unsure whether this should go to -user or > > -devel. > > > > I'm looking for some guidance to set up fingering on classical guitar > > sheets. > > > > I am attaching a simple piece of music, with two engraving sets (measures > > 1-5 and 6-10), one "as-is" from lilypond, the other using some trickery > > involving one-note chords, purely to show a sample of what the result I'm > > after (and it's an approximation), vs what I get at the moment. > > > > Measures 1-5 in the source look like what I am intending to type, but it > > has a number of engraving defects I don't understand (you can see the > > beams > > don't avoid the fingerings, nor they are located correctly wrt the > > accidentals, the second beat of measure 5 illustrates this well. I'm not > > super in love with measure 10 either, but if I understand the docs > > correctly, the issue there is that the 'offset' correction is applied > > post-layout, and so naturally it won't back-affect the placement of the > > beams. > > > > I have made several other experiments, I'm just not wanting to waste > > people's time. But setting Fingering.side-axis = #X seems somewhat > > promising, but it seems unable to find any usable Y data about the > > parents, > > and smashes all numbers on the B line, as well as not dealing with > > accidentals. > > > > I have an engraving project in front of me, for which I'm more than happy > > to put in the time to contribute the code to a proper solution myself, and > > I really don't want to make poor use of time from folks busy with other > > work, but I feel I'll need some level of guidance as to what to do. For > > context I can do C++ and I can manage guile ok (I'm a software engineer > > for > > work, I'm mostly working in the field of computer graphics). > > > > I was looking into this problem several years ago also, and Han-Wen > > Nienhuys at the time suggested I should use a positioning callback > > attached > > to the Fingering grobs, but I couldn't find a way to do such a thing (in > > particular I can't find what property to use for this). So far I've traced > > the Fingering system to be an instance of the Articulations/Scripts > > system, > > but that's as far as I got. > > > > It seems to me what's needed would be to decide where the heads go, then > > the accidentals, at this stage deal with the fingering and only then there > > would be enough bboxes to reason about the beaming (this is the skyline > > concept I think). In reasoning about how Articulations are engraved, it's > > possible the order of events for fingering would be different from the > > order of events in other articulations (which I think are laid out after > > beams are in place, if I am not mistaken), warranting a bigger change, but > > I have no idea where that is located/managed. > > > > Many thanks for your time, > > Luca
\version "2.22.1"
% file to test various requirements to engrave fingering for guitar
% the main goal is to obtain fingering places approx NorthEast of the note heads, right at
% the head.
% In all other respects this is a minimal working example
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Functions and global definitions
% string numbers orientation UP
stringUp = \set stringNumberOrientations = #'(up)
% string numbers orientation DOWN
stringDown = \set stringNumberOrientations = #'(down)
Barre = #(define-music-function (barre location str music) (string? ly:music?)
(let ((elts (extract-named-music music '(NoteEvent EventChord RestEvent SkipEvent))))
(if (pair? elts)
(let ((first-element (first elts))
(last-element (last elts)))
(set! (ly:music-property first-element 'articulations)
(cons (make-music 'TextSpanEvent 'span-direction -1)
(ly:music-property first-element 'articulations)))
(set! (ly:music-property last-element 'articulations)
(cons (make-music 'TextSpanEvent 'span-direction 1)
(ly:music-property last-element 'articulations))))))
#{
\once \override TextSpanner.font-size = #1
\once \override TextSpanner.staff-padding = #3
\once \override TextSpanner.style = #'line
\once \override TextSpanner.to-barline = ##f
\once \override TextSpanner.direction = #UP
\once \override TextSpanner.bound-details =
#`((left
(text . ,#{ \markup { #str } #})
(Y . 0)
(padding . -0.5)
(stencil-align-dir-y . .0)
(attach-dir . -1))
(right
(text . ,#{ \markup { \draw-line #'( .25 . -.5) } #})
(Y . 0)
(padding . 0.5)
(attach-dir . 1)))
\once \override TextSpanner.bound-details.left-broken.attach-dir = #-1
\once \override TextSpanner.bound-details.left-broken.text = ##f
\once \override TextSpanner.bound-details.right-broken.text = ##f
$music
#})
Barref = #(define-music-function (barre location num den str music) (string? string? string? ly:music?)
(let ((elts (extract-named-music music '(NoteEvent EventChord RestEvent SkipEvent))))
(if (pair? elts)
(let ((first-element (first elts))
(last-element (last elts)))
(set! (ly:music-property first-element 'articulations)
(cons (make-music 'TextSpanEvent 'span-direction -1)
(ly:music-property first-element 'articulations)))
(set! (ly:music-property last-element 'articulations)
(cons (make-music 'TextSpanEvent 'span-direction 1)
(ly:music-property last-element 'articulations))))))
#{
\once \override TextSpanner.font-size = #1
\once \override TextSpanner.staff-padding = #3
\once \override TextSpanner.style = #'line
\once \override TextSpanner.to-barline = ##f
\once \override TextSpanner.direction = #UP
\once \override TextSpanner.bound-details =
#`((left
(text . ,#{ \markup { \tiny \fraction #num #den #str } #})
(Y . 0)
(padding . -0.5)
(stencil-align-dir-y . .0)
(attach-dir . -1))
(right
(text . ,#{ \markup { \draw-line #'( .25 . -.5) } #})
(Y . 0)
(padding . 0.5)
(attach-dir . 1)))
\once \override TextSpanner.bound-details.left-broken.attach-dir = #-1
\once \override TextSpanner.bound-details.left-broken.text = ##f
\once \override TextSpanner.bound-details.right-broken.text = ##f
$music
#})
stringNumberSpanner =
#(define-music-function (StringNumber) (string?)
#{
\override TextSpanner.style = #'solid
\override TextSpanner.font-name = #'"Minion Pro Bold"
\override TextSpanner.font-size = #-2
\override TextSpanner.bound-details.left.stencil-align-dir-y = #CENTER
\override TextSpanner.bound-details.left.text =
\markup { \circle \number $StringNumber }
#})
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Configuration for the fingering
#(define (Fingering_stuff_engraver context)
(let ((head #f) (stem #f) (fingering #f))
(make-engraver
(acknowledgers
((finger-interface engraver grob source-engraver)
(set! fingering grob))
((note-head-interface engraver grob source-engraver)
(set! head grob))
((stem-interface engraver grob source-engraver)
(set! stem grob)))
((process-music engraver)
(if (and fingering stem head)
(ly:grob-set-property! fingering 'details
`((head . ,head) (stem . ,stem) . ,(ly:grob-property fingering 'details))))
(set! head #f)
(set! stem #f)
(set! fingering #f)))))
\layout {
\context {
\Voice
\consists #Fingering_stuff_engraver
% setup fingering on the left of the noteheads
%\override Voice.fingeringOrientations = #'(left)
% now move it up one stave-space and right a little
\override Fingering.extra-offset = #'(0 . 0)
\override Fingering.X-offset = #0.5
\override Fingering.Y-offset = 0
\override Fingering.after-line-breaking =
#(lambda (grob)
(let* ((det (ly:grob-property grob 'details))
(stem (assoc-get 'stem det))
(stem-height (interval-length (ly:grob-property stem 'Y-extent)))
(bm (if stem (ly:grob-property stem 'beaming) '()))
(bm-left (if (null? bm) #f (car bm)))
(total-beams (if bm-left (1+ (apply max bm-left)) 0))
(CONST_BEAM_SPACE 1)
(effective-stem-length (- stem-height (* total-beams CONST_BEAM_SPACE)))
(prev-offset (ly:grob-property grob 'Y-offset))
(grob-height (interval-length (ly:grob-property grob 'Y-extent)))
(head (assoc-get 'head det))
(head-offset (if head (ly:grob-property head 'Y-offset)))
(offset-diff (- prev-offset head-offset))
(nescessary-height (+ offset-diff grob-height 0.7))
(shift (- effective-stem-length nescessary-height))
(offset-diff-after-shift (- (+ prev-offset shift) head-offset))
(x-shift (if (< offset-diff-after-shift 0.1) -0.7
(if (< offset-diff-after-shift 0.3) -0.5 0))))
(if (and stem head)
(if (and bm-left (< effective-stem-length nescessary-height))
(ly:grob-set-property! grob 'extra-offset (cons x-shift (- effective-stem-length nescessary-height)))
))))
% align to side of parent grob (-1 left, 0 center, 1 right)
% if another number, it's in half-parent's width units
\override Fingering.parent-alignment-X = #-1
% align to side of parent grob (1 top, 0 center, -1 bottom)
% if another number, it's in half-parent's height units
%\override Fingering.parent-alignment-Y = #1
% align referenced to this side of stencil (-1 left, 0 center, 1 right)
% if another number, it's in half-object's width units
\override Fingering.self-alignment-X = #1
% align referenced to this side of stencil (1 top, 0 center, -1 bottom)
% if another number, it's in half-object's height units
%\override Fingering.self-alignment-Y = #-1
% align to the side of the parent, not above
%\override Fingering.side-axis = #X
%\override Fingering.use-skylines = ##t
% fingering should sit inside the staff
\override Fingering.staff-padding = #'()
% fingering should sit right at the note head, no worries about the beaming
\override Fingering.add-stem-support = ##f
\override Fingering.direction = #LEFT
% setup the size for the right-hand fingering notation
\override StrokeFinger.font-size = -2
% setup the shape for the right-hand fingering notation
\override StrokeFinger.font-shape = #'upright
% keep right-hand fingering inside slurs
\override StrokeFinger.avoid-slur = #'inside
% string numbers below the notehead
%\override Voice.stringNumberOrientations = #'(down)
% plucking fingering notation above the notehead
%\override Voice.strokeFingerOrientations = #'(up)
%\once \override StringNumber.self-alignment-X = #RIGHT
%\once \override Fingering.self-alignment-X = #RIGHT
%\override StringNumber.self-alignment-X = #RIGHT
}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Minimal document setup
\paper {
#(set-paper-size "a4")
}
\header{
title = "Fingering tests"
subtitle = "A little sampler to setup guitar fingering"
composer = "Luca Fascione"
lastupdated = "2022/Feb/12"
tagline = ##f
}
% various pieces of sample music
\parallelMusic guitarHi,guitarMid,guitarLo {
\mergeDifferentlyHeadedOn
\bar "[|:"
\slurDown \stringUp cis'4-1 gis,16 b e'-0 b |
s2 |
\Barref "4" "6" "CII" { a,16-0 a-1 e-1 a-1 } gis,4-3 |
a4-1 e,16 cis'-1 d'-2 e'-0 |
s2 |
\Barre "CII" { fis,16-1 fis-4 cis-3 fis } e,4-0 |
\Barref "1" "2" "CII" { fis'16-1 cis'-1( d'-2) fis' } e'-0 gis-1 b-0 d'-4 |
s2 |
d4-0 e,-0 |
\break
cis'2-1 |
s2|
\Barref "4" "6" "CII" {a,16-0 a-1 e-1 a a,-0( cis-3) e-1 a-1 } |
%5
cis'4-2 \Barre "CIV" {cis16 eis'32-3( fis'-4) gis'16-1 a'-2} |
s2 |
eis16-3 gis-1 d-0 gis cis4-1 |
}
\parallelMusic guitarHiB,guitarMidB,guitarLoB {
\mergeDifferentlyHeadedOn
\bar "[|:"
\slurDown \stringUp <cis'-1>4 <gis,>16 b <e'-0> b |
s2 |
\Barref "4" "6" "CII" { <a,-0>16 <a-1> <e-1> <a-1> } <gis,-3>4 |
<a-1>4 e,16 <cis'-1> <d'-2> <e'-0> |
s2 |
\Barre "CII" { <fis,-1>16 <fis-4> <cis-3> fis } <e,-0>4 |
\Barref "1" "2" "CII" { <fis'-1>16 <cis'-1(> <d'-2)> fis' } <e'-0> <gis-1> <b-0> <d'-4> |
s2 |
<d-0>4 <e,-0> |
\break
<cis'-1>2 |
s2|
\Barref "4" "6" "CII" {<a,-0>16 <a-1> <e-1> a <a,-0(> <cis-3)> <e-1> <a-1> } |
%5
cis'4-2 \Barre "CIV" {cis16 <eis'-3(>32 <fis'-4)> <gis'-1>16 <a'-2>} |
s2 |
<eis-3>16 <gis-1> <d-0> gis <cis-1>4 |
}
guitar = {
\accidentalStyle modern-cautionary
{
\key a \major
\time 2/4
\clef "violin_8"
<<
\voiceOne \guitarHi \\
\voiceFour \guitarMid \\
\voiceTwo \guitarLo
>>
}
}
fingeringSetup = {
% setup fingering on the left of the noteheads
\set fingeringOrientations = #'(left)
% now move it up and right a little
\override Fingering.extra-offset = #'(0.125 . 0.5)
}
guitarB = {
\accidentalStyle modern-cautionary
{
\key a \major
\time 2/4
\clef "violin_8"
<<
\new Voice = "hi" { \fingeringSetup \voiceOne \guitarHiB }
\new Voice = "mid" { \fingeringSetup \voiceFour \guitarMidB }
\new Voice = "lo" { \fingeringSetup \voiceTwo \guitarLoB }
>>
}
}
\score {
\new Staff = "guitar" { \guitar \break \guitarB }
\layout { }
}
signature.asc
Description: This is a digitally signed message part.
