Easy BPM Calculation in Java

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.

downloadDownload 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 …

downloadDownload 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.

Image credit

This entry was posted in Java and JavaScript. Bookmark the permalink. Both comments and trackbacks are currently closed.

9 Comments

  1. Extreme
    Posted December 17, 2009 at 11:38 pm | Permalink

    N?ce work. How can we both play the music and calculate instant bpm?

  2. Posted January 11, 2010 at 10:30 am | Permalink

    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)

  3. Pp
    Posted September 16, 2010 at 11:54 am | Permalink

    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

  4. Julio_a_jimenez
    Posted November 29, 2010 at 6:37 pm | Permalink

    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!

  5. Gish
    Posted November 30, 2010 at 8:15 am | Permalink

    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?

  6. Posted December 1, 2010 at 1:58 pm | Permalink

    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.

  7. Posted December 1, 2010 at 1:59 pm | Permalink

    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?

  8. Sunch1ld
    Posted May 11, 2011 at 1:33 pm | Permalink

    why are you using array of long in BPM2SampleProcessor ?

  9. Posted May 17, 2011 at 12:37 pm | Permalink

    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

  1. By Android, No-cost Development Platform – Streamhead on January 27, 2010 at 11:29 pm

    [...] 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. [...]

  • Feedback or questions? Contact me right away.

    Comments have been disabled on my posts. Not because I don't want to hear from you, but because they were adding very little to the conversation (most of them were spam anyway). I do listen to you and try to keep as much posts as possible up-to-date and error free. So if you have a question, if something isn't working the way you hoped or you have general feedback, please use the contact form below. I guarantee an answer to every honest question or remark.
  • Get in touch
    1. (required)
    2. (valid email required)
     

    cforms contact form by delicious:days