给定两次节拍之间的时间,我怎样才能最好地计算出每分钟的节拍数?
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五次点击
我正在创建一个应用程序来测试用户可以通过点击、鼠标点击/按钮按下等方式获得多快的节拍。
每次用户点击按钮时,我都会调用这个函数,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五次点击