给定两次节拍之间的时间,我怎样才能最好地计算出每分钟的节拍数?

How can I best calculate beats per min, given the time in between two beats?

我正在创建一个应用程序来测试用户可以通过点击、鼠标点击/按钮按下等方式获得多快的节拍。

每次用户点击按钮时,我都会调用这个函数,beat();计算他们当前的 BPM 并用该 BPM 填充图形。我还想在最后计算一个平均值。请参阅下面我当前使用的代码。

我目前遇到的问题是,当用户点击时,BPM 到处都是,有时是一致的,有时是不准确的。查看我的代码让我感到困惑,因为我认为我实际上并没有在这里计算 BPM,或者至少不准确。

我也尝试在新旧 BPM 值之间添加一个 lerp,以平滑仪表,但它似乎没有解决问题。

我在堆栈溢出中发现的最接近的问题是这个问题:Tap BPM code in Processing
但我仍然不确定这是否真的准确计算了用户 BPM。我将不胜感激这里的一些帮助,特别是关于如何仅使用 2 个时间戳(旧节拍和新节拍)计算 BPM 背后的数学解释。

void beat()
{

    if (beat0 == null)
    {
        beat0 = DateTime.Now;
        return;
    }
    else if (beat1 == null)
    {
        beat1 = DateTime.Now;
    }
    else
    {
        beat0 = beat1;
        beat1 = DateTime.Now;
    }

    if (beat0 != null && beat1 != null)
    {
        double delta = (beat1 - beat0).TotalSeconds;
        double bpm = 60 / delta;
        curBpm = (int)bpm;

        if (oldBpm == -1)
        {
            oldBpm = curBpm;
            return;
        }

        lerpBpm = (int)Mathf.Lerp(oldBpm, curBpm, (float)delta);

        bpmText.text = lerpBpm.ToString();
        FillGauge(lerpBpm);
        oldBpm = lerpBpm;
    }
}

我想要这样的东西..

一个数组,例如 5 个样本,以及一个知道哪个数组元素是“当前”的计数器

TimeSpan[] samples = new TimeSpan[5];
int index = 0;

我有一个秒表,运行。这是 .net

的高分辨率计时 class

当用户点击一个按钮时,我会获取秒表读数并将其存储在数组中:

var current = stopwatch.Elapsed;     //you'll see why I store in a temp variable in a moment 
samples[index] = current;

并增加索引,使用模数将其保持在数组边界内(循环数组)

index = (index +1)%samples.Length;

然后我需要查看数组中的最小值和最大值。您可以使用 LINQ min/max,或者可以只使用索引现在指向数组中最旧的项目这一事实..

int oldest = samples[index];

现在,如果您这样做 current - oldest,您将得到采集 5 个样本所花费的时间,除以 5 得到最后 5 个样本中每个样本的平均时间

var ms = (current - oldest).TotalMilliseconds;

如果这是从一个节拍到下一个节拍的时间,您想知道在 60000 毫秒长的时间段内可以容纳多少节拍

var bpm = 60000 / ms;

现在我想剩下的就是检查一下最早的读数是否是 TimeSpan.Zero(表明它从未被设置),这样你就不会在第一个开始计算疯狂的 bpm五次点击