Python:以设定的BPM间隔(<1s)播放音频的时间安排不正确

时间:2019-01-17 13:21:13

标签: python raspberry-pi pygame timing pyaudio

我正在尝试在Raspberry Pi上制作一个非常简单的节拍器,该Raspberry Pi会按设定的时间间隔播放.wav文件,但是时间上听上不准确。 我真的不知道为什么,python的时间模块不准确吗?

我认为处理音频的代码不是瓶颈,因为如果我将其放入没有计时器的循环中,它将始终发出嘎嘎声。 使用下面的简单代码,声音将在节拍上播放几次,然后一遍一遍地随机关闭一个节拍。

import pygame
from time import sleep

pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.mixer.init()
pygame.init()

BPM = 160
sound = pygame.mixer.Sound('sounds/hihat1.wav')


while True:
    sound.play()
    sleep(60/BPM)

我希望使声音每X毫秒重复一次,精度至少为+/- 10ms左右。那不现实吗?如果是这样,请提出一个替代方案。

2 个答案:

答案 0 :(得分:3)

事实证明,问题是使用了太大的块,这可能导致pygame延迟播放声音,因为之前的块已经排队。我的第一个建议是,我希望OP的代码会随着时间的推移而缓慢漂移,这表明这样的做法会更好:

import pygame
from time import time, sleep
import gc

pygame.mixer.pre_init(44100, -16, 2, 256)
pygame.mixer.init()
pygame.init()

BPM = 160
DELTA = 60/BPM

sound = pygame.mixer.Sound('sounds/hihat1.wav')
goal = time()

while True:
    print(time() - goal)
    sound.play()
    goal += DELTA
    gc.collect()
    sleep(goal - time())

即跟踪“当前时间”,并根据经过的时间调整sleep。我会在每次睡觉之前明确执行“垃圾收集”(即gc.collect()),以使事情更具确定性。

答案 1 :(得分:1)

当我在本地计算机上测试您的代码时,睡眠似乎并不在乎pygame线程,因此您的声音会相互重叠。

此外,我认为您应该使用pygames自己的计时器来延迟动作。

您可以在py上尝试以下代码吗?

import pygame

pygame.mixer.pre_init(44100, -16, 2, 2048)
pygame.mixer.init()
pygame.init()

BPM = 160
sound = pygame.mixer.Sound('sounds/hihat1.wav')

while True:
    sound.play()
    pygame.time.delay(int(sound.get_length()*1000))
    pygame.time.delay(int(60/BPM*1000))