lilypond-user
[Top][All Lists]
Advanced

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

Re: select a note in a chord


From: Valentin Villenave
Subject: Re: select a note in a chord
Date: Wed, 23 Jan 2019 22:10:34 +0000

On 1/19/19, Davide Bonetti <address@hidden> wrote:
> For the sake of the discussion, I copy there the code as it now is:

Greetings Davide and everybody,
although these chord-transform functions were only intended for
written voicings (i.e. not ChordNames), David K. had a brilliant idea:
by setting the 'octavation property for every transposed pitch, we can
print the intended voicing *without* causing the chord to loose its
name.

Problem: the version I tried to modify (see below) works nicely for
primary \dropNote and \raiseNote commands, but when they’re nested
(e.g. with \invertChords) it gives erratic results. There’s obviously
something I missed; could anybody give it a try and tell me where it’s
going off the rails?

%%%%%%%%%%%%%%%%%%%%%%%%%

\version "2.21.0"

#(define-public (move-chord-note n direction)
   (_i "Transpose a note (numbered as @var{n}) by one octave in
@var{direction}.")
   (lambda (music)
     (let* ((elts (ly:music-property music 'elements))
            (l (length elts))
            ;; if direction is up, count from the bottom note upward,
            ;; if direction is down, count from the top note downward.
            (count-from (cond ((= direction UP) (- n 1))
                          ((= direction DOWN) (- l n))))
            ;; Notes may not have been entered from bottom to top;
            ;; extract the pitches and put them in order.
            (pitches (map (lambda (x) (ly:music-property x 'pitch))
                       (filter
                        (lambda (y)
                          (music-is-of-type? y 'note-event))
                        elts)))
            (sorted (sort pitches ly:pitch<?)))
       (if (and (music-is-of-type? music 'event-chord)
                (not (zero? n)) (>= l n))
           (begin
            ;; first apply the sorted pitches
            ;; to the actual notes.
            (map (lambda (e p)
                   (ly:music-set-property! e 'pitch p))
              elts sorted)
            ;; then transpose the note up or
            ;; down, depending on direction.
            (let* ((note (list-ref elts count-from))
                   (oct (ly:music-property note 'octavation)))
              (list-set! elts count-from
                (ly:music-transpose note
                  (ly:make-pitch
                   (cond
                    ((= direction UP) +1)
                    ((= direction DOWN) -1))
                   0)))
              (ly:music-set-property! note 'octavation
                (+ (cond
                    ((= direction UP) 1)
                    ((= direction DOWN) -1))
                  (if (null? oct) 0 oct))))
            ))
       music)))

dropNote =
#(define-music-function (parser location num music) (integer? ly:music?)
   (_i "Drop a note of any chords in @var{music}, in @var{num}
position from above.")
   (music-map (move-chord-note num down) music))

raiseNote =
#(define-music-function (parser location num music) (integer? ly:music?)
   (_i "Raise a note of any chords in @var{music}, in @var{num}
position from below.")
   (music-map (move-chord-note num up) music))

invertChords =
#(define-music-function (num music) (integer? ly:music?)
   (_i "Invert any chords in @var{music} into their @var{num}-th position.
(Chord inversions may be directed downwards using negative integers.)")
   (let loop ((num num) (music music))
     (cond ((zero? num) music)
       ((negative? num) (loop (1+ num) (dropNote 1 music)))
       (else (loop (1- num) (raiseNote 1 music))))))


ac =
\chordmode {
  \dropNote 2 c:maj
  \raiseNote 1 d:m7
  \invertChords 2 e:m7
}

<<
  \chords { \ac }
  {
    <>^\markup \sans "(should be: C△, Dm7 and Em7)"
    \ac  \bar "||"
  }
>>

%%%%%%%%%%%%%%%%%

Thanks!

V.



reply via email to

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