I love it when the opportunity to combine music and coding comes together. I've worked on a few personal projects related to music, from making music with network traffic to an auto-accompaniment system for electronic drums. More recently, my wonderful wife gave me a beautiful, programmable music box for my birthday. You punch out music notes on a card and crank it through the music box to play a tune.
The music box came with several card sheets around 70cm (27in) long. The card sheets are printed with a grid system so you can measure the time domain and know what note you are selecting. However, I was not sure of my ability to punch blindly—and I am also at heart a little impatient. Sorry. I know, I know, good things come to those who wait, but if I can wait a little less, what's the harm, right?
So I came up with a crazy idea. Instead of having to measure all this stuff and having those crazy, crazy moments when I punch the wrong place and the entire song is ruined, what if I could make things a little less risky? What if could I pull in a good old computation device to help things along a little? What if my little computation device could draw all the dots I needed to punch on the card?
I started thinking about the requirements for what would become Punchbox, a simple-to-use music box card creator. What did I want this software to do? The music box can't play every note—it plays only the notes in a certain key. Of course, the great thing about music is that it can be transposed into any key. So, software that would automatically transpose a song into the best key would be great too. I'd also want it to be accurate—with sharp lines. So it would have to be a vector-based image.
And how would I program the notes into it? Given that some notes may have to be altered to create a new arrangement for a piece, what's the best way to edit them and quickly hear the changes? MIDI seems an obvious choice. It would allow me to quickly change the notes and hear immediate feedback by playing the MIDI through a synthesizer before I print it.
Unfortunately, the music box's cardstock is too thick to fit through my printer, so I decided to print the music on paper, attach it to the card, use the paper to guide my card punches, then remove the paper from the card.
Developing the tool
I program in Python, so I settled on Mido for the MIDI library, because it has the functionality I needed. I also selected Svgwrite for my SVG vector drawing library and PyYAML for the configuration. From the outset, I decided I wanted to make a tool anyone could use, so I picked Click as the command-line toolkit.
As I developed the tool, I realized many other configuration options that would be useful to people. I added the ability to define multiple music boxes, including the note pitch (the physical distance between the triggers), the note collision distance (how long it takes before a note can be triggered again), the available notes (in terms of their MIDI note value), and the ability to reverse the note order (right to left or left to right).
Using printer paper presented another problem. The strip going through the music box can sometimes be several meters long, but my printer prints only up to A4 (27.9cm, close to letter size). I decided to paginate the strips—but pagination requires a way to align the strips. So I added markers to the page. The system correctly identifies how many "staves" can fit on the page and paginates accordingly.
I added a divisor to enable scaling the tune in time (making it faster or slower), margins for the paper, marker sizes (for aligning the strips), and a font size (for numbering the strips and adding the filename).
One of my favorite features is auto-transposition. It takes the notes, runs them through a check to see how many are represented on the music box, and runs through a range of transpositions to see if it can find a perfect one (where all the notes are represented). If it can't find a perfect transposition, it picks the best one. When I print the page, it highlights in red any notes that won't fit. This allows me to inspect the sheet and cross-reference it with the MIDI in something like Rosegarden to delete or move notes.
Testing it out
It took me about a year of using the tool to add all these features. But perhaps the best moment was when I put the first sheet through my music box. I didn't run any tests on it until I printed and punched my first strip using Punchbox.
That first time almost brought tears to my eyes. Mozart, sweetly, gently playing on the most perfect little music box. Perfectly! No errors in timing or pitch. Thank you, open source—without Mido, Svgwrite, PyYAML, and Click, this project wouldn't have been possible.