Am Di., 13. Aug. 2024 um 18:04 Uhr schrieb Lucas Cavalcanti < lucaspi...@gmail.com>:
> Hello! I'm having a bit of trouble trying to replicate this behaviour with > string bending and ties: > [image: GuitarProStringBends] > A bit of context: I'm a long time GuitarPro user and now I am fully > migrating to lilypond. For the last 4 to 5 years I was only writing > standard sheet music and lead sheets; now I'm rewriting all my > tablature-based songs created in GP to Lilypond. > However, I still cannot find a way to replicate the behaviour mentioned > above. All that I can do is this: > [image: image.png] > I'm accustomed to seeing the stem displayed by the staff. In the way that > lilypond is outputting I cannot visualize correctly the beat structure of > the measure. > Any help on this would be greatly appreciated! > I'll be annexing the .ly file and pasting the code. > > Best regards, > Lucas > > \version "2.24.4" > gtbend = {\new TabStaff { \tabFullNotation \relative c''{ > g2..\3\^ \grace a8\3 a8\3~\^ a2\3 %\grace a8\3 > a8\2 f\3\^ fis4\3 d1\3 > \break > g2..\3\^ \grace a8\3 a8\3~\^ a2\3 %\grace a8\3 > a8\2 f\3\^ fis4\3 \bendHold \^ d1\3 > }}} > \score { \gtbend } > Hi, attached you'll find my attempt to create a style-sheet. Please holler for all I misunderstood or forgot or for bugs. Cheers, Harm
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% %%%% %%%% %%%% %%%% Style-sheet GuitarPro %%%% %%%% %%%% %%%% %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% %%%% TabNoteHead %%%% #(define tab-note-head::taller-circled-stencil (grob-transformer 'stencil ;; Make stencil a little taller. ;; Print it circled for notes longer than a quarter, but not if ;; 'display-cautionary is true. In this case a different stem-length ;; should be used. (lambda (grob orig) (let ((dur-log (ly:grob-property grob 'duration-log)) (cautionary? (ly:grob-property grob 'display-cautionary #f)) (taller-stencil (ly:make-stencil (ly:stencil-expr orig) (ly:stencil-extent orig X) (interval-widen (ly:stencil-extent orig Y) 0.2)))) (if (and (> 2 dur-log) (not cautionary?)) (circle-stencil taller-stencil 0.1 0.1) taller-stencil))))) %%%% %%%% Stem %%%% #(define stem::tab-length (lambda (grob) ;; Read 'stem-begin-position, ensure unbeamed stems all end at the same ;; height. (let* ((dir (ly:grob-property grob 'direction 1)) (staff-symbol (ly:grob-object grob 'staff-symbol)) (staff-lines (ly:grob-property staff-symbol 'line-positions)) (top-or-bottom-line (apply (if (positive? dir) max min) staff-lines)) (stem-begin (ly:grob-property grob 'stem-begin-position)) (details (ly:grob-property grob 'details)) (out-side-staff-length (assoc-get 'out-side-staff-length details 10))) (+ (* dir top-or-bottom-line) out-side-staff-length (* dir -1 stem-begin))))) #(define stem::tab-stem-begin-position ;; If 'display-cautionary is true let stems begin outside of tab-staff, ;; contolled by 'details.gap-to-staff. ;; For half notes the stem is shortened increasing the gap to ;; the staff-symbol, controlled by 'details-shorten-for-half-note. (lambda (grob) (let* ((nhds-array (ly:grob-object grob 'note-heads #f)) (nhds (if nhds-array (ly:grob-array->list nhds-array) #f)) (staff-pos (if nhds (map (lambda (tnhds) (ly:grob-property tnhds 'staff-position)) nhds) '())) (dir (ly:grob-property grob 'direction 1)) (staff-symbol (ly:grob-object grob 'staff-symbol)) (staff-lines (ly:grob-property staff-symbol 'line-positions)) (staff-space (ly:staff-symbol-staff-space grob)) (top-or-bottom-nhd-pos (apply (if (positive? dir) max min) staff-pos)) (top-or-bottom-line (apply (if (positive? dir) max min) staff-lines)) (dur-log (ly:grob-property grob 'duration-log)) (details (ly:grob-property grob 'details)) (gap-to-staff (assoc-get 'gap-to-staff details)) (shorten-for-half-note (assoc-get 'shorten-for-half-note details))) (+ top-or-bottom-line (* staff-space dir (if (eqv? 1 dur-log) (+ gap-to-staff shorten-for-half-note) gap-to-staff)))))) #(define stem::change-given-tab-stem-begin-position (grob-transformer 'stem-begin-position ;; If 'display-cautionary is true let stems begin outside of tab-staff, ;; contolled by 'details.gap-to-staff. ;; For half notes the stem is shortened increasing the gap to ;; the staff-symbol, controlled by 'details-shorten-for-half-note. (lambda (grob orig) (let* ((nhds-array (ly:grob-object grob 'note-heads #f)) (nhds (if nhds-array (ly:grob-array->list nhds-array) '()))) (if (every-cautionary? nhds) (stem::tab-stem-begin-position grob) orig))))) %%%% %%%% Beam %%%% #(define tab-beam::positions (lambda (grob) ;; Looking at Stem.details.out-side-staff-length, ensure same length of ;; stems as for unbeamed stems. (let* ((stems-array (ly:grob-object grob 'stems #f)) (stems (if stems-array (ly:grob-array->list stems-array) #f)) (stem-details (if stems (ly:grob-property (car stems) 'details) '())) (beam-thick (ly:grob-property grob 'beam-thickness)) (staff-space (ly:staff-symbol-staff-space grob)) (out-side-staff-length (assoc-get 'out-side-staff-length stem-details)) (dir (ly:grob-property grob 'direction)) (pos ;; TODO why do we need to reduce `out-side-staff-length` by 1? (* dir (1- out-side-staff-length)))) (cons pos pos)))) #(define tab-beam::stencil (lambda (grob) ;; While affecting beamed Stem's 'stem-begin-position and 'length we need ;; to recreate the stencil (let* ((stems-array (ly:grob-object grob 'stems #f)) (stems (if stems-array (ly:grob-array->list stems-array) '()))) (for-each (lambda (stem) (let* ((nhds-array (ly:grob-object stem 'note-heads #f)) (nhds (if nhds-array (ly:grob-array->list nhds-array) #f))) (when (and nhds (every-cautionary? nhds)) (ly:grob-set-property! stem 'stem-begin-position (stem::tab-stem-begin-position (car stems)))))) stems) (for-each (lambda (stem) (let* ((nhds-array (ly:grob-object stem 'note-heads #f)) (nhds (if nhds-array (ly:grob-array->list nhds-array) #f))) (when (and nhds (every-cautionary? nhds)) (ly:grob-set-property! stem 'length (stem::tab-length stem))))) stems) (ly:beam::print grob)))) %%%% %%%% DurationLine %%%% %% bow-stencil for faking Tie #(define duration-line::bow-stencil (lambda (grob) (let* ((vals (duration-line::calc grob)) (left-start (assoc-get 'x-start vals)) (right-end (assoc-get 'x-end vals)) (thick (assoc-get 'thick vals)) (dir (ly:grob-property grob 'direction -1))) (make-tie-stencil (cons left-start 0) ;; start (cons right-end 0) ;; end thick ;thick dir ;orientation 0.6 ; height-limit )))) %%%% %%%% BendSpanner %%%% #(define bend::target-visibility ;; Set details.target-visibility #t, but keep the target TabNoteHead ;;transparent, i.e. Stem, Flag and Dots become visible, but not the TabNoteHead ;; itself. (grob-transformer 'details (lambda (grob orig) (let ((right-bound (ly:spanner-bound grob RIGHT))) (if (ly:grob? right-bound) (begin (for-each (lambda (tnhd) (ly:grob-set-property! tnhd 'transparent #t)) (cdr (get-bound-note-heads grob))) (acons 'target-visibility #t orig)) orig))))) %% Short-cut printTarget = -\tweak details #bend::target-visibility \etc %%%% %%%% Dots %%%% #(define tab-dots::staff-position (lambda (grob) (let* ((tnhd (ly:grob-parent grob Y)) (stem (ly:grob-object tnhd 'stem)) (details (ly:grob-property stem 'details)) (out-side-staff-length (assoc-get 'out-side-staff-length details)) (dir (ly:grob-property stem 'direction 1)) (staff-pos (ly:grob-property tnhd 'staff-position)) (staff-space (ly:staff-symbol-staff-space grob)) (staff-symbol (ly:grob-object grob 'staff-symbol)) (staff-lines (ly:grob-property staff-symbol 'line-positions)) (top-or-bottom-line (apply (if (positive? dir) max min) staff-lines))) (if (negative? dir) (+ (* dir staff-pos) top-or-bottom-line (* dir out-side-staff-length)) ;; TODO ;; No clue how it should look for \stemUp 0)))) %%%% %%%% Helper %%%% #(define (every-cautionary? tab-note-heads) (every (lambda (x) (ly:grob-property x 'display-cautionary #f)) tab-note-heads)) %%%% %%%% layout %%%% guitarProStyleLayout = \layout { \context { \TabStaff \tabFullNotation \numericTimeSignature %% Stem \override Stem.layer = #-100 \override Stem.details.out-side-staff-length = 7 \override Stem.details.gap-to-staff = 1.5 \override Stem.details.shorten-for-half-note = 1.0 \override Stem.stencil = #ly:stem::print \revert Stem.X-extent \override Stem.stem-begin-position = #stem::change-given-tab-stem-begin-position \override Stem.length = #stem::tab-length %% TabNoteHead \override TabNoteHead.stem-attachment = #'(0 . 0) \override TabNoteHead.stencil = #tab-note-head::taller-circled-stencil %% Beam \override Beam.positions = #tab-beam::positions \override Beam.stencil = #tab-beam::stencil %% Dots \override Dots.staff-position = #tab-dots::staff-position \override DotColumn.padding = #-0.5 } \context { \TabVoice \consists Duration_line_engraver \override DurationLine.stencil = #duration-line::bow-stencil \override DurationLine.bound-details.left.padding = 0.1 \override DurationLine.bound-details.right.padding = 0.1 \override DurationLine.thickness = 1.2 } }
\version "2.25.19" \include "guitar-pro-style.ly" styleExample = { \clef "moderntab" g'2..\3 a'8\3~ \once \override TabNoteHead.display-cautionary = ##t a'2\3 << { \oneVoice a'8\2 f'8\3 \printTarget \^ s4*7/8\3 \tweak transparent ##t fis'1*1/32 } \\ { s8 \once \hideNotes f'8\3 \- \once \override TabNoteHead.display-cautionary = ##t \once \override TabNoteHead.transparent = ##t f'4 } >> d'1\3 \break g'2..\3 a'8\3~ \once \override TabNoteHead.display-cautionary = ##t a'2\3 << { \oneVoice a'8\2 f'\3 \printTarget \^ fis'4*7/8\3\bendHold \^ \tweak transparent ##t fis'1*1/32 } \\ { s8 \once \hideNotes f'8\3 \- \once \override TabNoteHead.display-cautionary = ##t \once \override TabNoteHead.transparent = ##t f'4 } >> d'1\3 } \paper { system-system-spacing.minimum-distance = 20 } \score { \new TabStaff \styleExample \layout { \guitarProStyleLayout indent = 0 } }