Cum pot face un metronom precis? (Programare, Python, Python 3.X, Timp, Metronom)

Python a intrebat.

Am încercat să fac un metronom foarte simplu care funcționează la 30 bpm:

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

Apoi, am pornit o aplicație de metronom pe telefon împreună cu semnalul sonor din calculator, iar acesta a devenit mai puțin precis pe măsură ce a trecut timpul. există o altă modalitate de a face „time.sleep()”? Este chiar vinovat „time.sleep()”?

Comentarii

  • Dacă aveți nevoie de un cronometru real, nu vă bazați pe intervalele de somn. Rulați sondajul de intervale și apoi verificați timpul ceasului. M-am lovit de acest lucru în Nodejs zilele trecute, sunt sigur că soluția poate fi adaptată la Python cu un efort minim. stackoverflow.com/questions/49540098/… – în mod eficient: știi ora ceasului când începe cronometrul tău, știi ora ceasului când metronomul tău ar trebui să „ticăie”, așa că rulează pollerul tău mai repede decât ticăie metronomul, și ticăie ori de câte ori valoarea BPM spune că ar trebui. –  > Por Mike „Pomax” Kamermans.
1 răspunsuri
PM 2Ring

Acest lucru este dificil de făcut pe un sistem de operare multitasking: nu este ușor pentru sistem să vă dea exact sleep întârziere pe care o solicitați. Vedeți Cât de precis este time.sleep() de la python? pentru detalii.

Dar ne putem apropia destul de mult prin măsurarea intervalului de timp și ajustarea întârzierii de somn. Python 3.3+ oferă time.perf_counter, care se presupune că este destul de bun la măsurarea intervalelor de timp, deși precizia exactă depinde de sistemul de operare și de hardware-ul dumneavoastră.

Iată un demo simplu care doar tipărește diferența dintre întârzierea solicitată și cea măsurată pentru fiecare ticăit. Ieșirile inițiale sunt un pic neglijente, dar în curând se reglează pentru a oferi ticuri care se află în interval de 10 microsecunde față de intervalul solicitat. Cu toate acestea, redarea unui sunet necesită mai multe resurse de sistem decât imprimarea pe terminal, iar acest lucru poate afecta precizia acestei tehnici. Pentru cele mai bune rezultate, reduceți la minimum sarcina de sarcini pe mașina dumneavoastră, mai ales dacă aceasta este single core.

Am setat întârzierea aici la 0,2 secunde = 300 bpm. Ritmurile de bătăi mai lente pot da mai puțin precizie, deoarece există mai mult timp în timpul fiecărui ciclu de somn pentru ca CPU să efectueze alte sarcini care pot face ca somnul să fie puțin mai lung decât cel solicitat.

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

ieșire tipică

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

Aceste rezultate provin de la o mașină veche cu un singur nucleu de 32 de biți la 2 GHz care rulează Linux, YMMV.

Comentarii

  • Deci, nu există o soluție reală pentru toate vitezele metronomului? Nu pot să trec peste asta? –  > Por Python.
  • @Python Puteți seta BPM-ul la orice doriți, folosind delay = d = 60 / bpm. Erorile vor fi, în general, mici, de cele mai multe ori mai mici de o milisecundă și, de obicei, mai puțin de atât. De exemplu, tocmai am testat-o pe 30 BPM și erorile au fost în mare parte în jurul a 5 microsecunde. Și, din moment ce tind să alterneze între pozitiv & negativ destul de regulat, deriva pe termen lung ar trebui să fie destul de mică. Dar va trebui să îl rulați pe sistemul dvs. la diferite viteze pentru a vedea ce rezultate obțineți. –  > Por PM 2Ring.