简体   繁体   中英

How can I do a precise metronome?

I tried to do a very simple metronome that is working at 30 bpm:

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

Then, I turned on a metronome app on my phone together with the beep in the computer, and it became less precise as the time went on. Is there another way to do the "time.sleep()"? Is it even the "time.sleep()" guilt?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM