Jump to content

Transposing pitched rests

From LilyPond wiki

If pitched rests (entered with \rest) are transposed, the \fixRests helper function ensures that rests are not positioned on staff lines

\version "2.24.0"

%% This code was originally written by Benkő Pál.
%%
%% Taken from
%%
%% https://gitlab.com/lilypond/lilypond/-/issues/2249#note_339764389

#(define (round-pitch p)
   "Move a rest half a space down if not on a line.

This is needed when transposing."
   (let* ((o (ly:pitch-octave p))
          (n (ly:pitch-notename p))
          (m (* (floor (/ (+ (* 7 o) n) 2)) 2))
          (a (remainder m 7))
          (b (/ (- m a) 7)))
     (ly:make-pitch b a 0)))

#(define (fix-rests music)
   "Prepare a single pitched rest for transposition."
   (let ((n (ly:music-property music 'name))
         (p (ly:music-property music 'pitch)))
     (if (and (ly:pitch? p) (eqv? n 'RestEvent))
         (ly:music-set-property! music 'pitch (round-pitch p)))
     music))

fixRests =
#(define-music-function (mus) (ly:music?)
   "Apply 'fix-rests' to MUS."
   (music-map (lambda (x) (fix-rests x)) mus))


mus = {
  g'2 g'\rest g'1\rest g'\breve\rest
  \break
}

{
  \omit Staff.TimeSignature
  \cadenzaOn

  <>^"original"
  \mus
  <>^"transposed without adjusting rest positions"
  \transpose g a \mus
  % Note that there is a ZWNJ character (U+200C) between 'f' and 'i'
  % to prevent the display of an 'fi' ligature.
  <>^\markup { transposed with \typewriter "\f‌ixRests" }
  \fixRests \transpose g a \mus
}

\paper {
  indent = 0
  line-width = 100\mm
  tagline = ##f
}