Base Drum Detection Algorithm

Home

I'm a drummer for a band that I'm in with some friends and we wanted a strobe light that would sync with our music while we played for concerts. To build such a device I wrote an algorithm in Rust to run on a Raspberry Pi and detect base drum hits in real time by analyzing audio input. I also included other functionality such as a button triggering mode and a timed strobe.

Base Drum Triggering

In order to detect bass drum hits I used a technique known as onset detection. I chose to use the microphone from my ear-buds because I already had it and it could fit through the hole in the top of my bass drum. I used the ADC from my audio jack to USB-C adapter, which I then adapted to USB-A for input to a Raspberry Pi 1 that I had on hand. After changing the default audio card in the ALSA config file, the Raspberry Pi was able recognise the audio input.

Detecting the bass drum hits was more complicated than expected as the microphone would pick up similar intensities from the different drums, despite being positioned inside the bass drum. Pictured right are the waveforms as seen by the microphone when some of the drums were hit. As can be observed, they have similar amplitudes, so simply writing a program that waits for the RMS audio value to reach a certain threshold would not work. To differentiate between the different drums my onset detection algorithm looked at the ratios between frequencies in the audio input.

My program uses a library called CPAL which takes in audio data in "buffers". It then takes 1024 data-points at a time and performs a Fourier transform on them using the Radix-4 algorithm from the library RustFFT. Because the sample rate is 44.1khz the lowest frequency the program can detect is ~43hz (sampling rate divided by number of samples); there's a trade-off between detecting low frequencies and latency. Next, the program looks at the bins of the FFT from one 1024 data-point "frame" to the next. If the intensity increases this increase is added to the "onset". The program does this over a low frequency range to get the "bass onset" and a high frequency range to get the "treble onset". When the bass drum it hit there will be a large increase in the intensity of very low frequencies but not very much increase in that of high ones. This means that the program can detect bass drum hits by ensuring that the bass onset reaches a certain threshold, and that the bass onset to treble onset ratio is high enough. After tweaking parameters, my program was able to detect very light bass drum hits while never being falsely triggered by any of the other drums, even while other instruments were playing.

Button Triggering and Strobe

I also wanted our singer to be able to trigger the flash lamp by pressing a button when we wanted the flash lamp going, but not necessarily with the bass drum. To do so, I attached a push-button switch (with a resistor) to a handle and connected it to the 3.3V and one of the GPIO pins of the Raspberry Pi. The program I wrote flashed the light when the button was first pressed. The strobe mode for the lamp simply flashed it 5 times per second.

Firing the Lamp

Both the bass drum and button triggered modes include a safety check function in order to prevent the lamp from overheating. It stores a log of times the lamp was fired and each time a button/bass drum hit is detected it checks that the capacitors have had long enough to recharge and that the power rating of the lamp isn't being exceeded over the last "n" flashes.

To fire the lamp a GPIO pin is set to 3.3V to send a signal to the optoisolator for 17ms. This is enough time to ensure that the 1.1V AC signal going to the thyristor will be high enough to trigger it at some point in the cycle. I experimented with using a diode and capacitor to rectify this signal but figured that it was easiest to keep it AC as the increased latency was minimal.

User Interface

For simplicity, I wanted to be able to switch between running these executables using only a keyboard and no monitor. To do so I wrote a fourth program in Rust. When the key "1" is pressed this program would run the bass drum detection program, "2" would run the button program, and "3" would run the strobe. Hitting enter would stop any of the programs. I made it so that the Raspberry Pi would boot into my user on startup, and added the user interface program to my .bashrc file so it would run automatically.