This is difficult to do on a multitasking operating system: it's not easy for the system to give you the exact sleep
delay that you request. See How accurate is python's time.sleep()? for details.
But we can get fairly close by measuring the time span and adjusting the sleep delay. Python 3.3+ provides time.perf_counter
, which is supposed to be pretty good at measuring time intervals, although the exact precision depends on your OS and hardware.
Here's a simple demo that just prints the difference between the requested and the measured time delay for each tick. The initial outputs are a bit sloppy, but it soon settles down to giving ticks that are within 10 microseconds of the requested interval. However, playing a sound takes more system resources than printing to the terminal, and that may impact the precision of this technique. For best results, minimize the task load on your machine, especially if it's single core.
I've set the delay here to 0.2 seconds = 300 bpm. Slower beat rates may give less precision because there's more time during each sleep cycle for the CPU to do other tasks that may cause the sleep to be a little longer than requested.
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
typical output
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
These results are from an old single core 32 bit 2GHz machine running Linux, YMMV.