Four-shape solfège

In another post I wondered whether it would be possible to enter notes using the four syllables used in Sacred Harp singing, where an octave is not do re mi fa sol la ti do but rather fa so la fa so la mi fa. I guessed that the answer was no, because LilyPond assumes that note names will repeat at the octave.

But @tychoish and @willf both pointed out that all you need is a way to distinguish between the two fa‘s, the two so‘s and the two la‘s in an octave. And of course there are plenty of ways of doing that.

One nice way is using capitalization: LilyPond is case-sensitive, and so it’s perfectly possible for fa and Fa to represent two different pitches. This lets us enter a C major scale as follows, without confusing the parser: Fa is always the tonic, fa is always the fourth degree; and similarly for So and so, or La and la; and so there is never any ambiguity:

\include "fasola.ly"
\fasola c' { Fa So La fa so la mi Fa }
\fasola d' { Fa So La fa so la mi Fa }

System Message: WARNING/2 (\relative c' { c d e f g a b c \key d \major d, e fis g a b cis d })

lilypond exited with error: [stderr] GNU LilyPond 2.19.15 Changing working directory to: `/var/folders/05/6rw3pz3n6n57db3pqf5r5pg00000gn/T/tmpajcaesua’ Processing `/var/folders/05/6rw3pz3n6n57db3pqf5r5pg00000gn/T/tmpajcaesua/music.ly’ Parsing... /var/folders/05/6rw3pz3n6n57db3pqf5r5pg00000gn/T/tmpajcaesua/music.ly:1: warning: no \version statement found, please add \version “2.19.15” for future compatibility Interpreting music... Preprocessing graphical objects... Finding the ideal number of pages... Fitting music on 1 page... Drawing systems... Layout output to `music.eps’... Converting to PNG...dyld: Library not loaded: ./bin/../sobin/libgs.8.70.dylib Referenced from: /Applications/LilyPond.app/Contents/Resources/bin/../bin/gs Reason: image not found fatal error: GS exited with status: 6 [stdout]

Here is the lilypond source code which was included (as fasola.ly) in that example:

fasola =
  #(define-music-function (parser location k m) ; take two real arguments: k and m.
                          (ly:pitch? ly:music?) ; k should be a pitch, m should be some music
    #{\key $k \major                            % set the key to k
      \transpose do $k { \relative $k { $m } }  % and transpose the music so that "do" is k
    #}
  )

relativeDoPitchNames = #`(
  (cf . ,(ly:make-pitch -1 0 FLAT))
  (c  . ,(ly:make-pitch -1 0 NATURAL))
  (cs . ,(ly:make-pitch -1 0 SHARP))
  (df . ,(ly:make-pitch -1 1 FLAT))
  (d  . ,(ly:make-pitch -1 1 NATURAL))
  (ds . ,(ly:make-pitch -1 1 SHARP))
  (ef . ,(ly:make-pitch -1 2 FLAT))
  (e  . ,(ly:make-pitch -1 2 NATURAL))
  (es . ,(ly:make-pitch -1 2 SHARP))
  (ff . ,(ly:make-pitch -1 3 FLAT))
  (f  . ,(ly:make-pitch -1 3 NATURAL))
  (fs . ,(ly:make-pitch -1 3 SHARP))
  (gf . ,(ly:make-pitch -1 4 FLAT))
  (g  . ,(ly:make-pitch -1 4 NATURAL))
  (gs . ,(ly:make-pitch -1 4 SHARP))
  (af . ,(ly:make-pitch -1 5 FLAT))
  (a  . ,(ly:make-pitch -1 5 NATURAL))
  (as . ,(ly:make-pitch -1 5 SHARP))
  (bf . ,(ly:make-pitch -1 6 FLAT))
  (b  . ,(ly:make-pitch -1 6 NATURAL))
  (bs . ,(ly:make-pitch -1 6 SHARP))
  (Fa  . ,(ly:make-pitch -1 0 NATURAL))
  (So  . ,(ly:make-pitch -1 1 NATURAL))
  (La  . ,(ly:make-pitch -1 2 NATURAL))
  (fa  . ,(ly:make-pitch -1 3 NATURAL))
  (so  . ,(ly:make-pitch -1 4 NATURAL))
  (la  . ,(ly:make-pitch -1 5 NATURAL))
  (mi  . ,(ly:make-pitch -1 6 NATURAL))
)
pitchnames = \relativeDoPitchNames
#(ly:parser-set-note-names parser relativeDoPitchNames)