Make Stunning Schenker Graphs with GNU Lilypond

GNU Lilypond provides an easy-to-use, yet extremely powerful, tool for generating musical notation, including Schenkerian Analysis graphs.
Creating a Lilypond Template for Schenkerian Graphs

Setting up a Lilypond file for a Schenker graph is fairly straightforward. A typical graph contains one or more grand staves, or piano staves, so one will likely begin with a piano template. To modify a piano template for a Schenker graph, add a few lines of code. Inside the PianoStaff brackets, but outside the individual Staff context brackets, add these lines:

\set Score.timing = ##f
\set PianoStaff.followVoice = ##t

The first line creates an unmetered score, with no barlines—typical for Schenker graphs. The second line is explained later.

Inside each Staff context, and inside \relative brackets if you use them, insert:

\override Staff.NoteCollision
  #'merge-differently-headed = ##t

This allows you to combine several layers of hidden voices—an important tool—without altering the note spacing.

The last global element is adding raggedright = ##t to the \layout section. I think this just looks better, but it also ensures consistency of measurement if you make significant edits to the graph after you've begun working on spacing. The piano template is now ready to be used for a Schenkerian graph. For an example template built upon a single grand staff, see the Resources.

Building a Schenkerian Graph in Lilypond

The first and most important part of the process of building a Schenkerian graph is to sketch the final graph by hand. The more complex the notation, the more valuable this will be. And even though Lilypond makes it easier than Finale or Sibelius to edit graphs after they have been created, you will still save much time and effort by sketching the complete graph by hand before typesetting it. It is also a good idea to mark off the beats that will be used. Because almost every voice in the Lilypond file will contain a number of skipped beats, it is essential to know the number and layout of beats ahead of time. One quarter-note beat for each notehead should suffice.

The Fundamental Structure

The next step is to typeset the fundamental structure, the half notes connected by an eighth-note beam. I chose to use two voices for each staff when creating this. One voice contains eighth notes with invisible noteheads, and the other contains half notes with invisible stems. The fundamental structure for the upper staff of the Bach graph looks like this:

    \override Beam  #'positions = #'(8 . 8)
    \override NoteHead #'transparent = ##t
    s1 b8[ s4. s1 a8 s4. s2 g8] s4.
    \revert Beam #'positions
    \revert NoteHead #'transparent
    \override Stem #'transparent = ##t
    s1 b2 s1 a2 s2 g2
    \revert Stem #'transparent

Figure 2. The fundamental structure uses half notes connected by an eighth-note beam.

Notice first that I override the beam positions, to make it level and out of the way of any notes and stems that may be placed under it. Also notice the use of the transparent property, one of your best friends when creating a Schenker graph in Lilypond. And of course, notice that the beats correspond exactly, with an eighth note and dotted-quarter skip in voice one, corresponding to each half note in voice two.

If you want to put scale-degree marks on each note, as in the Bach graph, Lilypond 2.6 now makes it possible without using LaTeX. You simply mark up the note like this:

b8[^\markup { \override #'(baseline-skip . 0.5)
\column { \small {^ 3} } }

The baseline-skip override should align the carat tightly over the numeral.

You also may notice that I chose to create multiple voices with brackets and back-slashes, rather than \voiceOne, \voiceTwo and so on. In my experience, the brackets are quicker, they make it easier to insert and delete voices, and they are less likely to cause alignment problems between voices.

Slurs and Layers

Once the fundamental structure has been created in each staff, next comes the surrounding notes. I typically begin with plain noteheads in one voice—separate from the two voices already created—and add beams, stems, slurs and additional voices as I continue. This helps me better organize my code. To create a voice with plain noteheads, begin the voice with the code:

\override Stem #'transparent = ##t
\override Stem #'length = #0