question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Beat detection and Onset detection

See original GitHub issue

I’ve been experimenting with beat detection and onset detection lately and I’ve come up with two class based on the getEnergy method, the results are pretty encouraging even if it’s pretty basic.

It may be a nice feature to add to the library. Let me know if you have feedback !

Here’s an example using those, you’ll need p5.dom :


var file ='GotanProject_Epoca.mp3'


var source_file; // sound file
var src_length; // hold its duration

var fft;

var pg; // to draw waveform

var playing = false;
var button;

// detectors
var onsetLow,beatLow;
var onsetLowMid,beatLowMid;
var onsetMid, beatMid;



function preload(){
    source_file = loadSound(file); // preload the sound
}

function setup() {
  createCanvas(windowWidth, 250);
  textAlign(CENTER);

  src_length = source_file.duration();
  source_file.playMode('restart'); 
  println("source duration: " +src_length);

  // draw the waveform to an off-screen graphic
  var peaks = source_file.getPeaks(); // get an array of peaks
  pg = createGraphics(width,150);
  pg.background(100);
  pg.translate(0,75);
  pg.noFill();
  pg.stroke(0);
  for (var i = 0 ; i < peaks.length ; i++){
        var x = map(i,0,peaks.length,0,width);
        var y = map(peaks[i],0,1,0,150);
          pg.line(x,0,x,y);
          pg.line(x,0,x,-y);
   }


    // FFT
   fft = new p5.FFT();

   // instanciation of onset and beat detection from fft
   // low band : 40Hz-120Hz
   onsetLow = new OnsetDetect(40,120,"bass",0.025);
   beatLow = new BeatDetect(40,120,"bass",0.7);
   // lowMid band : 140Hz-400Hz
   onsetLowMid = new OnsetDetect(140,400,"lowMid",0.025);
   beatLowMid = new BeatDetect(140,400,"lowMid",0.7);
   // mid band : 400Hz-2.6kHz
   onsetMid = new OnsetDetect(400,2600,"Mid",0.025);
   beatMid = new BeatDetect(400,2600,"Mid",0.7);


    // gui
   button = createButton('play');
   button.position(3, 3);
   button.mousePressed(play);
}


function draw() {
    background(180);

    image(pg,0,100); // display our waveform representation

     // draw playhead position 
    fill(255,255,180,150);
    noStroke();
    rect(map(source_file.currentTime(),0,src_length,0,windowWidth),100,3,150);
    //display current time
    text("current time: "+nfc(source_file.currentTime(),1)+" s",60,50);

    // we need to call fft.analyse() before the update functions of our class
    // this is because we use the getEnergy method inside our class.
    var spectrum = fft.analyze();  

        // display and update our detector objects
    text("onset detection",350,15);
    text("amplitude treshold",750,15);

    onsetLow.display(250,50);
    onsetLow.update(fft);

    beatLow.display(650,50);
    beatLow.update(fft);

    onsetLowMid.display(350,50);
    onsetLowMid.update(fft);

    beatLowMid.display(750,50);
    beatLowMid.update(fft);

    onsetMid.display(450,50);
    onsetMid.update(fft);

    beatMid.display(850,50);
    beatMid.update(fft);

    if (source_file.currentTime()>=src_length-0.05){
        source_file.pause();
    }

}

function mouseClicked(){
    if(mouseY>100 && mouseY<350){       
        var playpos = constrain(map(mouseX,0,windowWidth,0,src_length),0,src_length);   
        source_file.play(); 
        source_file.play(0,1,1,playpos,src_length); 
        playing = true;
        button.html('pause');       
    }   
    return false;//callback for p5js
}

function keyTyped(){
    if (key == ' '){
        play();
    }
    return false; // callback for p5js
}

function play(){
    if(playing){
        source_file.pause();
        button.html('play');
        playing = false;
    }
    else{
        source_file.play();
        button.html('pause');
        playing = true;
    }   
}


function OnsetDetect(f1,f2,str,thresh){
    this.isDetected = false;
    this.f1=f1;
    this.f2=f2;
    this.str = str;
    this.treshold = thresh;
    this.energy = 0;
    this.penergy =0;
    this.siz = 10;
    this.sensitivity = 500;
}

OnsetDetect.prototype.display = function(x,y) {

    if(this.isDetected == true){
        this.siz = lerp(this.siz,40,0.99);
    }
    else if (this.isDetected == false){
        this.siz = lerp(this.siz,15,0.99);
    }
    fill(255,0,0);
    ellipse(x,y,this.siz,this.siz);
    fill(0);
    text(this.str,x,y);
    text("( "+this.f1+" - "+this.f2+"Hz )",x,y+10);
}

OnsetDetect.prototype.update = function(fftObject) {
    this.energy = fftObject.getEnergy(this.f1,this.f2)/255;

    if(this.isDetected == false){
        if (this.energy-this.penergy > this.treshold){
            this.isDetected = true;
            var self = this;
            setTimeout(function () {
                self.isDetected = false;
            },this.sensitivity);
        }
    }

    this.penergy = this.energy;

}


function BeatDetect(f1,f2,str,thresh){
    this.isDetected = false;
    this.f1=f1;
    this.f2=f2;
    this.str = str;
    this.treshold = thresh;
    this.energy = 0;

    this.siz = 10;
    this.sensitivity = 500;
}

BeatDetect.prototype.display = function(x,y) {

    if(this.isDetected == true){
        this.siz = lerp(this.siz,40,0.99);
    }
    else if (this.isDetected == false){
        this.siz = lerp(this.siz,15,0.99);
    }
    fill(255,0,0);
    ellipse(x,y,this.siz,this.siz);
    fill(0);
    text(this.str,x,y);
    text("( "+this.f1+" - "+this.f2+"Hz )",x,y+10);
}

BeatDetect.prototype.update = function(fftObject) {
    this.energy = fftObject.getEnergy(this.f1,this.f2)/255;

    if(this.isDetected == false){
        if (this.energy > this.treshold){
            this.isDetected = true;
            var self = this;
            setTimeout(function () {
                self.isDetected = false;
            },this.sensitivity);
        }
    }   
}

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:2
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
therewasaguycommented, May 28, 2015

@b2renger’s offlinePeakDetection example allows you to get peaks from a soundfile above a certain threshold, a sort of beat detection with a good guess at the tempo. This would be a great feature to add to the p5.SoundFile class.

But there is already a method p5.SoundFile.getPeaks(). It returns an array of peaks useful for displaying the waveform.

Should we change the name of that method to distinguish it from the new Peaks functionality that looks for peaks above a certain threshold?

0reactions
SKempincommented, Jan 14, 2019

@b2renger @therewasaguy

I’ve just found this post and wondered if you could assist with a project I am trying to make. I wish to detect audio peaks from an mp3 file, log the timings and then replace these peaks with a repeat mp3 sample (for a click track).

I’ve detailed this here on stack overflow.

Do you think this is possible? The peak detection seems to be possile with P5 (I’m yet to try) but I’m not sure if the rest of the task is too complex for JS?

Any input would be hugley appreciated, there still seems to be a lack of info on the web audio api!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Comparison of the onset and beat positions. - ResearchGate
Beat detection systems are widely used in the music information retrieval (MIR) research field for the computation of tempo and beat time positions...
Read more >
Intro MIR, Rhythm Analysis, Onset Detection - Computer Science
Onset Detection. Next Time: Beat Detection. Tempo Estimation. Higher-level Rhythmic Patterns. Wayne Snyder. Computer Science Department. Boston University ...
Read more >
On Musical Onset Detection via the S-Transform - arXiv
Abstract—Musical onset detection is a key component in any beat tracking system. Existing onset detection methods are based on temporal/spectral analysis, ...
Read more >
Beat detection and BPM tempo estimation - Essentia
In this tutorial, we will show how to perform automatic beat detection (beat tracking) and tempo (BPM) estimation using different algorithms in Essentia....
Read more >
Lecture 10: Beat Tracking - Electrical Engineering @Columbia
Other outputs tempo time signature metrical level(s). 4. Onset Event detection. Beat marking. Musical knowledge. Audio. Beat times etc.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found