Search code examples
lilypond

Mark key note in different colors according to voice?


I am working with 4 part vocal music. I am trying to make the key note a different color in each voice part. Based on previous answers and lilypond snippets, I have this code:

%Association list of pitches to colors.
#(define color-mapping
   (list    
    (cons (ly:make-pitch 0 6 FLAT) (x11-color 'blue))))

%Compare pitch and alteration (not octave).
#(define (pitch-equals? p1 p2)
   (and
    (= (ly:pitch-alteration p1) (ly:pitch-alteration p2))
    (= (ly:pitch-notename p1) (ly:pitch-notename p2))))

#(define (pitch-to-color pitch)
   (let ((color (assoc pitch color-mapping pitch-equals?)))
     (if color
         (cdr color))))

#(define (color-notehead grob)
   (pitch-to-color
    (ly:event-property (event-cause grob) 'pitch)))

And then in each voice I call it with:

\override NoteHead.color = #color-notehead

That makes every Bb in the score blue, which is a great start. But I would like to be able to have the Bb in voiceOne blue, in voiceTwo green, etc, so that my singers can tell at a glance when THEY have the tonic note.

The clunky solution would be to make 4 different versions of the music, and only call the override NoteHead.color in one voice per version. And give out a different version to each singer based on voice part.

Is there a coding way to do this where the specific note is a different color per voice?


Solution

  • Probably the easiest solution is to define different functions for each different voice, and in each function definition you'd use different colours. Here is an example with two voices:

    \version "2.19.53"
    
    %Association list of pitches to colors.
    #(define color-mapping-voice1
       (list    
        (cons (ly:make-pitch 0 6 FLAT) (x11-color 'blue))))
    
    #(define color-mapping-voice2
       (list    
        (cons (ly:make-pitch 0 6 FLAT) (x11-color 'red))))
    
    %Compare pitch and alteration (not octave).
    #(define (pitch-equals? p1 p2)
       (and
        (= (ly:pitch-alteration p1) (ly:pitch-alteration p2))
        (= (ly:pitch-notename p1) (ly:pitch-notename p2))))
    
    #(define (pitch-to-color-voice1 pitch)
       (let ((color (assoc pitch color-mapping-voice1 pitch-equals?)))
         (if color
             (cdr color))))
    
    #(define (pitch-to-color-voice2 pitch)
       (let ((color (assoc pitch color-mapping-voice2 pitch-equals?)))
         (if color
             (cdr color))))
    
    #(define (color-notehead-voice1 grob)
       (pitch-to-color-voice1
        (ly:event-property (event-cause grob) 'pitch)))
    
    #(define (color-notehead-voice2 grob)
       (pitch-to-color-voice2
        (ly:event-property (event-cause grob) 'pitch)))
    
    {
      \new Staff <<
        \new Voice{ 
          \voiceOne
          \override NoteHead.color = #color-notehead-voice1 
          bes' bes' d'' f''
        }
        \new Voice{ 
          \voiceTwo
          \override NoteHead.color = #color-notehead-voice2 
          bes d' f' bes'
        }
      >>
    }
    

    Producing:

    enter image description here