Quick and Dirty, Real-Time BPM Detection

Status
Not open for further replies.

gfvalvo

Well-known member
Hi All.

I know this topic has been discussed multiple times. But, not sure if there was an answer that meets my (simple) needs.

I’m streaming music through a TOSLINK-to-I2S converter and into a T3.2. Looking for a relatively simple way to get the approximate (real-time) BPM.

I understand that this is a deceptively difficult task, and I am not at all an audio guy. The nuances of high-quality audio are wasted on me.

But, that’s also a strength -- I’m not that picky about a solution. “Good Enough” is definitely good enough. I just want someone to look at the display and say “hey, the lights on that Christmas tree are going with the music’s beat”.

While not an audio guy, I am a pretty good coder. So, I’d be happy if someone just suggested an algorithm. Of course, I’m not above using a wheel someone else has already invented.

Thanks.
 
I'd start with a low pass filter. BPMs are in a range between let's say 30 and 240 while the latter is already beyond techno... that corresponds to 0.5 to 4Hz. On the other side, the (lowest) E string of a double bass is around 35Hz. Thus, using a state variable low pass filter with a 6Hz corner frequency and a Q of 0.806 could well separate the beats from the music. Behind this filter, a relatively simple peak or zero-cross detection (both are possible) could give you the desired result.
 
i doubt that this works with classical music (or other without high energy change) for pop or techno it should work.. :)
I hope you tell us the results of your experiments! Sounds interesting.
 
He wanted quick and dirty, he got quick and dirty. :)

The inspiration for that low pass filter approach came to me from my observation of young people in small cars. All you can hear from their music outside the car is that "oompf-oompf-oompf"...
 
Beat is a phenomenon of a signal's envelope.

An envelope follower is usually a very low corner lowpass on a rectified signal.

Scan for crossing from below of an adjustable threshold to detect beat.

Or... you can use the peak or RMS objects from the audio library and poll for large changes. Lowpass filter on the signal first should help.
 
I gets a bit confusing now.. are we talking about beat detection -oompf-oompf-oompf-blinky or bpm=beats per minute (without "ooompf" maybe) ?

A morse-key on a oomph bass box could do the first case... :) or an air-pressure sensor in a door-lock of an ooompf-car ..
 
for the second case you need a sophisticated algorithm, I think... something with auto-correlation ..or even more, deep analysis with ffts and algorithms I don't know the name of :) , and at least some seconds of sound.
 
Low pass to Peak object in Audio Library
... then set output true if peak is greater than threshold variable.

Set the threshold with a sensativity knob that's just a scaled analog read from a potentiometer.

You could also add an adjustment knob for cutoff on the filter.
 
Thanks, I’ll give that a try. So far, I’ve been trying the envelope technique you suggested:

* Rectify (square) the signal using the ‘multiply’ object.

* Lowpass filter to produce the “envelope”.

I keep a running-average of the envelope’s level (exponential moving average) as a “threshold”. When an adjacent pair of samples rises from below this threshold to above it, I declare a “beat” has occurred. I don’t really need to know BPM, just the fact that it has happened.

So far, results have been mediocre. Works well with audio that has say a pronounced drum beat. Others not so much. As I said, I’m not an audio guy. Perhaps I need to fine tune the LPF or set the threshold higher (say 150% of the envelope’s running mean).

I might also play with the FFT technique linked in Reply #6
 
Beat detection really depends from the music. The second movement of Tchaikovsky's 6th symphony has a 5/4 waltz (which is by default 3/4). Thus, main and secondary beats go one against another and even experienced musicians are struggling with that. How then should a poor little Teensy get it sorted? ;)
 
The second movement of Tchaikovsky's 6th symphony has a 5/4 waltz (which is by default 3/4). Thus, main and secondary beats go one against another and even experienced musicians are struggling with that.)
The fact that I really don't know what that means will work to my advantage. I'll simply stop futzing with it once the results are "good enough" (per my standard).
 
This concept is interesting to me. I'm in the pro-audio world and this type of thing is always wanted for so many reasons. If you look at the "DJ Effect Lights" out there such as "American DJ Vertigo" or "Chauvet Derby" those lights have a small microphone in the back and they have a little volume controller. It detects a beat and the programs follow the speed of the detected song. The beat just dictates how fast the program goes.

I believe most of them are programmed to detect a "4 beat measure". First step is to create a beat "tap" method using the button. You should be able to tap the button 4 times and then get a BPM. Once a BPM is detected, it should play a click, click, click, click, ... at the speed of the BPM. This proves you can detect, and then "play back" a BPM (metronome anyone?). This is done on DJ hardware controllers as well as in DJ software. It's manual BPM detection. You can tap 4 times fast to speed up the BPM or 4 times slow to slow it down. Once you mastered the manual tap method using the button you'll have an easier time listening to audio and determining the speed when listening to the microphone. The detector should have a range of between about 50BPM to 150BPM. Anything less than 50 would be doubled, and anything more than 150BPM would be halved.

And you are detecting the BPM but also detecting the "starting beat". I wouldn't recommend detecting every beat. It's better to detect 4 and then play out 4, while re-calibrating.... Detecting one beat at a time leads to a not so great "stuttered playback" where the lights will change only when detected. If you create an ongoing beat which plays even when the BPM isn't perfect you'll have a much more fluid detection. You could also detect volume or the presence of any beat at all. Some lights will go into a smoother mode when it's not hearing any beat. Or it would go black when no beat is detected. Then when the beat drops it goes...

This would be very helpful for recreating your own "DJ Effect light" which many people on this forum are doing. It could also create a nice BPM meter (with LCD to display the current BPM), or a DMX controller with beat detection, or a midi controller... So yeah this code is worthwhile and interesting. You are right to say you'll be hard pressed to be exact, nor does it have to be. I've found most sound active lights are just doing their best and it looks really nice.

*After writing this post I realize I'm suggesting you start with a metronome, then add the audio detection after...

PS - I'm not sure if this would help you at all with your code. This is the foobar BPM analyzer (not real time). It might give you some ideas on how to calculate the BPM.
https://github.com/stengerh/foo_bpm
https://www.foobar2000.org/components/view/foo_bpm
 
You might always study the source code of these libraries to see how they solve the problem and then integrate the corresponding algorithm by rewriting it into your own code.
 
Status
Not open for further replies.
Back
Top