Main Archive Specials Wiki | FAQ Links Submit Forum


Beat Detector Class

References : Posted by DSPMaster[at]free[dot]fr

Notes :
This class was designed for a VST plugin. Basically, it's just a 2nd order LP filter, followed by an enveloppe detector (thanks Bram), feeding a Schmitt trigger. The rising edge detector provides a 1-sample pulse each time a beat is detected. Code is self documented...
Note : The class uses a fixed comparison level, you may need to change it.


Code :
// ***** BEATDETECTOR.H *****
#ifndef BeatDetectorH
#define BeatDetectorH

class TBeatDetector
{
private:
float KBeatFilter; // Filter coefficient
float Filter1Out, Filter2Out;
float BeatRelease; // Release time coefficient
float PeakEnv; // Peak enveloppe follower
bool BeatTrigger; // Schmitt trigger output
bool PrevBeatPulse; // Rising edge memory
public:
bool BeatPulse; // Beat detector output

TBeatDetector();
~TBeatDetector();
virtual void setSampleRate(float SampleRate);
virtual void AudioProcess (float input);
};
#endif


// ***** BEATDETECTOR.CPP *****
#include "BeatDetector.h"
#include "math.h"

#define FREQ_LP_BEAT 150.0f // Low Pass filter frequency
#define T_FILTER 1.0f/(2.0f*M_PI*FREQ_LP_BEAT) // Low Pass filter time constant
#define BEAT_RTIME 0.02f // Release time of enveloppe detector in second

TBeatDetector::TBeatDetector()
// Beat detector constructor
{
Filter1Out=0.0;
Filter2Out=0.0;
PeakEnv=0.0;
BeatTrigger=false;
PrevBeatPulse=false;
setSampleRate(44100);
}

TBeatDetector::~TBeatDetector()
{
// Nothing specific to do...
}

void TBeatDetector::setSampleRate (float sampleRate)
// Compute all sample frequency related coeffs
{
KBeatFilter=1.0/(sampleRate*T_FILTER);
BeatRelease=(float)exp(-1.0f/(sampleRate*BEAT_RTIME));
}

void TBeatDetector::AudioProcess (float input)
// Process incoming signal
{
float EnvIn;

// Step 1 : 2nd order low pass filter (made of two 1st order RC filter)
Filter1Out=Filter1Out+(KBeatFilter*(input-Filter1Out));
Filter2Out=Filter2Out+(KBeatFilter*(Filter1Out-Filter2Out));

// Step 2 : peak detector
EnvIn=fabs(Filter2Out);
if (EnvIn>PeakEnv) PeakEnv=EnvIn; // Attack time = 0
else
{
PeakEnv*=BeatRelease;
PeakEnv+=(1.0f-BeatRelease)*EnvIn;
}

// Step 3 : Schmitt trigger
if (!BeatTrigger)
{
if (PeakEnv>0.3) BeatTrigger=true;
}
else
{
if (PeakEnv<0.15) BeatTrigger=false;
}

// Step 4 : rising edge detector
BeatPulse=false;
if ((BeatTrigger)&&(!PrevBeatPulse))
BeatPulse=true;
PrevBeatPulse=BeatTrigger;
}



Comments


Added on : 18/05/05 by thaddy[ AT ]thaddy[ DOT ]com
Comment :
// Nice work!
//Here's a Delphi and freepascal version:            
unit beattrigger;

interface

type
TBeatDetector = class
private
  KBeatFilter,               // Filter coefficient
  Filter1Out,
  Filter2Out,
  BeatRelease,               // Release time coefficient
  PeakEnv:single;            // Peak enveloppe follower
  BeatTrigger,               // Schmitt trigger output
  PrevBeatPulse:Boolean;     // Rising edge memory
public
  BeatPulse:Boolean;            // Beat detector output
  constructor Create;
  procedure setSampleRate(SampleRate:single);
  procedure AudioProcess (input:single);
end;

function fabs(value:single):Single;

implementation


const
FREQ_LP_BEAT = 150.0;                    // Low Pass filter frequency
T_FILTER = 1.0/(2.0 * PI*FREQ_LP_BEAT);  // Low Pass filter time constant
BEAT_RTIME = 0.02;   // Release time of enveloppe detector in second

constructor TBeatDetector.create;
// Beat detector constructor
begin
  inherited;
  Filter1Out:=0.0;
  Filter2Out:=0.0;
  PeakEnv:=0.0;
  BeatTrigger:=false;
  PrevBeatPulse:=false;
  setSampleRate(44100);
end;


procedure TBeatDetector.setSampleRate (sampleRate:single);
// Compute all sample frequency related coeffs
begin
  KBeatFilter:=1.0/(sampleRate*T_FILTER);
  BeatRelease:= exp(-1.0/(sampleRate*BEAT_RTIME));
end;

function fabs(value:single):Single;
asm
fld value
fabs
fwait
end;

procedure  TBeatDetector.AudioProcess (input:single);
var
EnvIn:Single;
// Process incoming signal
begin
  // Step 1 : 2nd order low pass filter (made of two 1st order RC filter)
  Filter1Out:=Filter1Out+(KBeatFilter*(input-Filter1Out));
  Filter2Out:=Filter2Out+(KBeatFilter*(Filter1Out-Filter2Out));
  // Step 2 : peak detector
  EnvIn:=fabs(Filter2Out);
  if EnvIn>PeakEnv then PeakEnv:=EnvIn  // Attack time = 0
  else
  begin
    PeakEnv:=PeakEnv*BeatRelease;
    PeakEnv:=PeakEnv+(1.0-BeatRelease)*EnvIn;
  end;
  // Step 3 : Schmitt trigger
  if not BeatTrigger then
  begin
    if PeakEnv>0.3 then BeatTrigger:=true;
  end
  else
  begin
    if PeakEnv<0.15 then BeatTrigger:=false;
  end;

  // Step 4 : rising edge detector
  BeatPulse:=false;
  if (BeatTrigger = true ) and( not PrevBeatPulse) then
    BeatPulse:=true;
  PrevBeatPulse:=BeatTrigger;
end;

end.




Added on : 21/06/05 by foo[ AT ]bar[ DOT ]baz
Comment :
If you have virtual methods the destructor should be virtual as well as otherwise the destruction of derived objects is undefined.      



Added on : 29/06/05 by thaddy[ AT ]thaddy[ DOT ]com
Comment :
This already - implied - the case in the PAS version. The above comment holds only for the C++ version, but makes sense to me.      



Added on : 01/06/09 by kwolff[ AT ]intra-team[ DOT ]de
Comment :
Can you tell me how to implement the variable bpm, to get the beats per minute?

Thanx,
Kris




Added on : 05/03/10 by ata_n[ AT ]hotmail[ DOT ]com
Comment :
Im having a hard time setting the comparison level. My audio data is signed 16 bit integers, so I have set the levels at (0.3*32768) and (0.15*32768)...
ive tried different levels, nothing responds correctly..
any ideas anyone?


Thanks,
Ata




Added on : 05/07/11 by lindathorn[ AT ]mail15[ DOT ]com
Comment :
Following my own monitoring, thousands of people on our planet receive the <a href="http://bestfinance-blog.com/topics/mortgage-loans">mortgage loans</a> from good creditors. Thus, there is good possibilities to find a auto loan in all countries.



Added on : 09/07/11 by lindathorn[ AT ]mail15[ DOT ]com
Comment :
Some time before, I needed to buy a car for my corporation but I didn't have enough money and couldn't order something. Thank God my father suggested to try to take the loan from reliable creditors. Therefore, I did so and used to be happy with my small business loan.



Added on : 26/08/11 by nyc10003[ AT ]nyc[ DOT ]rr[ DOT ]com
Comment :
Can I use the code on the Schmitt trigger for an iPhone app that I may be selling?  Is there a fee?              



Added on : 26/05/13 by nikolatesla20[ AT ]gmail[ DOT ]com
Comment :
I can't seem to actually get this to work at all...              



Added on : 09/07/14 by sadsakurasad[ AT ]yahoo[ DOT ]com
Comment :
This is really good content, I praise what you've done right here, along with sharing excellent information with great tips. Thank you! http://www.friv3go.com



Added on : 25/09/14 by htmlfriv
Comment :
like my content of the ban, it is very hay and really is meaningful for me
http://www.bestgamesy8.org/  |  y8  |http://www.games2girlsdressup.com/
http://www.kizi100games.info/ Kizi




Add your own comment
Comments are displayed in fixed width, no HTML code allowed!
Email:

Comment:

Are you human?



Site created and maintained by Bram
Graphic design by line.out | Server sponsered by fxpansion