Invert notes in a chord

A set of functions to:
- drop notes in a chord (like jazz drop2),
- rise notes in a chord
- invert chords

\version "2.24.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 their possible octavation.
            (pitches (map
                      (lambda (x)
                        (let ((oct (ly:music-property x 'octavation))
                              (p (ly:music-property x 'pitch)))
                          (if (null? oct) p
                              (ly:pitch-transpose p
                                (ly:make-pitch oct 0 0)))))
                      (filter
                       (lambda (y)
                         (music-is-of-type? y 'note-event))
                       elts))))
       (if (and (music-is-of-type? music 'event-chord)
                (not (zero? n)) (>= l n))
           (begin
            ;; Sort the actual notes, depending on their pitch.
            (set! elts
                  (sort elts
                    (lambda (a b)
                      (ly:pitch<?
                       (ly:music-property a 'pitch)
                       (ly:music-property b 'pitch)))))
            ;; 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)))

%% drop a note of a chord, in num position from above
dropNote =
#(define-music-function (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))

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

%% invert chords
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)
           ((ly:music-function-extract dropNote)  1 music)))
       (else
         (loop
           (1- num)
           ((ly:music-function-extract riseNote)  1 music))))))



ac = \relative c' {
  <c es g bes>2
  <d as' f c'>
  \chordmode {c:maj es:6} %work also with chordmode
}

{
  <>^\markup "chords"
  \ac
  \bar "||"
  <>^\markup "drop 2"
  \dropNote 2 \ac
  \bar "||"
  <>^\markup "drop 4"
  \dropNote 4 \ac
  \bar "||"
  <>^\markup "drop 2 and 4"
  \dropNote 2 \dropNote 4 \ac
  \bar "||"
  <>^\markup "rise 1"
  \riseNote 1 \ac
  \bar "||"
  <>^\markup "rise 3"
  \riseNote 3 \ac
  \bar "||"
  <>^\markup "2nd inversion"
  \invertChords 2 \ac
  \bar "||"
  <>^\markup "\"down\" inversion"
  \invertChords -1 \ac
  \bar "||"
}