Online Beat tracking using MIDI input

Hi!

I’m interested in real-time beat tracking using MIDI input. Do anyone have experience of how to do this? I’ve tried BeatTrack and BeatTrack2 UGens previously, but they seem to only take audio input.

Thanks in advance!

I’m not sure what you mean by real-time beat tracking, but this set of functions will (after two reference note on events) give you an average BPM if you’re playing quarter notes and you can change how many seconds it takes between beats for it to reset by changing the resetTime. From there, you could send the average to TempoClock, but I don’t know if this is what you want…

(
//forward declare variables

var resetTime = 3;
var numTaps = 0;
var averageBPM = 0;
var calcBPM=0, countTaps=0, resetTaps=0, checkReset=0, process=0, setTimes=0, currentTime=0, prevTime=Main.elapsedTime, calcElapsedTime, elapsedTime=0, times=0;

//MIDI setup
MIDIClient.init;
MIDIIn.connectAll;

times = [];

//define function

checkReset = {|inval|
	resetTime.wait;
	if (inval == numTaps, {numTaps = 0; times = []; averageBPM=nil; "reset".postln;});
};

countTaps = {
	numTaps = numTaps+1;
	// numTaps.postln;
	checkReset.(numTaps);
};

setTimes = {
	if (numTaps < 1, {
		prevTime = Main.elapsedTime;
	});
};

calcElapsedTime = {
	if (numTaps < 1, {
		currentTime = Main.elapsedTime;
		prevTime = nil;
	},
	{
		prevTime = currentTime;
		currentTime = Main.elapsedTime;
		elapsedTime = currentTime - prevTime;
	});
};

calcBPM = {|time|
	var val;
	if (numTaps > 1, {
		times = times.add(time);
		averageBPM = times.mean.reciprocal * 60;
	});
};

process = {
	countTaps.fork;
	setTimes.fork;
	calcElapsedTime.fork;
	calcBPM.(elapsedTime);
	if (averageBPM.notNil.and( averageBPM != 0 )){averageBPM.postln};
};


MIDIdef.noteOn(\on,
	{
		process.fork;
	};
)

// resetTaps = CondVar();
)

If you really want to the that algorithm, you could just turn the midi into sound and beat track it … Kinda lazy, but it’s what I’d do.