Временные проблемы в скрипте метронома в Python (с использованием Pygame)

Я пытаюсь написать сценарий метронома, который дает мне звуковую обратную связь, а также отправляет MIDI-сообщения на синтезатор. я используюPython 2.7.5+ а такжеPygame 1.9.1.release на Linux Mint 16. Я в порядке с MIDI-частью. Что меня беспокоит, так это время.

Прежде всего, вот в основном то, что я делаю:

import time
import pygame.mixer

pygame.mixer.init()
sound = pygame.mixer.Sound('click.wav')

interval = 0.5 #should be equivalent to 120 bpm

t0 = time.time()

while True: #infinite loop, use keyboard interrupt Ctrl-C
    if time.time() - t0 >= interval:
        sound.play()
        t0 = time.time()

Тем не менее, это довольно нестабильно и невозможно играть на инструменте.

Я также посмотрел вtime.clock():

import time
import pygame.mixer

pygame.mixer.init()
sound = pygame.mixer.Sound('click.wav')

interval = 0.5 #should be equivalent to 120 bpm

t0 = time.clock()

while True:
    if time.clock() - t0 >= interval:
        sound.play()
        t0 = time.clock()

...так же какpygame.time.Clock()конкретноpygame.time.Clock.tick_busy_loop(), который предположительно обеспечивает лучшую точность, потребляя больше ресурсов процессора:

import pygame.time
import pygame.mixer

pygame.mixer.init()
#pygame.time has no init function

sound = pygame.mixer.Sound('click.wav')
clock = pygame.time.Clock()

interval = 0.5 #should be equivalent to 120 bpm

time_passed = 0
clock.tick_busy_loop()

while True: #infinite loop, use keyboard interrupt Ctrl-C
    time_passed += clock.tick_busy_loop()
    if time_passed >= interval:
        sound.play()
        time_passed = 0

Все из которых привели к тем же проблемам. Хотя, мне кажется, когда я попробовал эти минимальные примеры,pygame.time Решение было очень стабильным. Проблема здесь в том, что в моем реальном скрипте я делаю некоторые вычисления (например, увеличивая счетчики и отправляя MIDI-сообщения) в пределахwhile цикл, который, кажется, влияет на время, которое занимает цикл, и щелчок начинает заикаться и спотыкаться.

я смотрел наэтот ответ, но я не совсем понял идею файлов миди. Может ли это помочь здесь? Некоторое объяснение было бы наиболее полезным.

Более того, я пытался поставить

import os
os.nice(-19)

в начале, чтобы получить более высокий приоритет процесса, но никаких улучшений не было заметно.

Интересно, как мне добиться стабильного метронома, как это делают обычные DAW, такие как Cubase, Ableton и Logic. Я читал о подходе к генерации или предварительной записи аудиосэмплов рассматриваемого темпа и цепочке этих сэмплов для достижения более высокой точности, но я действительно хотел бы избежать этого подхода, поскольку он кажется очень трудоемким.

Есть ли какой-нибудь умный способ, которым я могу использовать стабильнуюpygame.time вариант и делать обработку в другом месте?

Если это имеет какое-либо применение: вот фактическоеwhile цикл я бегу:

bpm = 80.0
beats_in_one_second = bpm/60.0
midi_send_interval = beats_in_one_second/24.0 #MIDI convention

playing = True
player.write_short(250) #start
frame_count = 0
quarter_count = 0
time_0 = time.time()

while playing:
    if time.time() - time_0 >= midi_send_interval:
        player.write_short(248) #clock tick
        time_0 = time.time()
        frame_count += 1
        if frame_count == 24:
            sound.play()
            quarter_count += 1
            frame_count = 0
            if quarter_count == 16:
                playing = False

player.write_short(252) #stop

Проблема заключается в том, что стандарт MIDI требует 24 сообщения на четвертную ноту, что значительно увеличивает потребность в точности.

Ответы на вопрос(0)

Ваш ответ на вопрос