June 23, 2019

Beautiful Tablature with LaTeX

Beautiful Tablature with LaTeX

As a programmer that's written a fairly long and technical whitepaper, I've gotten fairly used to using LaTeX (pronounced "lah-tech"). I've used it at work, too, in order to document various things about programs, such as what API methods are being consumed, or to give rundowns of various parts of an application. The final results look darn impressive and many times are quicker to produce than with normal word processors (especially if you're fairly proficient).

If you haven't heard of LaTeX before, it's basically Microsoft Word for programmers (and the open-source community). As such, it's fairly technical (and debugging what you would consider to be trivial things can drive you insane), but it's a very powerful typesetting program that lets you do practically anything and everything you want with text. You can create variables and macros so you don't ever have to find-and-replace (and you can type less) when you need to rename something, and you don't have to deal with pasting text with or without formatting (I don't know how anyone can stand Microsoft's persistence of formatting and "smart quotes" in nearly all their applications).

Recently, I've gotten the idea of using it to typeset tablature for guitar, and found that there are some solutions out there.

Enter LilyPond

LilyPond is based off of LaTeX and comes prepackaged as its own application. Now, this blog post isn't meant to be a tutorial in getting everything set up, especially since I installed a lot of things in trying to get things working how I wanted it, and I can't really make a reliable tutorial without starting over with a fresh OS installation (something I don't really want to do since I've got it working).

The LilyPond application really only lets you write sheet music, but it does support tablature for most instruments (including guitar). I was more interested in including regular LaTeX markup in the form of explanations alongside some tabs of difficult guitar licks, so the LilyPond application wasn't exactly what I was after.

However, LilyPond comes with additional utilities, such as lilypond-book, and after adding the LilyPond bin directory to my PATH, I followed the documentation and used the lilypondfile{filename.ly} LaTeX command.

lilypond-book can take a .tex file using LilyPond-specific commands, parse the commands and produce a new .tex file with the LilyPond-specific commands replaced with LaTeX-compliant markup.

As far as editors go, something like Visual Studio Code is adequate. There are some syntax highlighting extensions for both LaTeX and LilyPond, but at this time, there isn't an extensions that automates the workflow.

One can easily write a simple bash or batch script to run the lilypond-book command and then the appropriate pdflatex command (or other command from their TeX distribution of choice) to produce a final output. All in all, not too painful of a setup.

Enter TuxGuitar

I've been using TuxGuitar for as long as I've been playing guitar, which is something like 11 years now. It hasn't really changed much throughout all the time I've been using it, but it turns out that it has support for exporting music to a LilyPond format!

Now, this export feature is currently broken, but it is fairly easy to correct the output. Also, some of the ways that TuxGuitar exports doesn't exactly produce tablature with the exact notation that one would prefer, but that's not too bad to fix, either. One of these days I'll patch TuxGuitar to format exactly how I want it to, but until then, I'll keep hand-keying changes in the LilyPond output.

The first fix you'll want to make is to change this line:

\clef #(if $inTab "tab" "treble_8")

to this line:

\clef #(if inTab "tab" "treble_8")

Removing the $ is all you need to do do get your output to work with lilypond-book.

If you're keeping the music score in with the tablature, you might want to take the _8 out, too. You also might want to remove the \ottava #0s and \ottava #1s from the actual notes in the .ly file, but again, that's up to your preference and what you think would be most readable by your target audience.

TuxGuitar also doesn't seem to export legato (hammer-ons and pull-offs) correctly (it annotates with "H"s instead of using a slur), so you can adjust the LilyPond file according to the official documentation to get the results that you want.

Enter GuitarChordSchemes

Lastly, you might want to write out guitar chords and scales, too. There's a LaTeX package for this: guitarchordschemes.

For scales, when debugging what I thought might've been a padding issue caused by the aforementioned package, I wrote the following custom command that you're free to use instead (keep in mind that it is much more limited!):

\begin{tikzpicture}[scale=.5,note/.style={circle,draw,fill=gray!50,minimum size=1}]
  % poorly named variables used for calculations
  \def\es{\nf - 1}
  \def\ed{\nf + 1}

  % strings
  \foreach \x in {0,...,5}
    \draw [thick] (1,\x)--(2*\ed,\x) ;
  \draw [thick] (1,0)--(1,5);
  \draw [thick] (2*\ed,0)--(2*\ed,5);

  % string names
  \node [right, scale=.75] at (0,0) {E};
  \node  [right, scale=.75] at (0,1) {A};
  \node  [right, scale=.75] at (0,2) {D};
  \node  [right, scale=.75] at (0,3) {G};
  \node  [right, scale=.75] at (0,4) {B};
  \node  [right, scale=.75] at (0,5) {E};

  % fret lines
  \foreach \x in {2,...,\nf}
    \draw [thick] (2*\x - 1,0)--(2*\x - 1,5) ;

  % notes 
  \foreach \x/\y [count=\i] in #2 {
    \node [note] (0,0) at (2*\y, 6 - \x) {};


You'd use this command in the following way to make a three-note-per-string major scale shape:

  1/4, 1/6, 1/7,
  2/4, 2/6, 2/7,
  3/3, 3/4, 3/6,
  4/3, 4/4, 4/6,
  5/2, 5/4, 5/6,
  6/2, 6/4, 6/6

The first argument is how many frets should be displayed, and the second argument are the actual notes that should be fretted (in the form of string/fret.

This looks like the following:

The scales command from the guitarchordschemes package can produce very similar output and has more flexibility (as well as support for fingerings, indicating roots, and positions) because it was not written in less than an hour.


Eventually I'll make a template and perhaps even a proper Visual Studio Code extension and tutorial for getting everything setup, but I feel that this post achieves enough for now.