lilypond-user
[Top][All Lists]
Advanced

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

Re: Moving notes in a chord to the opposite side of the stem?


From: David Nalesnik
Subject: Re: Moving notes in a chord to the opposite side of the stem?
Date: Mon, 9 Apr 2012 22:40:28 -0500

Hi Paul,

On Mon, Apr 9, 2012 at 9:50 PM, Paul Morris <address@hidden> wrote:
Thanks David and Nick!  More below...

David Nalesnik wrote:
Hi Paul,

On Mon, Apr 9, 2012 at 4:47 PM, Nick Payne <address@hidden> wrote:
On 10/04/12 06:56, Paul Morris wrote:
Thank you!  This works, but unfortunately (like the Hydra's heads) it introduces two other problems, one with horizontal spacing collisions and one with ledger lines.

1. Because the spacing engine does not take into account this low-level tweak, the tweaked notes sometimes collide with bar/measure lines and sometimes with other adjacent notes.  Is there a way to use Scheme to also increase the horizontal space given to the chord?  (I am still a beginner at Scheme.)

Can't help with the second problem, but for the first you could add additional horizontal space to either the barline or stem to increase their separation:

\version "2.15.36"

barspace = #(define-music-function (parser location extent) (pair?) #{
    \once \override Staff.BarLine #'extra-spacing-width = #extent
#})

stemspace = #(define-music-function (parser location extent) (pair?) #{
    \once \override Staff.Stem #'X-extent = #extent
#})

\relative c'' {
    c2 c c c \barspace #'(0 . 2)
    c c
    \stemspace #'(-2 . 0) c c
}

_______________________________________________
lilypond-user mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/lilypond-user


This seems to do the trick as far as horizontal spacing is concerned:

\version "2.15.36"

#(define ((shift offsets) grob)
  (let ((note-heads (ly:grob-array->list (ly:grob-object grob 'note-heads))))
    (map
      (lambda (p q) (set! (ly:grob-property p 'X-offset) q))
      note-heads offsets)))

displaceHeads =
#(define-music-function (parser location offsets) (list?)
  #{
    \once \override NoteColumn #'before-line-breaking = #(shift offsets)
  #}
)

{
  \displaceHeads #'(0 1.2 0)
  <c' e' g'>4
  \displaceHeads #'(0 1.2 1.2)
  <d' f' a'>
}

Hope this helps!
-David

Actually, David's approach appears to fix both problems!  Ledger lines are extended and appear twice as wide, just like with other chords that have notes on both sides of the stem.  The horizontal spacing seems to be working with standard noteheads.  (Looks like a good candidate for the LSR.)


Unfortunately a function I'm using to substitute custom stencils for NoteHead grobs seems to disrupt the horizontal spacing in some instances (particularly noticeable with bar lines).  I haven't figured out the pattern yet.  But worst case, that's something I can fix manually using the tweaks Nick suggested.  Or maybe there is a way to expand David's function to access the Stem from the NoteColumn and automatically give it an X-offset too?

A stripped down version of my code is below, if anyone is curious.  It is still a bit long.

Again, thanks so much!  I really appreciate it, as it would take me forever to try and figure this stuff out on my own.

-Paul


\version "2.15.32"

%Begin TwinNote scripts
%Customizing note head stencils based on pitch
%Defining stencils

upTriangle =
#(ly:make-stencil
    (list 'embedded-ps
    "gsave
      currentpoint translate
      newpath
      -.1875 -.5 moveto
      .65625 .5 lineto
      1.5 -.5 lineto
      closepath
      fill
      grestore" )
    (cons -.1875 1.5)
    (cons -.5 .5)
)

downTriangle =
#(ly:make-stencil
    (list 'embedded-ps
    "gsave
      currentpoint translate

      newpath
      .08 .34 moveto
      .65625 -.4 lineto
      1.2325 .34 lineto
      closepath
      0.12 setlinewidth
      stroke    

      newpath
      -.0775 .43 moveto
      .65625 -.43 lineto
      1.39 .43 lineto
      closepath
      0.1 setlinewidth
      stroke    
    
      newpath
      -.1675 .48 moveto
      .65625 -.48 lineto
      1.48 .48 lineto
      closepath
      0.04 setlinewidth
      stroke

      grestore" )
    (cons -.1875 1.5)
    (cons -.5 .5)
)

%Based on the pitch's semitone, which note head
#(define (semitone-to-stencil semitone)
        (if (= (remainder semitone 2) 0) downTriangle upTriangle)
)

%Get the pitch from the grob, convert to semitone
#(define (stencil-notehead grob)
   (semitone-to-stencil
     (ly:pitch-semitones (ly:event-property (event-cause grob) 'pitch))))

%End TwinNote scripts


#(define ((shift offsets) grob)
  (let ((note-heads (ly:grob-array->list (ly:grob-object grob 'note-heads))))
    (map
      (lambda (p q) (set! (ly:grob-property p 'X-offset) q))
      note-heads offsets)))

displaceHeads =
#(define-music-function (parser location offsets) (list?)
  #{
    \once \override NoteColumn #'before-line-breaking = #(shift offsets)
  #}
)

theMusic = {
\displaceHeads #'(0 0 1.45)
<c' e' g' >4

\displaceHeads #'(0 1.45 1.45)
<d' f' a'>

\displaceHeads #'(0 1.45 1.45)
<d' f' a'>

\displaceHeads #'(0 0 1.45)
< c' e' g'>

\displaceHeads #'(-1.45 -1.45 0)
< c'' e'' g''>

\displaceHeads #'(-1.45 -1.45 0)
< c''' e''' g'''>

\displaceHeads #'(0 0 1.45)
< c e g>

\displaceHeads #'(0 -1.45 0)
< c'' e'' g''>

\displaceHeads #'(0 0 -1.45)
< c'' e'' g''>
}

%TwinNote staff
\new Staff \with {
    staffLineLayoutFunction = #(lambda (p) (floor (/ (+ (ly:pitch-semitones p) 1) 2)))
    \override StaffSymbol #'line-positions = #'( 4 2 -2 -4 )

    % this override is messing up horizontal spacing:
    \override NoteHead #'stencil = #stencil-notehead
}
{
    \theMusic
}

% Regular staff
\new Staff {
    \theMusic
}


If you treat this new situation as I did earlier, by setting the stencil within an override of  'before-line-breaking, the new shapes are accommodated:

\new Staff \with {
    staffLineLayoutFunction = #(lambda (p) (floor (/ (+ (ly:pitch-semitones p) 1) 2)))
    \override StaffSymbol #'line-positions = #'( 4 2 -2 -4 )
    % this override is messing up horizontal spacing:
    %\override NoteHead #'stencil = #stencil-notehead
    \override NoteHead #'before-line-breaking = #(lambda (grob) 
      (set! (ly:grob-property grob 'stencil) (stencil-notehead grob)))
}

By the way, a quibble, but I probably should have used for-each instead of map in the earlier function:

#(define ((shift offsets) grob)
  (let ((note-heads (ly:grob-array->list (ly:grob-object grob 'note-heads))))
    (for-each
      (lambda (p q) (set! (ly:grob-property p 'X-offset) q))
      note-heads offsets)))

Best,
David


reply via email to

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