SuperCollider CLASSES (extension)

DrumTrack
ExtensionExtension

Crosscorrelation search and drum pattern matching beat tracker

Description

Crosscorrelation search and drum pattern matching beat tracker, as described in:

N Collins. Drum Track: Beat Induction from an Acoustic Drum Kit with Synchronised Scheduling. Proceedings of the International Computer Music Conference (ICMC), Barcelona, Sept 4-9, 2005

(with special reference to the work of Jean Laroche on cross correlation/dynamic programming and Masataka Goto on drum detection and pattern spotting).

This beat tracker was devised for concert applications in tracking an acoustic drum kit, but can also be used on polyphonic audio (for pop signals with drums).

There are four k-rate outputs, being ticks at quarter, eighth and sixteenth level from the determined beat, and the current detected tempo.

Tempi of 90bpm to 190bpm are the allowed options. A tempo weighting prior can be set via a 100 float buffer. The default is a flat profile; the concert allowed for drum and bass speed drumming.

Class Methods

*kr (in, lock: 0, dynleak: 0, tempowt: 0, phasewt: 0, basswt: 0, patternwt: 1, prior, kicksensitivity: 1, snaresensitivity: 1, debugmode: 0)

Arguments:

in

Audio input to track

lock

If this argument is greater than 0.5, the tracker will lock at its current periodicity and continue from the current phase. Whilst it updates the model's phase and period, this is not reflected in the output until lock goes back below 0.5.

You might want to play around with the following parameters, their meaning is explained in the academic paper.

dynleak

Coefficient of leaky integrator in causal dynamic programming routine

tempowt

Weighting for tempo transition cost

phasewt

Weighting for phase transition cost

basswt

Weighting for low frequency evidence

patternwt

Weighting for drum pattern evidence

prior

If a nonnegative integer, denotes a 100 float Buffer where a weighting curve for tempi resides, from 90 bpm to 189 bpm in steps of 1.

kicksensitivity

Multiplier for the kick drum detector's sensitivity. 1.0 is the default, increase for less senstive, decrease for more.

snaresensitivity

Multiplier for the snare drum detector's sensitivity. 1.0 is the default, increase for less senstive, decrease for more.

debugmode

0 for no debug information; 1 prints information on winning drum pattern matches and transitions to new phases/periods. 2 prints whenever a kick or snare is detected to help with fine tuning the kick and snare sensitivity.

Inherited class methods

Instance Methods

Inherited instance methods

Examples

//choose some file you want to track off your hard drive (mono)
b=Buffer.read(s,"/Volumes/data/stevebeattrack/samples/051.wav");

(
a= SynthDef(\help_drumtrack,{arg vol=1.0, beepvol=1.0, lock=0, kick=1, snare=1;
var trackb,trackh,trackq,tempo;
var source, beep;

source= PlayBuf.ar(1,b.bufnum,1.0,1,0,1);

#trackb,trackh,trackq,tempo=DrumTrack.kr(source, lock,kicksensitivity:kick,snaresensitivity:snare,debugmode:2);

beep= SinOsc.ar(1000,0.0,Decay.kr(trackb,0.1));

Out.ar(0,Pan2.ar((vol*source)+(beepvol*beep),0.0));

}).play;
)

a.set(\vol,0.0);

a.set(\beepvol,1.0);

a.set(\kick,0.2);
a.set(\snare,0.7);

a.set(\lock,1); //fix it rigidly from current phase/period solution

a.set(\lock,0); //unfix, back to tracking







//track audio in (try clapping a beat or beatboxing, but allow up to 6 seconds for tracking to begin) and spawning stuff at quarters, eighths and sixteenths

//tempo prior

(
var mean, stddev, constant;
mean=30;
stddev=10;
constant= -0.5/(stddev.squared); //no need for front term on Gaussian since normalizeSum ignores 1/(stddev*(2pi.sqrt));

a = (Array.fill(100,{arg i; exp(((i-mean).squared)*constant)})).normalizeSum; //Gaussian around 120 bpm (=index 30)

Post << a << nl;
b = Buffer.sendCollection(s, a, 1, 0, {arg buf; "finished".postln;});
)
        
(
SynthDef(\help_drumtrack2,{
var trackb,trackh,trackq,tempo;
var source;
var bsound,hsound,qsound;

source= AudioIn.ar(1);

#trackb,trackh,trackq,tempo=DrumTrack.kr(source,prior:(b.bufnum));

bsound= Pan2.ar(LPF.ar(WhiteNoise.ar*(Decay.kr(trackb,0.05)),1000),0.0);

hsound= Pan2.ar(BPF.ar(WhiteNoise.ar*(Decay.kr(trackh,0.05)),3000,0.66),-0.5);

qsound= Pan2.ar(HPF.ar(WhiteNoise.ar*(Decay.kr(trackq,0.05)),5000),0.5);

Out.ar(0, bsound+hsound+qsound);
}).play;
)