Jump to content

Transposing pitches with minimum accidentals (“smart” transpose): Difference between revisions

From LilyPond wiki
m Replace version="2.24.0" with version="2.24" now that the LilyWiki extension supports auto-selecting the latest release in a stable series
mNo edit summary
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
This example uses some Scheme code to enforce enharmonic modifications for notes in order to have the minimum number of accidentals. In this case, the following rules apply:
This example uses some Scheme code to enforce enharmonic modifications for notes in order to have the minimum number of accidentals. In this case, the following rules apply:


Double accidentals should be removed
* double accidentals should be removed
 
* b sharp → c
B sharp -> C
* e sharp → f
 
* c flat → b
E sharp -> F
* f flat → e
 
C flat -> B
 
F flat -> E


In this manner, the most natural enharmonic notes are chosen.
In this manner, the most natural enharmonic notes are chosen.
Line 16: Line 12:
#(define (naturalize-pitch p)
#(define (naturalize-pitch p)
   (let ((o (ly:pitch-octave p))
   (let ((o (ly:pitch-octave p))
        ;; `ly:pitch-alteration` returns quarter tone steps.
         (a (* 4 (ly:pitch-alteration p)))
         (a (* 4 (ly:pitch-alteration p)))
        ;; alteration, a, in quarter tone steps,
        ;; for historical reasons
         (n (ly:pitch-notename p)))
         (n (ly:pitch-notename p)))
     (cond
     (cond
       ((and (> a 1) (or (eqv? n 6) (eqv? n 2)))
       ((and (> a 1)
            (or (eqv? n 6) (eqv? n 2)))
       (set! a (- a 2))
       (set! a (- a 2))
       (set! n (+ n 1)))
       (set! n (+ n 1)))
       ((and (< a -1) (or (eqv? n 0) (eqv? n 3)))
       ((and (< a -1)
            (or (eqv? n 0) (eqv? n 3)))
       (set! a (+ a 2))
       (set! a (+ a 2))
       (set! n (- n 1))))
       (set! n (- n 1))))
     (cond
     (cond
       ((> a 2) (set! a (- a 4)) (set! n (+ n 1)))
       ((> a 2)
       ((< a -2) (set! a (+ a 4)) (set! n (- n 1))))
      (set! a (- a 4))
     (if (< n 0) (begin (set! o (- o 1)) (set! n (+ n 7))))
      (set! n (+ n 1)))
     (if (> n 6) (begin (set! o (+ o 1)) (set! n (- n 7))))
       ((< a -2)
      (set! a (+ a 4))
      (set! n (- n 1))))
     (when (< n 0)
      (set! o (- o 1))
      (set! n (+ n 7)))
     (when (> n 6)
      (set! o (+ o 1))
      (set! n (- n 7)))
     (ly:make-pitch o n (/ a 4))))
     (ly:make-pitch o n (/ a 4))))


Line 38: Line 43:
         (e (ly:music-property music 'element))
         (e (ly:music-property music 'element))
         (p (ly:music-property music 'pitch)))
         (p (ly:music-property music 'pitch)))
     (if (pair? es)
     (when (pair? es)
        (ly:music-set-property!
      (ly:music-set-property! music 'elements
          music 'elements
                              (map naturalize es)))
          (map naturalize es)))
     (when (ly:music? e)
     (if (ly:music? e)
      (ly:music-set-property! music 'element
        (ly:music-set-property!
                              (naturalize e)))
          music 'element
     (when (ly:pitch? p)
          (naturalize e)))
      (set! p (naturalize-pitch p))
     (if (ly:pitch? p)
      (ly:music-set-property! music 'pitch p))
        (begin
          (set! p (naturalize-pitch p))
          (ly:music-set-property! music 'pitch p)))
     music))
     music))


naturalizeMusic =
naturalizeMusic =
#(define-music-function (m)
#(define-music-function (m) (ly:music?)
  (ly:music?)
   (naturalize m))
   (naturalize m))


music = \relative c' { c4 d e g }
music = \relative c' { c4 d e g }


\score {
\new Staff {
  \new Staff {
  \transpose c ais { \music }
    \transpose c ais { \music }
  \naturalizeMusic \transpose c ais { \music }
    \naturalizeMusic \transpose c ais { \music }
  \transpose c deses { \music }
    \transpose c deses { \music }
  \naturalizeMusic \transpose c deses { \music }
    \naturalizeMusic \transpose c deses { \music }
  }
  \layout { }
}
}
</lilypond>
</lilypond>
Line 75: Line 73:
[[Category:Workaround]]
[[Category:Workaround]]
[[Category:Scheme]]
[[Category:Scheme]]
[[Category:Snippet]]

Latest revision as of 13:09, 28 December 2025

This example uses some Scheme code to enforce enharmonic modifications for notes in order to have the minimum number of accidentals. In this case, the following rules apply:

  • double accidentals should be removed
  • b sharp → c
  • e sharp → f
  • c flat → b
  • f flat → e

In this manner, the most natural enharmonic notes are chosen.

\version "2.24"

#(define (naturalize-pitch p)
   (let ((o (ly:pitch-octave p))
         ;; `ly:pitch-alteration` returns quarter tone steps.
         (a (* 4 (ly:pitch-alteration p)))
         (n (ly:pitch-notename p)))
     (cond
      ((and (> a 1)
            (or (eqv? n 6) (eqv? n 2)))
       (set! a (- a 2))
       (set! n (+ n 1)))
      ((and (< a -1)
            (or (eqv? n 0) (eqv? n 3)))
       (set! a (+ a 2))
       (set! n (- n 1))))
     (cond
      ((> a 2)
       (set! a (- a 4))
       (set! n (+ n 1)))
      ((< a -2)
       (set! a (+ a 4))
       (set! n (- n 1))))
     (when (< n 0)
       (set! o (- o 1))
       (set! n (+ n 7)))
     (when (> n 6)
       (set! o (+ o 1))
       (set! n (- n 7)))
     (ly:make-pitch o n (/ a 4))))

#(define (naturalize music)
   (let ((es (ly:music-property music 'elements))
         (e (ly:music-property music 'element))
         (p (ly:music-property music 'pitch)))
     (when (pair? es)
       (ly:music-set-property! music 'elements
                               (map naturalize es)))
     (when (ly:music? e)
       (ly:music-set-property! music 'element
                               (naturalize e)))
     (when (ly:pitch? p)
       (set! p (naturalize-pitch p))
       (ly:music-set-property! music 'pitch p))
     music))

naturalizeMusic =
#(define-music-function (m) (ly:music?)
   (naturalize m))

music = \relative c' { c4 d e g }

\new Staff {
  \transpose c ais { \music }
  \naturalizeMusic \transpose c ais { \music }
  \transpose c deses { \music }
  \naturalizeMusic \transpose c deses { \music }
}