Getting Python to Play the Piano

Getting Python to Play the Piano

During a recent visit to Costco, the kids and I walked past the KAWAI pianos on roadshow display. We were admiring one of the models that was fully acoustic on the instrument side, but had some embedded electronics and firmware that automated music playing by mechanically actuating the keys.

The nice sales gentleman made his pitch that it’s value in entertaining without requiring an actual piano player. The model on display was $18,999. Considering that I look like a broke college kid most days and our cart contained other low-cost items, I’m hoping the sales gent was being somewhat joking in a deadpan manner and not expecting us to actually place an order on the spot. Plus, I had earlier remarked to my daughter that the price of the piano was just as much as my daily driver sedan.

But it got me to recall that our more modest digital piano is equipped with a USB (USB to Host) port. I was able to confirm after quick documentation review that the USB port presents itself as a MIDI device. I found a USB A/B cable and attached it to the nearby Linux laptop. The OS detected it just fine without requiring any additional drivers or manual kernel module loading.

To anyone at Yamaha reading this, THANK YOU for building devices with standard interfaces without requiring proprietary software or connectivity hardware. For that, you rock.

I spent the next few days downloading MIDI files of various popular music arranged by random folks, and piped them to the piano for play-by-instrument using Rosegarden, which is a music composing and editing program. How well a song performs depends on the arrangement, and the nature of the song’s genre contributes as well. (popular 90s era Latin Pop/Dance sound amazing)

For those unfamiliar: compared to a sound file (.wav) that contains a pulse-code sequence to represent a audio signal, a MIDI file is essentially a sequence of instructions to command an instrument device (physical, or software emulation) to play notes/sounds with prescribed voice and other parameters as well as set instrument controls.

But in my quest for semi-unattended playback, I wanted something that I could just load a playlist and go. I didn’t find such a program, so I went ahead and drafted up a Python script.

The relatively basic script scans the directory for MIDI files into an array, randomly sorts the array, and then calls ‘aplaymidi’ program that comes with Linux with the MIDI port number and file name to play. It features some filename character escaping and very little robust error case handling. But it does catch CTRL+C to gracefully (as best it can) quit out of the loop.

The script runs on the laptop as expected. But because it’s Linux + Python, it also runs on a Raspberry Pi.

I had a moment of pause wondering if the plug-and-play would indeed work on the Pi since it’s ARM based vs. x86/x64, but it was for not because it detected just fine.

Here’s the script running on the Pi, invoked from an SSH terminal shell, since I’m running the pi headless (no monitor or keyboard/mouse attached)

It is truly amazing that I can attach a $35 computer and “upgrade” a lower cost instrument with feature(s) found on models costing hundreds or thousands more!

With the GPIO pins on the RPi, I could certainly attach some hardware buttons and handle events for Play/Stop, FF, and Prev. –For another time, or I’ll leave it as an exercise for you the reader.

Addendum: As with most software projects, the same objective could have been accomplished with other solutions (in this case: shell script, perl, etc) but 1) I wanted to expand my python-fu, and 2) Python is the cool language/tool of this writing. Not that I’d universally suggest everyone to chase every fad and trend, it does help to keep up with available options and general marketshare. If given the chance to work on a lower risk project, I do encourage you to try out and evaluate new or new-to-you tools to solve the problem rather than always using your go-to choices.

Leave a Reply

Your email address will not be published. Required fields are marked *