如何制作精确的节拍器?

时间:2018-07-17 20:27:06

标签: python python-3.x time metronome

我试图做一个非常简单的节拍器,它以30 bpm的速度工作:

While True:
    winsound.Beep(1000, 200)
    time.sleep(2 - 0.2)

然后,我同时打开手机上的节拍器应用程序和计算机中的蜂鸣声,随着时间的流逝,它变得越来越不精确。 还有另一种方法可以执行“ time.sleep()”吗?甚至是“ time.sleep()”的内gui吗?

1 个答案:

答案 0 :(得分:3)

在多任务操作系统上很难做到这一点:要给系统精确的sleep延迟并不容易。有关详情,请参见How accurate is python's time.sleep()?

但是,通过测量时间跨度并调整睡眠延迟,我们可以相当接近。 Python 3.3+提供了time.perf_counter,尽管确切的精度取决于您的操作系统和硬件,但是它可以很好地测量时间间隔。

这是一个简单的演示,仅显示每个刻度的请求延迟和测量延迟之间的差异。初始输出有些草率,但很快就稳定下来,使滴答声落在请求间隔的10微秒内。但是,播放声音比打印到终端需要更多的系统资源,这可能会影响该技术的精度。为了获得最佳结果,请最小化计算机上的任务负载,尤其是在单核计算机上。

我将延迟设置为0.2秒= 300 bpm。较慢的节拍速率可能会导致 精度降低,因为在每个睡眠周期中,CPU都有更多时间执行其他任务,这可能会导致睡眠时间比请求的时间长一点。

from time import sleep, perf_counter

delay = d = 0.2
print(60 / delay, 'bpm')
prev = perf_counter()
for i in range(20):
    sleep(d)
    t = perf_counter()
    delta = t - prev - delay
    print('{:+.9f}'.format(delta))
    d -= delta
    prev = t

典型输出

300.0 bpm
+0.000262488
+0.000151862
-0.000019085
-0.000011358
+0.000023078
-0.000015817
-0.000004357
+0.000009283
-0.000012252
+0.000020515
-0.000009061
+0.000003249
-0.000011482
+0.000029230
+0.000001554
-0.000023614
-0.000003286
+0.000000127
-0.000003732
+0.000016311

这些结果来自运行Linux的旧单核32位2GHz计算机YMMV。