Python 中精确的循环计时

Bas*_*asj 2 python time timer

对于这个项目,我正在设计一个音序器/鼓机,它应该能够以精确的速度发送 MIDI 音符。示例:每 2 秒 16 个音符(即音乐术语中,每小节 16 个 1/16 音符,BPM 120),即每 125 毫秒一个音符。

我在想:

import time

def midi_note_send(...):
    ....

while True:
    midi_note_send(...)
    time.sleep(0.125)
Run Code Online (Sandbox Code Playgroud)

如果我这样做,如何确定它恰好是 125 毫秒?该循环的 1000 次迭代是否存在使用 126 秒而不是 125 秒的风险?如果是这样,如何获得更精确的循环?

最后一点:一台好的鼓机应该能够在 1 小时内保持 120 BPM 的节奏,精度误差 < 1 秒。
使用的平台:Linux + RaspberryPi 但这个问题一般来说是有效的。

Tem*_*olf 6

正如我在这里展示的

\n\n
import time\ndef drummer():\n    counter = 0\n    # time.sleep(time.time() * 8 % 1 / 8) # enable to sync clock for demo\n    while counter < 60 * 8:\n        counter += 1\n        print time.time()\n        time.sleep(.125 - time.time() * 8 % 1 / 8)\n
Run Code Online (Sandbox Code Playgroud)\n\n

该计时器会调整每个节拍并重新排列。

\n\n

而且调整几乎不需要时间:

\n\n
timeit.timeit("time.time() * 8 % 1 / 8", number=1000000)\n0.2493131160736084\n
Run Code Online (Sandbox Code Playgroud)\n\n

这意味着每次执行大约需要 0.25 微秒

\n\n

为了准确性:

\n\n
1488490895.000160\n1488490895.125177\n1488490895.250167\n1488490895.375151\n1488490895.500166\n1488490895.625179\n1488490895.750178\n1488490895.875153\n
Run Code Online (Sandbox Code Playgroud)\n\n

音符之间有约 28 微秒的漂移。在本地运行较长时间会产生约 130\xce\xbcs 的总漂移 (+- 65\xce\xbcs),但是,由于它每个节拍都与时钟同步,因此不会随着时间的推移而偏差。

\n