我正在努力使用 Kinect for Windows SDK 来创建一个执行应用程序(使用 C#)。
基本上我需要跟踪指挥的一只手(通常是右手)并识别他的指挥速度(BPM),以通过 MIDI 将此值发送到另一个应用程序。
我开始的是SkeletonFramesReadyEvent
将JointType.HandRight
带有DateTime.Now.Ticks
时间戳的添加到List
更新并删除第一个条目的历史记录中。我保留了 60 帧(2 秒)的历史记录。
我通过搜索最后一个低点和高点来计算 BPM,Joint.Position.Y
然后计算差异并除以bpm = 60*ticksPerSecond/diff
。然而结果是错误的。还有另一种方法吗?我错过了什么?
这是我目前使用的:
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;
}