Let It Snow!
26th Dec 2019
I've been arranging a lot of things over the past two years as the CEO of Meeshkan — meetups, obligatory insurances, flights, pizza deliveries. However, one thing I haven't gotten the chance to arrange much is music. Until now! This holiday season, I took the time to make a six-voice arrangement of Let It Snow! by Sammy Cahn and Jule Styne. I have open-sourced the arrangement for folks to sing as they go caroling. In addition to a PDF, this project contains the LilyPond markdown and the small hack I wrote to get LilyPond to write swing rhythms correctly in the MIDI.
In this article, I'll discuss two facets of this project — the arrangement in LilyPond and the MIDI swing hack (written in Scheme). In doing so, I hope everyone finds a useful stocking stuffer. Ho ho ho!
Created by two Dutch musicians in 1996, GNU LilyPond is one of my favorite FOSS projects. It is currently maintained by a passionate and vibrant community of musicians and music enthusiasts.
LilyPond has a similar markdown language to LaTeX. In Let It Snow!, for example, the following input syntax:
generates the following result in measure 52, voice two of the PDF:
The other elements of the syntax are all explained in LilyPond's amazing documentation, which exists mostly due to a heroic effort by Graham Percival. For example, Let It Snow! contains key signatures, tempo indications, final bar lines, slurs, and partial measures. I have yet to run into something that LilyPond cannot do with some finagling.
The top-level organization of my LilyPond files tends to be like this:
Start with a version number, then the music and optionally lyrics, then smoosh everything together into a score, then provide options for typesetting and for the MIDI if needed. Even though LilyPond's documentation is second to none, top-level organization of LilyPond files is a pain for newbies, and I find that pilfering other people's stuff is the best way to avoid tedious gotchyas and get that "wow" effect of a score on first compile. To see a few more use cases in vocal music, you can check out the repo for Sit Ozfårs Wysr. If you're a pianist, Google Keith O'Hara. If you're doing orchestral music, check out Werner Lemberg. Contemporary music? Trevor Bača. Check out these people's open-source scores, use them to make your own, and write great things!
LilyPond, without any coaxing, will generate a MIDI in straight-eighths and no swing, which is great for Bach, Buxtehude, Berstein, Beethoven, Brahms, Bruckner, and Bellini but not so great for Basie, Baker and Brubeck. There are many tricks one can use to make Lily swing, but they tend to be all-or-nothing, meaning that they will act on the global tempo map, which means that unswung parts will be ignored. This is particularly annoying when working with jazz arrangements that contain tuplets, which should never be swung.
To get around this, I wrote an ugly hack. But unlike many of my other hacks, this one works. My initial goal was to write it in a functional style, but for some reason that didn't pan out, so I used global variables to store tempo information. If anyone can see why the
fold command isn't folding durations properly, please let me know. With that caveat, let's see how the sausage is made!
First, for anyone doing wholesale music manipulation in LilyPond, start by repurposing the naturalizeMusic example on this page. I've copied it below as well. It is stable, well written, and provides a useful template for most tweaking you'll need to do on a score.
In LilyPond, a score is represented as a Lisp list containing an arboreal structure of musical information. In the example above,
naturalizeMusic is the top-level entry point that behaves like a LaTeX macro. Then, the function
naturalize is a recursive function that acts on lists of elements, individual notes, and individual pitches of notes, drilling down through the tree until it gets to pitches. In the case of Let It Snow!, I do the same thing with rhythms. You can use the same strategy it with articulations, dynamics, or slurs, and the general pattern will always be the same. Lastly,
naturalize-pitch actually does the heavy lifting on the pitches. In my version, the
swing-duration function acts on a single duration, making it swing if it is contains an eighth note and otherwise leaving it untouched. The result is unswung tuplets and swung eighth notes coexisting in the same MIDI. w00t!
Enjoy Let It Snow! The supporting materials talked about in this article are for anyone wishing to do their own arranging, coding, singing, or mixing. A big thank you to Timo Mäkelä for the editing and mixing, Jiffel for the facility, Bill Hare for mixing and mastering, Juuso Westerlund, and shout outs to Gustav Schulman, Maria Schulman and Matti Kari for helping find great locations for filming. I wish you all Happy Holidays and a Happy Roaring 20s!