Использование asyncio для создания базового метронома. У меня проблемы с точностью воспроизведения звука - PullRequest
0 голосов
/ 31 мая 2019

Я не могу получить точность, необходимую для метронома.

Здравствуйте, Я новичок в программировании на Python, хотя у меня есть некоторый опыт работы с Fortran и Matlab. Я хочу создать основной метроном с Python в качестве моего первого проекта. Во-первых, я использовал модули time и winsound. Модуль времени использовался для расчета времени ожидания между звуковыми сигналами, которые воспроизводил модуль winsound. Когда я запускал код и сравнивал его звуковой сигнал с приложением метронома, я понял, что временные интервалы между звуковыми сигналами не были точными. Поэтому я перешел с time.sleep () на asyncio.sleep. На первый взгляд это решило проблему. Поэтому в следующий раз мне пришлось поменять модуль winsound, так как я подумал, что он тоже не точный. Я инициализировал pygame.mixer и импортировал некоторые звуковые файлы wav. И это то, чем я сейчас являюсь.

Является ли проблема pygame.mixer? Есть ли вероятность, что проблема в файлах wav? Вот код:

# Import Pygame for sound playback. Contextlib is used to avoid pygame's welcoming message.
import contextlib
with contextlib.redirect_stdout(None):
    import pygame

# Used asyncio instead of time. Asyncio's sleep funcion is precise where time's sleep function is not.
import asyncio

# Pygame mixer initialize for sound playback.
pygame.mixer.init()
tick1= pygame.mixer.Sound("Metro 1.wav")
tick2= pygame.mixer.Sound("Metro 2.wav")
tick3= pygame.mixer.Sound("Metro 3.wav")

# Basic Metronome script. Bpm is the Beats per minute (Tempo), bpb is the beats per bar (4/4=4, 5/4=5, 7/8=7 etc.)
# and tsound is a variable for the type of tick you want to use in its beat.
async def metro_tic(bpm ,bpb,tsound):
    t=0                     #
    sleep =(60.0 / bpm)     # Converting Bpm to miliseconds.
    counter = 0             # Counter is a variable that indicates at which beat of the bar the metronome is functioning.
    while True:
        if counter>=bpb:           # If the variable counter is bigger or equal (both bpb and counter are integers so
            counter=counter-bpb      # only the equal relation counts) than the beats per bar it restarts to the value 0.
        else:
            if counter % bpb==0:            # If counter is equal to 0 (meaning we are at the first beat of the bar)
                print('1st Tick')           # a unique event occurs (not specified yet!!!).
            if tsound[counter]==1:          # If tsound eg at the second beat (tsound[2]) is equal to 1,
                tick1.play()                # number 1 tick sound will play.
            elif tsound[counter]==2:        # If tsound eg at the second beat (tsound[2]) is equal to 2,
                tick2.play()                # number 2 tick sound will play.
            elif tsound[counter]==3:        # If tsound eg at the second beat (tsound[2]) is equal to 3,
                tick3.play()                # number 3 tick sound will play.
            elif tsound[counter]==0:        # If tsound eg at the second beat (tsound[2]) is equal to 0,
                print ('no tick')           # no tick sound will play.
            counter += 1                    # After each beat counter adds 1 to it's self so as to continue to the next beat
            await asyncio.sleep(sleep)      # Metro_tic function sleeps for the amount of time calculated at sleep 



asyncio.run(metro_tic(80, 4, [1, 2, 2, 2]))
...