I am struggeling with the Kinect for Windows SDK to create an application for conducting (with C#).
Basically I need to track one hand (usually the right one) of a conductor and recognize his speed in directing (BPM) to send this value to another application via MIDI.
What I started with is the SkeletonFramesReadyEvent
adding the JointType.HandRight
with a DateTime.Now.Ticks
timestamp to a history List
which is updated and removes the first entry. I keep the history of 60 frames (2 seconds).
I calculate the BPM by searching for the last low and high of the Joint.Position.Y
and then calculate the difference and divide bpm = 60*ticksPerSecond/diff
. However the result is wrong. Is there another way of doing this? What am I missing?
This is what I am using so far:
public int DetectBPM(JointType type)
{
// we have not history yet
if (!HasHistory()) return 0;
// only calculate every second
var detectTime = DateTime.Now.Second;
if (_lastBPM != 0 && _lastBPMDectect == detectTime) return _lastBPM;
// search last high/low boundaries
var index = (int) type;
var list = History[index];
var i = list.Count - 1;
var lastHigh = list[i];
var lastLow = list[i];
// shift to last peak first
while (i > 0 && list[i].Joint.Position.Y >= list[i - 1].Joint.Position.Y) i--;
// find last low
while (i >= 0 && lastLow.Joint.Position.Y >= list[i].Joint.Position.Y) lastLow = list[i--];
// find last high
while (i >= 0 && lastHigh.Joint.Position.Y <= list[i].Joint.Position.Y) lastHigh = list[i--];
var ticks = lastLow.Timestamp - lastHigh.Timestamp;
var elapsedTime = new TimeSpan(ticks);
var bpm = (int) (60000/elapsedTime.TotalMilliseconds);
Console.WriteLine("DEBUG: BPM = " + _lastBPM + ", elapsedMS: " + elapsedTime.TotalMilliseconds);
_lastBPMDectect = detectTime;
_lastBPM = bpm;
return _lastBPM;
}
Math.Abs()
around the difference in the calculation ofticks
(that'll account for the negative values). According to the documentationTimestamp
is in milliseconds, not ticks, so useTimeSpan.FromMilliseconds(ticks)
instead ofnew TimeSpan(ticks)
(probably renameticks
too) – Adallard