lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Whole-note tremolo beams


From: Leo Correia de Verdier
Subject: Re: Whole-note tremolo beams
Date: Sun, 22 Mar 2020 17:38:33 +0100

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-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 { #music }
    #}
    ))


suppressWarning =
#(define-void-function (amount message)(number? string?)
   (for-each
    (lambda (warning) (ly:expect-warning message))
    (iota amount 1 1)))

\paper { ragged-right = ##f }

{
  \suppressWarning 3 "weird stem size"
  \clef alto
  \wholeNoteTremolo #8 #'(0 . 1.5) { gis'16 <dis'' b'> }
  \wholeNoteTremolo #16 { <gis b>32 <f' d''> }
  \wholeNoteTremolo #4 #'(0 . 3.5) { <g' d''! g''>8 <bes des' ees'> }
  \time 6/4
  \wholeNoteTremolo #12 #'(0.7 . 0) { a'16 b' }
}

> 21 mars 2020 kl. 17:35 skrev Leo Correia de Verdier <address@hidden>:
> 
> 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 <dis'' b'>
>  \wholeNoteTremolo #16 #1.3 #0 <gis b>32 <f' d''>
>  \wholeNoteTremolo #4 #1.3 #3.5 <g' d'' g''>8 <bes des' ees'>
>  \time 6/4
>  \wholeNoteTremolo #12 #1.3 #0 a'16 b’
> }
> %%%%%%%%%%%%%%%%%
>> 19 mars 2020 kl. 12:08 skrev Thomas Morley <address@hidden>:
>> 
>> Am Do., 19. März 2020 um 11:12 Uhr schrieb Leo Correia de Verdier
>> <address@hidden>:
>>> 
>>> 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 <address@hidden>:
>>>> 
>>>> 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  { <e, gis b>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
> 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]