lilypond-user
[Top][All Lists]
Advanced

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

Re: ! Please answer interesting functionality question for PhD Diss


From: Jean Abou Samra
Subject: Re: ! Please answer interesting functionality question for PhD Diss
Date: Sun, 25 Oct 2020 11:49:49 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0

Hi Harm,

Le 25/10/2020 à 11:40, Thomas Morley a écrit :
Hi Jean,

Am Sa., 24. Okt. 2020 um 11:55 Uhr schrieb Jean Abou Samra <jean@abou-samra.fr>:

The problem so far is that I didn't find a proper way to set the chord 
configuration at a given musical moment (note heads placed at the left or at 
the right of the stem). For now I've used an extra-offset, which leads to 
inconsistent spacing. There is \override Stem.note-collision-threshold = 50, 
but that doesn't let you achieve the fourth chord before the end, where the 
upper note is on the left and the lower note is on the right, since the usual 
placement is the other way around.
Stem.note-collision-threshold gives you some possibilities, but to
freely position note-heads at a Stem, one needs to tackle
Stem.positioning-done.

#(define (distribute-note-heads-around-stem note-head-shifts)
   (lambda (grob)
   "Takes the note-heads from a stem-grob and applies offsets in X-direction
taken from @var{note-head-shifts}."
     (let* ((nhds-array (ly:grob-object grob 'note-heads))
            (nhds-list
              (if (ly:grob-array? nhds-array)
                  (ly:grob-array->list nhds-array)
                  '()))
            (sorted-nhds
              (sort
                nhds-list
                (lambda (p1 p2)
                  (ly:pitch<?
                    (ly:prob-property (ly:grob-property p1 'cause) 'pitch)
                    (ly:prob-property (ly:grob-property p2 'cause) 'pitch)))))
            (stem-starting-nhd?
              (lambda (nhd)
                (if (positive? (ly:grob-property grob 'direction))
                    (equal? nhd (car sorted-nhds))
                    (equal? nhd (last sorted-nhds))))))

       ;; Move note-heads in X-direction, looking at 'note-head-shifts'
       ;; If a stem starts at a moved note-head, adjust this note-head's
       ;; 'stem-attachment
       (for-each
         (lambda (nhd nhd-shift)
           (if (and (stem-starting-nhd? nhd) (not (zero? nhd-shift)))
               (let ((default-stem-attach
                       (ly:note-head::calc-stem-attachment grob)))
                 (ly:grob-set-property! nhd 'stem-attachment
                   (cons (car default-stem-attach)
                         (- (cdr default-stem-attach))))))
           (ly:grob-translate-axis! nhd
             (* nhd-shift
                (-
                   (interval-length (ly:grob-extent nhd nhd X))
                   (interval-length (ly:grob-extent grob grob X))))
           X))
         nhds-list
         note-head-shifts)
       #t)))

distributeNoteHeads =
#(define-music-function (nhd-shifts)(number-list?)
"Returns an override to distribute note-heads around a stem, according to
@var{nhd-shifts}."
   (if (not (every ly:dir? nhd-shifts))
       (let ((signs (map (@@ (lily) sign) nhd-shifts)))
         (ly:warning
           "Only directions like -1, 0, 1 are accepted, transforming ~a to ~a."
           nhd-shifts
           signs)
         ;; sign should really be public
         (set! nhd-shifts (map (@@ (lily) sign) nhd-shifts))))
   #{
     \override Stem.positioning-done =
       #(distribute-note-heads-around-stem nhd-shifts)
   #})

{
   %% Test the warning
   \once \distributeNoteHeads #'(1.1 0)
   < ees' gis' >

   \voiceTwo
   \once \distributeNoteHeads #'(0 -1)
   < e' g' >
}


Wohoo! Even when dealing with complex and important merge requests
you are still available for impressive things like this!

Thanks! Now I shall try to understand…

This sort-of looks like a missing feature in LilyPond to me. I'll
take a look at the original callback to see if it's easy to make it
read some property which has a callback similar to what is calculated
at present in positioning-done, so you could override it.

Code attached, with an output that resembles the image you (Michael) sent 
earlier. Note that you need a development version of LilyPond 
(lilypond.org/development). Naturally, this is only a start since at this point 
more details are needed about the specification of what you want to achieve. 
Nevertheless, I wanted to share this code to avoid duplication of effort in 
case someone else were willing to take over this topic.
To your comment:
% Not defined?
#(define pi (acos -1))

It's defined in lily-library,scm as
(define-public PI (* 4 (atan 1)))

Thank you for the tip!

Cheers,
Jean




reply via email to

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