Python:以设定的 BPM 间隔(<1 秒)播放音频的时间不准确
Python: Inaccurate timing playing audio at a set BPM interval (<1s)
我正在尝试在 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 毫秒重复一次,精度至少为 +/-10 毫秒左右。那不现实吗?如果是这样,请提出替代方案。
当我在我的本地机器上测试你的代码时,睡眠似乎不关心 pygame 线程,所以你的声音会自己重叠。
此外,我认为您应该使用 pygame 自己的计时器来延迟操作。
你能在你的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))
问题原来是使用了过大的块大小,这可能导致 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())
即跟踪 "current time" 并根据经过的时间调整 sleep
s。我在每次睡觉前明确执行 "garbage collect"(即 gc.collect()
)以使事情更具确定性。
我正在尝试在 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 毫秒重复一次,精度至少为 +/-10 毫秒左右。那不现实吗?如果是这样,请提出替代方案。
当我在我的本地机器上测试你的代码时,睡眠似乎不关心 pygame 线程,所以你的声音会自己重叠。
此外,我认为您应该使用 pygame 自己的计时器来延迟操作。
你能在你的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))
问题原来是使用了过大的块大小,这可能导致 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())
即跟踪 "current time" 并根据经过的时间调整 sleep
s。我在每次睡觉前明确执行 "garbage collect"(即 gc.collect()
)以使事情更具确定性。