The BeatDetect class allows you to analyze an audio stream for beats (rhythmic onsets). Beat Detection Algorithms by Frédéric Patin describes beats in the following way:
The human listening system determines the rhythm of music by detecting a pseudo-periodical succession of beats. The signal which is intercepted by the ear contains a certain energy, this energy is converted into an electrical signal which the brain interprets. Obviously, The more energy the sound transports, the louder the sound will seem. But a sound will be heard as a beat only if his energy is largely superior to the sound’s energy history, that is to say if the brain detects a brutal variation in sound energy. Therefore if the ear intercepts a monotonous sound with sometimes big energy peaks it will detect beats, however, if you play a continuous loud sound you will not perceive any beats. Thus, the beats are big variations of sound energy.
The two algorithms in BeatDetect are based on two algorithms described in that paper.
Beat Detection
// Create a BeatDetect object that is in SOUND_ENERGY mode. BeatDetect() // Create a BeatDetect object that is in FREQ_ENERGY mode // and expects a sample buffer with the requested attributes. BeatDetect(int timeSize, float sampleRate) // Analyze the samples in ab. void detect(AudioBuffer ab) // Constant used to request frequency energy tracking mode. static int FREQ_ENERGY // Constant used to request sound energy tracking mode. static int SOUND_ENERY // Set the detection mode to use void detectMode(int algo) // Sets the sensitivity of the algorithm (in milliseconds) void setSensitivity(int s)
To use BeatDetect, inside of draw() you must call the detect method, passing the AudioBuffer you want to analyze. BeatDetect has two modes: sound energy tracking and frequency energy tracking. In sound energy mode, the level of the buffer, as returned by level(), is used as the instant energy in each frame. Beats, then, are spikes in this value, relative to the previous one second of sound. In frequency energy mode, the same process is used but instead of tracking the level of the buffer, an FFT is used to obtain a spectrum, which is then divided into average bands, and each of these bands is tracked individually. The result is that it is possible to track sounds that occur in different parts of the frequency spectrum independently (like the kick drum and snare drum). The setSensitivity method is used to put a damper on the analysis. If you set the sensitivity to 200, every time the algorithm detects a beat it will wait 200 milliseconds before testing for a beat again, returning false in the meantime. You can use this to dampen the algorithm if it is giving too many false-positives. The default value is 10, which is essentially no damping. If you try to set the sensitivity to a negative value, an error will be reported and it will be set to 10 instead.
Sound Energy Mode
// returns true when a beat has been detected. boolean isOnset()
In sound energy mode you use isOnset() to query the algorithm. This will return true if a “beat” has been detected. But remember, because it is simply the level of the audio being analyzed, this merely represents significant spikes in the level. If you are analyzing dance music, this will track the kick drum pretty well.
Code Sample (online example)
/** * This sketch demonstrates how to use the BeatDetect object song SOUND_ENERGY mode.<br /> * You must call <code>detect</code> every frame and then you can use <code>isOnset</code> * to track the beat of the music. * <p> * This sketch plays an entire song, so it may be a little slow to load. */ import ddf.minim.*; import ddf.minim.analysis.*; Minim minim; AudioPlayer song; BeatDetect beat; float eRadius; void setup() { size(200, 200, P3D); minim = new Minim(this); song = minim.loadFile("marcus_kellis_theme.mp3", 2048); song.play(); // a beat detection object song SOUND_ENERGY mode with a sensitivity of 10 milliseconds beat = new BeatDetect(); ellipseMode(CENTER_RADIUS); eRadius = 20; } void draw() { background(0); beat.detect(song.mix); float a = map(eRadius, 20, 80, 60, 255); fill(60, 255, 0, a); if ( beat.isOnset() ) eRadius = 80; ellipse(width/2, height/2, eRadius, eRadius); eRadius *= 0.95; if ( eRadius < 20 ) eRadius = 20; } void stop() { // always close Minim audio classes when you are finished with them song.close(); // always stop Minim before exiting minim.stop(); super.stop(); }
Frequency Energy Mode
// returns true when a beat has been // detected in the ith frequency band. boolean isOnset(int i) // returns true if a beat corresponding to the // frequency range of a kick drum has been detected. boolean isKick() // returns true if a beat corresponding to the // frequency range of a snare drum has been detected. boolean isSnare() // returns true if a beat corresponding to the // frequency range of a hi hat has been detected. boolean isHat() // returns true if at least threshold bands of the // bands included in the range [low, high] have registered a beat. boolean isRange(int low, int high, int threshold)
In frequency energy mode you use the above methods to query particular frequency bands or ranges of frequency bands. It should be noted that isKick(), isSnare(), and isHat() merely call isRange() with values determined by testing the algorithm against music with a heavy beat and they may not be appropriate for all kinds of music. If you find they are performing poorly with your music, you should use isRange() directly to locate the bands that provide the most meaningful information for you. The example below also demonstrates how you might write an AudioListener class that catches buffers for you so that you don’t have to call the detect method in draw().
Code Sample (online example)
/** * This sketch demonstrates how to use the BeatDetect object in FREQ_ENERGY mode.<br /> * You can use <code>isKick</code>, <code>isSnare</code>, </code>isHat</code>, <code>isRange</code>, * and <code>isOnset(int)</code> to track whatever kind of beats you are looking to track, they will report * true or false based on the state of the analysis. To "tick" the analysis you must call <code>detect</code> * with successive buffers of audio. You can do this inside of <code>draw</code>, but you are likely to miss some * audio buffers if you do this. The sketch implements an <code>AudioListener</code> called <code>BeatListener</code> * so that it can call <code>detect</code> on every buffer of audio processed by the system without repeating a buffer * or missing one. * <p> * This sketch plays an entire song so it may be a little slow to load. */ import ddf.minim.*; import ddf.minim.analysis.*; Minim minim; AudioPlayer song; BeatDetect beat; BeatListener bl; float kickSize, snareSize, hatSize; void setup() { size(512, 200, P3D); minim = new Minim(this); song = minim.loadFile("marcus_kellis_theme.mp3", 2048); song.play(); // a beat detection object that is FREQ_ENERGY mode that // expects buffers the length of song's buffer size // and samples captured at songs's sample rate beat = new BeatDetect(song.bufferSize(), song.sampleRate()); // set the sensitivity to 300 milliseconds // After a beat has been detected, the algorithm will wait for 300 milliseconds // before allowing another beat to be reported. You can use this to dampen the // algorithm if it is giving too many false-positives. The default value is 10, // which is essentially no damping. If you try to set the sensitivity to a negative value, // an error will be reported and it will be set to 10 instead. beat.setSensitivity(300); kickSize = snareSize = hatSize = 16; // make a new beat listener, so that we won't miss any buffers for the analysis bl = new BeatListener(beat, song); textFont(createFont("Helvetica", 16)); textAlign(CENTER); } void draw() { background(0); fill(255); if ( beat.isKick() ) kickSize = 32; if ( beat.isSnare() ) snareSize = 32; if ( beat.isHat() ) hatSize = 32; textSize(kickSize); text("KICK", width/4, height/2); textSize(snareSize); text("SNARE", width/2, height/2); textSize(hatSize); text("HAT", 3*width/4, height/2); kickSize = constrain(kickSize * 0.95, 16, 32); snareSize = constrain(snareSize * 0.95, 16, 32); hatSize = constrain(hatSize * 0.95, 16, 32); } void stop() { // always close Minim audio classes when you are finished with them song.close(); // always stop Minim before exiting minim.stop(); // this closes the sketch super.stop(); }
-
Hmmm, getting: Cannot find a class or type named “BeatListener” in the example and my own code.
-
I am not clear on how the isOnset(int i) method works.
What is the maximum number of frequency bands? I assumed that the maximum is 32 since the paper you cite uses 32.
-
I’m getting “Cannot find a class or type named “BeatListener” in the example and my own code too.
Can anyone help?!
-
Hi, i am trying to use the beatdetection with an audio live input from the linein. The line in Example works fine, and the Beat detection with an mp3 file works as well. But is it possible to use the beat detection with the linein? I cant get it to work.
-
Pingback from XX :: Heart Skipped a Beat « mediadump on April 18, 2010 at 2:03 pm
-
cerr,
I just wrote beat detection that uses the the line-in as input. The hardest part i found was configing my computers settings to get the right input, but if you got line-in example to work then you should be fine. Here’s parts of my code that my help:
minim = new Minim(this);
in = minim.getLineIn();
//bpf filter helps beatDetection algo when bass beat detection is only //wanted
bpf = new BandPass(55, 12, in.sampleRate());
in.addEffect(bpf);
beat.detect(in.mix);
if ( beat.isOnset() )
{
//what you want it to do
}hope this helps.
-
forgot 2 line safter in.addEffect(bpf);
add in:beat = new BeatDetect();
beat.setSensitivity(275); -
Pingback from kellective» Sound visualisation on June 29, 2010 at 5:25 pm
-
“It should be noted that isKick(), isSnare(), and isHat() merely call isRange() with values determined by testing the algorithm against music with a heavy beat and they may not be appropriate for all kinds of music.”
What exactly would those values be?

15 comments
Comments feed for this article
Trackback link: http://code.compartmental.net/tools/minim/manual-beatdetect/trackback/