2 回答
TA贡献1725条经验 获得超7个赞
由于需要处理器与其他程序共享自身,因此做任何需要时间精度的事情都非常困难。不幸的是,对于定时关键程序,操作系统可以随时选择切换到另一个进程。这可能意味着它可能要等到明显的延迟后才能返回程序。导入时间后使用time.sleep这是一种尝试平衡哔哔声之间时间的更一致的方法,因为处理器的“理由”减少了。尽管Windows上的睡眠默认粒度为15.6ms,但我认为您无需播放超过64Hz的拍子。看来您正在使用多线程来尝试解决您的问题,但是,线程的python实现有时会强制线程按顺序运行。这将使您从流程中退出的情况变得更加糟糕。
我认为最好的解决方案是以所需的频率生成包含节拍器蜂鸣声的声音数据。然后,您可以以操作系统熟悉的方式播放声音数据。由于系统知道如何以可靠的方式处理声音,因此您的节拍器将开始工作。
令人失望的是,但是计时关键的应用程序非常困难,除非您想弄清正在使用的系统。
TA贡献1835条经验 获得超7个赞
播放声音来模拟普通的节拍器不需要“实时”功能。
看起来您使用Tkinter框架创建了GUI。root.after()允许您延迟调用函数。您可以使用它来实现刻度:
def tick(interval, function, *args):
root.after(interval - timer() % interval, tick, interval, function, *args)
function(*args) # assume it doesn't block
tick()运行function与给定的args每interval毫秒。单个刻度的持续时间受root.after()精度影响,但从长远来看,稳定性仅取决于timer()功能。
这是一个打印一些统计数据(240每分钟心跳数)的脚本:
#!/usr/bin/env python
from __future__ import division, print_function
import sys
from timeit import default_timer
try:
from Tkinter import Tk
except ImportError: # Python 3
from tkinter import Tk
def timer():
return int(default_timer() * 1000 + .5)
def tick(interval, function, *args):
root.after(interval - timer() % interval, tick, interval, function, *args)
function(*args) # assume it doesn't block
def bpm(milliseconds):
"""Beats per minute."""
return 60000 / milliseconds
def print_tempo(last=[timer()], total=[0], count=[0]):
now = timer()
elapsed = now - last[0]
total[0] += elapsed
count[0] += 1
average = total[0] / count[0]
print("{:.1f} BPM, average: {:.0f} BPM, now {}"
.format(bpm(elapsed), bpm(average), now),
end='\r', file=sys.stderr)
last[0] = now
interval = 250 # milliseconds
root = Tk()
root.withdraw() # don't show GUI
root.after(interval - timer() % interval, tick, interval, print_tempo)
root.mainloop()
速度仅拍打一拍:我的机器上为240±1。
添加回答
举报