After last weeks mixed success, I started implementing the more advanced techniques Yov408 describes in his article. However, nothing seemed to improve the calculated beats per minute. I was about to go and implement the Fourier Transform, something which I wanted to avoid in order to keep the algorithm zippy. But I went back to the spreadsheet and discovered a much simpler solution.
Download the NetBeans example project
The second sample I tried has about 3 or 4 beats too much. Upon closer inspection of those misses, those are all instances where the energy went above the threshold during for only one sample.
Once I understood the nature of the problem, it was easy to implement a solution that only detects a beat when the energy is high enough for a few more samples. I put this into code and was amazed by the results. Pretty much any song I used resulted in a BPM count withing 5 BPM of the actual count.
The adapted algorithm is:
Every 1024 samples:
- Compute the instant sound energy ‘e’ on the 1024 new sample values taken in (an) and (bn) using the formula (R1)
- Compute the average local energy <E> with (E) sound energy history buffer:

(R3) - Shift the sound energy history buffer (E) of 1 index to the right. We make room for the new energy value and flush the oldest.
- Pile in the new energy value ‘e’ at E[0].
- If ‘e’ > ‘C*<E>’ we detect a possible beat. If a possible beat was not detected in the previous calculation, we start counting, N = 0. Otherwise, N is increased by one.
- If N equals a threshold (3 is a pretty good value), a true beat is detected.
Given the simplicity of the algorithm I think this is an incredible result and good enough to move into the next step of the project: Porting this to small devices.
To be continued …
Download the NetBeans example project
BTW for those following along via e-mail or the RSS feed, come visit the site and let me know what you think of the new logo.
9 Comments
N?ce work. How can we both play the music and calculate instant bpm?
I've put this project on the back burner until I can get my hands on a Droid.
If you want to do real time calculation, you would just calculate the BPM according to the algorithm up until the data you have. Just shift the buffer in accordance to the real time output (you need a powerful enough processor to handle this, give the simplicity, I think that won't be a problem)
To calculate the pitch from ex 128 bpm to 130 bpm, it´s easy.
But i need help writing a java app for mobile device.
My algorithm that works all the time is following [ 100 / (from bpm) 128 x (to bpm) 130 – 100 = 1,5625
exaple 2: 135 bpm to 145 bpm
” 100 / 135 x 145 – 100 = 7,40 ” Help me, anyone?! mail me patrick@spelagenten.se
You have done an excellent job with this and I truly appreciate you sharing the code. When I was reading through the code i noticed that AveragingOutputAudioDevice and FileSampleProcessor were not being used in the code. Are these alternative classes, or have they been deprecated from the project as you’ve progressed along? Thank you!
I am getting an error “Exception in thread “main” java.lang.IndexOutOfBoundsException: Index: 0, Size: 0″ when running the main program. Can someone help me on this?
Hi Julio,
Initially I had a few other modules calculating different characteristics. It’s been a while but I believe that’s what those classes were there for. I left them in since I think they will come in handy in the future.
It’s been a while since I worked in this project though.
I’m not entirely sure. The project does very little error checking. I’m going to guess that it doesn’t find the mp3 file you want to analyze.
If that doesn’t help, can you send the rest of the stack trace?
why are you using array of long in BPM2SampleProcessor ?
I honestly have no idea. At the time, I probably just used it so that I wouldn’t run into the limits of int or something. I’m not sure it matters?
I’ve currently started the project of going over and updated my old blogpost. This will be one of them (I just noticed the formula went missing and the original GameDev article is gone). I can’t promise you anything, but stay tuned (or bug me via the contact form if you want to place this one higher in the queue
)
One Trackback
[...] The last post on my current project already teasered the next step: taking it mobile. Considering the fact that I was programming the algorithm in Java, you might have concluded that it was going to be an Android application. If you did, you’re right. [...]