troydenton.ca

Yep, I'm on the internet

Drum Machine pt3

Feb 25, 2026

Update: part 4 is now available

I am now playing in a (proto-)band, and we need a drummer! Drummers are hard to find, though. Instead of meeting people, I'll just go back to inventing stuff. My original foot-operated drum machine is a good start (previous post here), but in this case I don't want to punch in patterns while performing. This would drive the audience and bandmates insane. I only need to play back pre-made drum tracks, and Hydrogen is really good at playing back pre-made drum tracks, so let's let Hydrogen worry about it.

Playing pre-made mp3 files would be an easier approach, but I have ambitions to implement tap-tempo and bar looping controls. Also, it turns out Hydrogen is relatively easy to automate as a system service.

New Hardware

This device needs to be portable and self-contained - continuing the theme of using stuff I already have, I dug up an old bluetooth speaker that has both a USB power output and an aux in. There's a very audible ground loop/DC path issue when powering the raspi from the same speaker it's playing on - you can hear a buzzy white noise that seems to correlate to CPU load. I've not yet figured out how to spin that as a feature, so I've ordered a ground loop decoupling thing that hopefully fixes it.


Soon there will be a 20x2 character LCD to display track names and other drum machine stuff (below). This is much better than a 1.6" LCD screen. I definitely did not initially order a tiny 1.6" screen by mistake. Until the large, brilliantly selected LCD screen arrives, my software uses espeak to read out track names. Its got a grating robot voice that pairs well with my "audible CPU load" feature.



New Software

Hydrogen has a utility called h2cli that's perfect for playing files without needing a GUI, X session, etc. Hydrogen supports OSC, so I can trigger OSC packets to control Hydrogen with the foot switches. MIDI could also do this, but OSC is simpler because the commands are very program-specific, e.g. /Hydrogen/PLAY. The MIDI equivalent would involve mapping configurations and channels and all the usual MIDI-isms that manifest when you're trying to play a song from your dreams before you forget it. I was able to get OSC working very quickly with the osc++ library. I especially like that the compile instructions "just worked" on a raspi.

Hydrogen needs to run as soon as the machine finishes booting, so I have that rigged up with a basic systemd service. Specifically, this needs to be run as a systemd user service so that it can access the audio subsystem.

Sending an OSC message to load a song shortly after Hydrogen starts would cause it to segfault, but compiling the latest Hydrogen fixed the issue (previously I was using the repo version). Note, cross-compiling for the raspi can be done on a mac with a docker image, this is much faster. Also note that this is for a 32bit OS:


docker run -it --platform linux/arm/v7 debian:bookworm bash
apt update
apt install -y \
qtbase5-dev qttools5-dev qttools5-dev-tools \
libqt5svg5-dev libqt5xmlpatterns5-dev libqwt-qt5-dev \
git build-essential cmake \
libasound2-dev libjack-jackd2-dev libpulse-dev \
libarchive-dev libsndfile1-dev liblrdf-dev \
liblo-dev libcppunit-dev

git clone https://github.com/hydrogen/hydrogen

cd hydrogen
mkdir build && cd build
cmake ..
make
		

Compiling a newer Hydrogen also magically fixed an audio system race condition that I was previously fixing with a systemd service startup delay:

ExecStartPre=sleep 3

Footswitch Daemon

I was able to re-use my previous drum machine footswitch code to make a footswitch service (fsw) whose main job is reading/debouncing the switch inputs, and sending OSC messages to Hydrogen. With Play/Pause, Stop, Next and Prev track buttons, it's already useful enough to practice with.

There isn't a feedback mechanism to detect when an OSC message has been received correctly. Also, the software needs to tell Hydrogen to load the correct song from the filesystem as soon as Hydrogen starts up. fsw and Hydrogen are completely different processes, so some hackery is needed to passively detect this. The solution I settled on is that fsw determines when Hydrogen is done initializing by watching the pulseaudio client connections. When it sees a "hydrogen" entry, it assumes that Hydrogen is ready to accept OSC messages, and sends the initial "open file" message.

File management

I configured a SMB mount and Avahi so that the raspi pops up on my network as a storage device, because this was the laziest thing I could think of. I just save my Hydrogen projects to this SMB share, and then the raspi h2cli process can play them. There is a slight issue where Hydrogen likes to save sample filepaths as absolute (which doesnt match between my laptop filesystem and the raspi filesystem, and I don't want them to), so I wrote a script that fixes .h2song files to use relative filepath names.

What's next?