某种节拍器逻辑不准确- c#



我正试图实现某种节拍器(tap tempo)逻辑,即每次点击一个键,计算每次点击之间的间隔,测量平均BPM(每分钟跳动数)

例如,如果我每秒钟点击一个键,我期望BPM为60。

我引入了一些代码来使用点击,我注意到一些延迟,平均是62,

我认为我的手动点击是不对的,所以我引入了一个Timer对象它会"点击"每一秒,但我的速度是62,而不是60

为什么?怎样才能更准确呢?

下面是我的代码:

对不起,这是意大利面,我试着只是为了好玩

public class Program
{
static Stopwatch sw = new Stopwatch();
static List<double> nums = new List<double>();
private static void TimerOnElapsed(object sender, ElapsedEventArgs e)
{
EvaluateTime(sw, nums);
sw.Restart();
}
// Driver program
public static void Main()
{

Console.WriteLine("App is ready");
Timer timer = new Timer();
timer.Interval = 1000;
timer.Elapsed += TimerOnElapsed;
timer.AutoReset = true;
sw.Restart();
timer.Start();
while (true)
{
Console.WriteLine(sw.Elapsed.TotalSeconds);
var x = Console.ReadKey();
if (x.Key != ConsoleKey.B)
{
EvaluateTime(sw, nums);
}
sw.Restart();
if (x.Key == ConsoleKey.S)
{
return;
}
}
}

private static void EvaluateTime(Stopwatch sw, List<double> nums)
{
nums.Add(sw.Elapsed.TotalSeconds);
Console.Clear();
Console.WriteLine($"Average: {Math.Round(60 / (nums.Sum() / nums.Count), 2)}");
}
}

我发现重新启动秒表的开销是造成延迟的原因,

我宁愿使用秒表的时间并计算每次点击之间的间隔

通过检查elapsed seconds minus the sum of all previous elements

最后的代码看起来像这样:

public class Program
{
static readonly Stopwatch sw = new Stopwatch();
static readonly List<double> nums = new List<double>();
// Driver program
public static void Main()
{
Console.WriteLine("App is ready");
while (true)
{
Console.WriteLine(sw.Elapsed.TotalSeconds);
var x = Console.ReadKey();
if (!sw.IsRunning) sw.Start();
else EvaluateTime(sw, nums);
switch (x.Key)
{
case ConsoleKey.S:
return;
case ConsoleKey.R:
sw.Reset();
nums.Clear();
Console.WriteLine("waiting for input");
break;
}
}
}
private static void EvaluateTime(Stopwatch sw, List<double> nums)
{
Console.WriteLine(
$"{Math.Round(sw.Elapsed.TotalSeconds, 2)} - {Math.Round(nums.Sum(), 2)} = {Math.Round(sw.Elapsed.TotalSeconds, 2) - Math.Round(nums.Sum(), 2)}");
nums.Add(Math.Round(sw.Elapsed.TotalSeconds - nums.Sum(), 2));
Console.WriteLine($"The Average Is ====> {Math.Round(60 / (nums.Sum() / nums.Count), 2)}");
}

我尝试再次使用计时器,现在结果更加一致:

App is ready
0
1 - 0 = 1
The Average Is ====> 60
2 - 1 = 1
The Average Is ====> 60
3 - 2 = 1
The Average Is ====> 60
4 - 3 = 1
The Average Is ====> 60
5 - 4 = 1
The Average Is ====> 60
6 - 5 = 1
The Average Is ====> 60
6.99 - 6 = 0.9900000000000002
The Average Is ====> 60.09
8.01 - 6.99 = 1.0199999999999996 // my guess for this inconsitency is the increasing size of the sum calculation, but this is a small difference
The Average Is ====> 59.93
8.99 - 8.01 = 0.9800000000000004
The Average Is ====> 60.07

最新更新