Re: Whole-note tremolo beams
Am So., 22. März 2020 um 17:38 Uhr schrieb Leo Correia de Verdier : > > Second attempt: [...] Hi, please find attached my own take on it. The tremolo-beam now avoids left-note-column's dots and right-note-column accidentals automagically and is centered around the thought line between the vertical center of the note-heads staff-positions of left and right note-column. Furthermore, I introduced some subproperties of Beam.details: (1) Beam.details.tremolo-positions, expecting a pair, defaulting to '(0 . 0) for fine-tuning NB Introducing details.tremolo-positions is part of the workaround. A user set 'positions would disturb the stencil-examination. If you use Beam.positions, you will need to figure out all the needed values. Then the function assumes you want to Y-position the Beam yourself and restricts it's behaviour to left/right gaps. (2) Beam.details.whole-note-tremolo-gaps, expecting a pair, defaulting to '(0.5 . 0.5) for fine-tuning the gaps Note: because of https://sourceforge.net/p/testlilyissues/issues/5868/ an additional function 'correct-whole-note-tremolo-gap' is added. In general, the function examines the default-stencil and returns a modified one. The first ~90 lines are debugging helpers. They may be activated setting the boolean in line 369 to #f Ofcourse it would be better the default would do the right thing right from the begining... Thus, it's a workaround, nothing more, but demonstrating how tremolo for whole notes should come out per default imho. Cheers, Harm \version "2.20.0" %% debugging helpers #(define* (make-cross-stencil coords #:optional (thick 0.2) (sz 0.3)) (ly:stencil-add (make-line-stencil thick (- (car coords) sz) (- (cdr coords) sz) (+ (car coords) sz) (+ (cdr coords) sz)) (make-line-stencil thick (- (car coords) sz) (+ (cdr coords) sz) (+ (car coords) sz) (- (cdr coords) sz #(define (beam-stencil stil) "Add some visual debugging-aid to the given @var{stil}, which is supposed to be a beam-stencil." (lambda (grob) (let* ((sys (ly:grob-system grob)) (left-stem (ly:spanner-bound grob LEFT)) (right-stem (ly:spanner-bound grob RIGHT)) (left-stem-x (ly:grob-relative-coordinate left-stem sys X)) (right-stem-x (ly:grob-relative-coordinate right-stem sys X)) ;; left/right NoteColumn (left-nc (ly:grob-parent left-stem X)) (right-nc (ly:grob-parent right-stem X)) ;; left NoteHeads average staff-positions (left-y-average (get-average-staff-positions-of-note-heads left-nc)) ;; right NoteHeads average staff-positions (right-y-average (get-average-staff-positions-of-note-heads right-nc)) ;(stil (ly:beam::print grob)) (details (ly:grob-property grob 'details)) (tremolo-positions (assoc-get 'tremolo-positions details '(0 . 0))) (beam-dir (if (> (ly:grob-property grob 'direction) 0) "UP" "DOWN")) (stil-x-ext (ly:stencil-extent stil X)) (stil-start (car stil-x-ext)) (stil-end (cdr stil-x-ext)) (stil-y-ext (ly:stencil-extent stil Y)) (stil-y-center (interval-center stil-y-ext))) (ly:stencil-add stil ;; Print the Beam.direction (ly:stencil-translate-axis (grob-interpret-markup grob beam-dir) 4 Y) ;; Print a cross at point (left-stem-x-coord left-y-average-coord) ;; division by 2 to reflect half-staff-space unit, below as well (make-cross-stencil (cons 0 (+ (/ left-y-average 2 ;; Print a cross at point (right-stem-x-coord right-y-average-coord) (make-cross-stencil (cons (- right-stem-x left-stem-x) (+ (/ right-y-average 2 ;; print a blue line connecting left/right-y-average (stencil-with-color (make-line-stencil 0.1 0 (/ left-y-average 2) (- right-stem-x left-stem-x) (/ right-y-average 2)) blue) ;; print two vertical lines at left/right edge of the given stil (make-line-stencil 0.1 stil-start (- stil-y-center 5) stil-start (+ stil-y-center 5)) (make-line-stencil 0.1 stil-end (- stil-y-center 5) stil-end (+ stil-y-center 5)) #(define whole-note-stem-stencil (lambda (grob) "Debugging-aid, print a simple vertical line for whole-note stems." (if (zero? (ly:grob-property grob 'duration-log)) (make-line-stencil 0.1 0 -5 0 5) ly:stem::print))) %% %% the code %% #(define (lists-map function ls) "Apply @var{function} to @var{ls} and all of it sublists. First it recurses over the children, then the function is applied to @var
Re: Whole-note tremolo beams
Second attempt: The function now has a syntax more similar to \repeat tremolo. I managed to fix it so it works in any clef, and it can be manually offset to avoid both augmentation dots and accidentals. This is still a little bit off, for some reason I can’t find out. When adding extra space the whole beam is moved a little in the opposite direction. The only thing I really have no idea on how to fix and that prevents it from being really useful for me is getting it to work in relative or fixed mode too. Does any of you know to accomplish that? Also: does any of you know a proper points of departure for the calculation of the slope in these cases? This looks kind of ok, but not really up to standards. \version "2.20.0" wholeNoteTremolo = #(define-music-function (parser location repeats extra-space basic-gap music) (integer? (pair? '(0 . 0)) (number? 1.3) ly:music?) (define is-note? (lambda (x) (equal? (ly:music-property x 'name) 'NoteEvent))) (define is-chord? (lambda (x) (equal? (ly:music-property x 'name) 'EventChord))) (define list-same (lambda (lst) (cond ((null? lst) #f) ((null? (cdr lst)) (car lst)) ((not (equal? (car lst) (cadr lst))) #f) (else (list-same (cdr lst)) (let* ((elts (ly:music-property music 'elements)) (notes-and-chords (filter (lambda (x) (or (is-note? x) (is-chord? x))) elts)) (nc-i (car notes-and-chords)) (nc-ii (cadr notes-and-chords)) (duration-i (cond ((is-note? nc-i) (duration-of-note nc-i)) ((is-chord? nc-i) (list-same (map duration-of-note (filter is-note? (ly:music-property nc-i 'elements) (else #f))) (duration-ii (cond ((is-note? nc-ii) (duration-of-note nc-ii)) ((is-chord? nc-ii) (list-same (map duration-of-note (filter is-note? (ly:music-property nc-ii 'elements) (else #f))) (beam-count (if (and (equal? duration-i duration-ii) duration-i) (- (ly:duration-log duration-i) 2))) (middle-c-pos #f) (pitches-i (cond ((is-chord? nc-i) (event-chord-pitches nc-i)) ((is-note? nc-i) (list (ly:music-property nc-i 'pitch))) (else #f))) (pitch-steps-i (map ly:pitch-steps pitches-i)) (pitches-ii (cond ((is-chord? nc-ii) (event-chord-pitches nc-ii)) ((is-note? nc-ii) (list (ly:music-property nc-ii 'pitch))) (else #f))) (pitch-steps-ii (map ly:pitch-steps pitches-ii)) (staff-pos-i #f) (staff-pos-ii #f) (rising #f) (y-pos #f)) #{ \context Staff \applyContext #(lambda (context) (begin (set! middle-c-pos (ly:context-property context 'middleCPosition)) (set! staff-pos-i (cons (/ (+ middle-c-pos (eval (cons min pitch-steps-i) (interaction-environment))) 2) (/ (+ middle-c-pos (eval (cons max pitch-steps-i) (interaction-environment))) 2))) (set! staff-pos-ii (cons (/ (+ middle-c-pos (eval (cons min pitch-steps-ii) (interaction-environment))) 2) (/ (+ middle-c-pos (eval (cons max pitch-steps-ii) (interaction-environment))) 2))) ;this will choose the outmost notes of chords, giving maximal slope, I don't know if that's the way ;to calculate beam positions in this case (set! rising (< (+ (car staff-pos-i) (cdr staff-pos-i)) (+ (car staff-pos-ii) (cdr staff-pos-ii (set! y-pos (if rising (cons (car staff-pos-i) (cdr staff-pos-ii)) (cons (cdr staff-pos-i) (car staff-pos-ii )) \once \override Beam.length-fraction = #1 %should be widened for steeper slopes %the following two lines are supposed to make the beams shorter and move them left, to avoid %the accidental, or right, to avoid dots, but for some reason the beam moves slightly too much \once \override Beam.gap = #(+ basic-gap (/ (+ (car extra-space ) (cdr extra-space)) 2)) %this doesn't really work \once \override Beam.extra-offset = #(cons (/ (- (car extra-space) (cdr extra-space)) 2) 0) %this doesn't really work \once \override Beam.positions = #(lambda (grob) (let* ((dir (ly:grob-property grob 'direction)) (length-fraction (ly:grob-property grob 'length-fraction)) (beam-interval (* length-fraction .37)) ;horrible approximation (beam-thickness (ly:grob
Re: Whole-note tremolo beams
Thanks a lot! Here is a first attempt I’ve made, including a lot of problems: (For instance: only works in absolute mode, doesn’t avoid augmentation dots, doesn’t work in other clefs than treble, code could look better) % \version "2.20.0" \paper { ragged-right = ##f } wholeNoteTremolo = #(define-music-function (parser location repeats basic-gap acc-width nc-i nc-ii) (integer? (number? 1.3) (number? 0) ly:music? ly:music?) (define middle-c-pos #f) (define is-note? (lambda (x) (equal? (ly:music-property x 'name) 'NoteEvent))) (define is-chord? (lambda (x) (equal? (ly:music-property x 'name) 'EventChord))) (define list-same (lambda (lst) (cond ((null? lst) #f) ((null? (cdr lst)) (car lst)) ((not (equal? (car lst) (cadr lst))) #f) (else (list-same (cdr lst)) ;doesn't work, doesn't seem to get evaluated. #{ \context Staff \applyContext #(lambda (context) (begin (set! middle-c-pos (ly:context-property context 'middleCPosition)) (pretty-print middle-c-pos) )) #} (let* ((duration-i (cond ((is-note? nc-i) (duration-of-note nc-i)) ((is-chord? nc-i) (list-same (map duration-of-note (filter is-note? (ly:music-property nc-i 'elements) (else #f))) (duration-ii (cond ((is-note? nc-ii) (duration-of-note nc-ii)) ((is-chord? nc-ii) (list-same (map duration-of-note (filter is-note? (ly:music-property nc-ii 'elements) (else #f))) (beam-count (if (and (equal? duration-i duration-ii) duration-i) (- (ly:duration-log duration-i) 2))) (middle-c-pos -6) ;remove when call to staff works, otherwise it will only accept treble clef (pitches-i (cond ((is-chord? nc-i) (event-chord-pitches nc-i)) ((is-note? nc-i) (list (ly:music-property nc-i 'pitch))) (else #f))) (pitch-steps-i (map ly:pitch-steps pitches-i)) (staff-pos-i (cons (/ (+ middle-c-pos (eval (cons min pitch-steps-i) (interaction-environment))) 2) (/ (+ middle-c-pos (eval (cons max pitch-steps-i) (interaction-environment))) 2))) (pitches-ii (cond ((is-chord? nc-ii) (event-chord-pitches nc-ii)) ((is-note? nc-ii) (list (ly:music-property nc-ii 'pitch))) (else #f))) (pitch-steps-ii (map ly:pitch-steps pitches-ii)) (staff-pos-ii (cons (/ (+ middle-c-pos (eval (cons min pitch-steps-ii) (interaction-environment))) 2) (/ (+ middle-c-pos (eval (cons max pitch-steps-ii) (interaction-environment))) 2))) (rising (< (+ (car staff-pos-i) (cdr staff-pos-i)) (+ (car staff-pos-ii) (cdr staff-pos-ii ;this will choose the outmost notes of chords, giving maximal slope, I don't know if that's the way ;to calculate beam positions in this case (y-pos (if rising (cons (car staff-pos-i) (cdr staff-pos-ii)) (cons (cdr staff-pos-i) (car staff-pos-ii) #{ \once \override Beam.length-fraction = #1 %should be widened for steeper slopes %the following two lines are supposed to make the beams shorter and move them left, to avoid %the accidental, but for some reason seem to move the beam too much \once \override Beam.gap = #(+ basic-gap (/ acc-width 2)) %this doesn't really work \once \override Beam.extra-offset = #(cons (/ acc-width -2) 0) %this doesn't really work \once \override Beam.positions = #(lambda (grob) (let* ((dir (ly:grob-property grob 'direction)) (length-fraction (ly:grob-property grob 'length-fraction)) (beam-interval (* length-fraction .37)) ;horrible approximation (beam-thickness (ly:grob-property grob 'beam-thickness)) (half-beams-thickness (* (/ (- beam-count 1) 2) (+ beam-interval beam-thickness) dir)) (slope (- (car y-pos) (cdr y-pos))) (beam-damping (* .3 (tanh slope) (abs slope (cons (+ (car y-pos) half-beams-thickness (- beam-damping)) (+ (cdr y-pos) half-beams-thickness beam-damping)) )) \repeat tremolo #repeats { #nc-i #nc-ii } #} )) { \wholeNoteTremolo #8 #1.3 #1.5 gis'16 \wholeNoteTremolo #16 #1.3 #0 32 \wholeNoteTremolo #4 #1.3 #3.5 8 \time 6/4 \wholeNoteTremolo #12 #1.3 #0 a'16 b’ } % > 19 mars 2020 kl. 12:08 skrev Thomas Morley : > > Am Do., 19. März 2020 um 11:12 Uhr schrieb Leo Correia de Verdier > : >> >> For the sake of clarity, a MWE: >> >> %%% >> >> \version "2.20.0" >> \repeat tremolo 16 {dis'32 dis’’} >> >>
Re: Whole-note tremolo beams
Am Do., 19. März 2020 um 11:12 Uhr schrieb Leo Correia de Verdier : > > For the sake of clarity, a MWE: > > %%% > > \version "2.20.0" > \repeat tremolo 16 {dis'32 dis’’} > > %%% > > > 19 mars 2020 kl. 11:01 skrev Leo Correia de Verdier > > : > > > > Dear list! > > > > I’m working on a piece with a lot of whole note tremolos and was wondering > > if any of you have a nice workaround for the beams (issues 318 and 704). I > > would like them slanted (with the same slope as a regular beam), centered > > between the noteheads and avoiding accidentals on the second note column, > > but if you have code producing any of these results it would be welcome. > > Harm’s code from this tread does unfortunately not seem to work any longer > > http://lilypond.1069038.n5.nabble.com/Tremolos-between-two-whole-notes-tt57577.html#a57580 > > . I’ll start hacking something together, but if any of you already have > > invented this wheel it would be nice not to reinvent it. > > > > Thanks a lot! > > /Leo > > Hi, here an updated version of my ancient code, along with a function to supress warnings. \version "2.20.0" \paper { line-width = 120 } tweakWholeNoteTremolo = #(define-music-function (parser location gap y-off-pair)((number? 0.8) pair?) #{ \once \override Beam.gap = $gap \once \override Beam.positions = #(lambda (grob) (let* ((pos (beam::place-broken-parts-individually grob))) (cons (+ (car pos) (car y-off-pair)) (+ (cdr pos) (car y-off-pair) (cdr y-off-pair) #}) %--- test suppressWarning = #(define-void-function (amount message)(number? string?) (for-each (lambda (warning) (ly:expect-warning message)) (iota amount 1 1))) \suppressWarning 3 "weird stem size" \score { \relative c'' { \tweakWholeNoteTremolo #'(-2.4 . 1.2) \repeat tremolo 16 { gis32 dis' } %\break \tweakWholeNoteTremolo #'(-3.6 . 1.7) \repeat tremolo 32 { 64 d' } \tweakWholeNoteTremolo #1.3 #'(4.4 . -3.0) \repeat tremolo 16 { a'32 a, } } } \new PianoStaff << \new Staff = "right" { \repeat tremolo 16 { \tweakWholeNoteTremolo #'(11.2 . -19) e'''32 \change Staff = "left" a,, } } \new Staff = "left" { \clef bass s1 } >> It will not avoid possible accidentals at right NoteColumn, though. Not saying it would be impossible, rather I've not the time to dive into it deeper... Cheers, Harm
Re: Whole-note tremolo beams
For the sake of clarity, a MWE: %%% \version "2.20.0" \repeat tremolo 16 {dis'32 dis’’} %%% > 19 mars 2020 kl. 11:01 skrev Leo Correia de Verdier > : > > Dear list! > > I’m working on a piece with a lot of whole note tremolos and was wondering if > any of you have a nice workaround for the beams (issues 318 and 704). I would > like them slanted (with the same slope as a regular beam), centered between > the noteheads and avoiding accidentals on the second note column, but if you > have code producing any of these results it would be welcome. Harm’s code > from this tread does unfortunately not seem to work any longer > http://lilypond.1069038.n5.nabble.com/Tremolos-between-two-whole-notes-tt57577.html#a57580 > . I’ll start hacking something together, but if any of you already have > invented this wheel it would be nice not to reinvent it. > > Thanks a lot! > /Leo