lilypond

Change color of notes below and above a certain pitch


While writing a Lilypond score for recorders (flutes), I wish I could automatically mark notes with pitches beyond the range of an instrument by changing its color.

The idea is that, for example, all absolute pitches below f and all pitches above g'' are colored red for the bass instrument. The same for tenor, alt and soprano instruments.

I found a helpful question on coloring notes, Coloring notes in Lilypond by pitch, but there remains a piece of code I cannot write:

#(define (ambitus-notehead-alt grob)
  ( **code_i_cannot_write** )
#(define (ambitus-notehead-tenor grob)
  ( **code_i_cannot_write** )
#(define (ambitus-notehead-bass grob)
  ( **code_i_cannot_write** )

\score {
  \new Staff \relative c' {
    \override NoteHead #'color = #ambitus-notehead-alt
    \music_altrecorder
  }
  \new Staff \relative c' {
    \override NoteHead #'color = #ambitus-notehead-tenor
    \music_tenorrecorder
  }
  \new Staff \relative c' {
    \override NoteHead #'color = #ambitus-notehead-bass
    \music_bassrecorder
  }
}

Solution

  • Here is a function that does what you want:

    \version "2.19.82"
    
    #(define (colour-out-of-range grob)
       (let* ((pch (ly:event-property (event-cause grob) 'pitch))
              (semitones (ly:pitch-semitones pch)))
              (cond ((< semitones 0) red)
                    ((> semitones 24) red)
                    (else black))))
    
    \score {
      \new Staff \relative c' {
        \override NoteHead.color = #colour-out-of-range
        g8 a b c d e f g a b c d e f g a b c d e f g
      }
    }
    

    Producing:

    enter image description here

    To customize it for your instrument's range, change the values of (< semitones 0) and (> semitones 24). The value 0 is the middle C (C4), and increments of 1 are equal to one semitone. So in the case above, the range is between C4-C6. You need to use negative values for pitches below middle C (e.g. -5 is G3).