An adventure indeed
The first couple weeks of my coding project had me write exactly zero lines of code. It was not exactly fun or exciting, but it taught me some of the most valuable lessons of my computer science journey so far.
A what misadventure?
The underlying technology behind my project is MIDI, or Musical Instrument Digital Interface. I have used MIDI for years to record, mix, produce, and transcribe music, but that was always as a musician. The extent of my MIDI knowledge was that I could plug an instrument into a computer and they would magically communicate. While my view back then wasn’t exactly nuanced, my intuition had me on the right path. MIDI is simply a system to send messages following a specific protocol. The message from any machine – sequencer software, a keyboard, or a standalone computer – are all about the same. A MIDI message essentially says,
- Through this port (a digital highway for our message)
- And this channel (a lane on our digital highway)
- Send this patch (a number corresponding to a sound)
And that’s about it.
A port has 16 MIDI channels on it, which can all transmit messages at the same time. The industry standard is to have drum sounds be on channel 10 (although some systems see this at channel 9, depending on if they start at channel 1 or channel 0). Your computer is ready to send all sorts of these messages – stopping and starting notes on a whim. This isn’t really much use without something ready to receive them though!
Midi alone wasn’t enough
For my project, the MIDI messages are generated by rtmidi (a C++ module, wrapped by a python module, which is wrapped by a python module, that I am wrapping with my own python module – this topic deserves its own post). These messages need to be played by a software synthesizer (softsynth), software dedicated to getting the MIDI messages out of your speakers. I went with an older but reliable softsynth, TiMidity++ .
Bonus for those familiar with softsynths – I noticed the ‘standard’ for UNIX systems was Fluidsynth (and by extension Qsynth, the GUI for it). However, I found TiMidity to be much simpler to use. I think for a beginner like myself, the barebones-ness of TiMidity allowed me to do exactly what I wanted (getting sound out of my machine). As I was troubleshooting ALSA, JACK, and Pulseaudio – it was nice getting TiMidity to work with every combination of dependencies I ran across. Also, I found p-midi, a really simple command line tool for using a softsynth.
I quickly found out that a softsynth was not enough for sound to come out of my machine. Every operating system requires sound drivers that need to play nice with your virtual instrument. On linux systems (more on that below), there are 3 big players – ALSA, JACK, and pulseaudio.
Sound Dependencies for Linux
Advanced Linux Sound Architecture (ALSA) is a software framework and part of the Linux kernel that provides an application programming interface (API) for sound card device drivers. It makes all the sound come out of the machine, and so anything that you want to make sound ultimately needs to interact with ALSA at some point.
JACK (JACK Audio Connection Kit) is an API for audio applications to communicate with each other and with audio hardware. JACK is being used in implemented in my project for the case that I have real time access to the kernel, meaning I want to send MIDI messages to my machine in a very fancy way. It is also available on other UNIX systems, so Mac people can use this tool as well!
Pulseaudio is the newer kid on the block, and is meant to be a high level API for ALSA. Allegedly it is an easier way for regular users to control their system sound. I’m not sure if this was actually achieved (my struggles might have made me a bit biased). All I know is that every help section / chat room / StackOverflow post I visited had a post for “Have you tried killing pulseaudio?”
While it was frustrating, I really enjoyed learning about and implementing these technologies. Trying to get these to work with mido, rtmidi, and other python modules was the type of techy learning experience I was looking for. My big takeaways were:
Virtual Environments Are Important
In tandem with this project, I started my deep-dive journey into Linux systems with Fedora 27 as the host OS on my computer. I did not realize when I installed Fedora that everybody and their mom develops for Debian/Ubuntu instead.
Originally I was very stubborn about doing all of my work in Fedora. I like the minimal version of GNOME it runs out of the box, and to be honest I just really like the color blue. However as I was testing out different modules and back-ends to implement in my project, it became very clear that I would have to interrupt my beautiful work environment with an ungodly amount of purple from time to time.
Being new to Linux is fun, but getting dependent software to run on both Fedora and Ubuntu was just too much fun (I can’t tell if I’m being sarcastic or not). They are different enough to require a fair amount of googling, but similar enough for to develop a common troubleshooting process between them.
My stubbornness for using Fedora ultimately taught me why VMs are important. While I have used virtual machines for schoolwork for quite some time, I had never really internalized why using them is an import tool for development.
Why are virtual environments so important? Coding/software projects are very creative processes. You need room to play around, to experiment, and to explore the limitless tools available. That means you need room to make very big mistakes with very little consequences. A virtual environment allows you to make mistakes and simply start fresh if everything breaks. For example, if you delete your desktop environment, it is much less stressful to reboot a VM than to spend two days worrying about retrieving your homework that you didn’t back up anywhere.
Bonus: Let me tell ya – you truly haven’t lived until you accidentally disable the GUI interface on your machine. The adrenaline of not being able to access my LaTex homework files was enough to recommend it to anyone. If you ever need to launch GNOME from the shell using Fedora, run
`systemctl start gdm`
Reading Documentation is Important
By the time I chose what existing modules I wanted to implement in my project, understood MIDI at an acceptable level, and fixed the limitless issues I ran into, I probably read 300 pages of documentation. Was that more masochism than necessary? Probably. Am I glad I did it? Absolutely. The more I read the faster I got at reading, and consequently began to solve problems much more quickly. Better yet, I began solving problems on school projects at a noticeably faster pace.
Creating Documentation is Very Important
Besides learning that documentation is your friend, I learned you need to be your own friend. Document everything. Yes – everything. Document your issues, what you tried to solve them with, and of course how you fixed them. Future you will thank you.
There were many times early in my project where my patient mentor asked me what I had tried to solve my problem… I had tried so many things I couldn’t really remember. Not only was that not helpful to him – it was a waste of my own time. Currently, I have the entire process for getting sound dependencies documented on my GitHub. An originally week-long process only took 15 minutes when I inevitably needed to reinstall everything.
Give your code and yourself some space to improve
Following my last point, it is just as important to revisit your own documentation periodically. As I write this post, I recognize my own documentation and installation guide is still a little hard to follow. If you can’t clearly follow your explanation, how is anyone else supposed to?
I am a firm believer that clean code leads to a clean write up, and more importantly vice-versa. If you can explain code concisely in plain English, then I would bet your code is quite clear too.
When does that clarity happen though? I have learned it is definitely not on the first try. Projects need space. Code needs a fresh pair of eyes on it. Give yourself time to revisit your work and make it better. As a grad student, I know the familiar feeling of getting work done right before a deadline. However, anyone’s first draft is not as good as they would like it to be.
As for my code, it is a few drafts in and certainly not clear yet. I can’t wait to walk you through it in my next post.