Python pygame.mixer.Sound.play虽然定期开火,但不规则

Python pygame.mixer.Sound.play虽然定期开火,但不规则,python,audio,pygame,Python,Audio,Pygame,我现在试着每x毫秒重复一次声音——x依赖于我通过套接字接收的UDP数据包——我决定使用pygame。我用这个答案每隔x毫秒重复一次: 但现在我遇到了一个问题,声音播放得非常不规则,并且在问题持续存在的情况下,这是一个最小的工作示例: import pygame from pygame.locals import * pygame.mixer.init() sound = pygame.mixer.Sound('sound.wav') def play_sound(): sound.s

我现在试着每x毫秒重复一次声音——x依赖于我通过套接字接收的UDP数据包——我决定使用pygame。我用这个答案每隔x毫秒重复一次:

但现在我遇到了一个问题,声音播放得非常不规则,并且在问题持续存在的情况下,这是一个最小的工作示例:

import pygame
from pygame.locals import *

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

def play_sound():
    sound.stop()
    sound.play()

pygame.init()
clock = pygame.time.Clock()

pygame.time.set_timer(USEREVENT+1, 200)

while True:
    # clock.tick(30)
    for event in pygame.event.get():
        if event.type == USEREVENT+1:
            play_sound()
以下是我通过Audacity从脚本中记录的波形:

您可以看到,由于某些原因,某些示例的播放时间比其他示例长。对于我想要建造的节拍器来说不是很好

编辑更新: 这不是pygame.time.set_timer的问题,因为此代码无法解决问题,也不依赖pygame.time.set_timer:

import pygame
from datetime import datetime

d = datetime.now()

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

pygame.init()

while True:
    if (datetime.now() - d).total_seconds() > 0.2:
        sound.play()
        d = datetime.now()

他也有同样的问题。Ubuntu 16.04、Python3.5 64位(Anaconda)和新安装的pygame也存在这个问题。

这里有一个替代方法的想法。 如果目标是定期播放声音, 如果您(动态)将声音填充到所需的间隔长度,可能会获得更好的效果, 然后简单地循环它

如果只有少数几个有效间隔,则可能最容易 存储专用的声音文件并加载相应的文件

否则,模块将提供对 原始声音数据的数组,这使它成为可能 要动态生成所需长度的声音对象,请执行以下操作:

import pygame
import numpy


# Helper function
def getResizedSound(sound, seconds):

    frequency, bits, channels = pygame.mixer.get_init()

    # Determine silence value
    silence = 0 if bits < 0 else (2**bits / 2) - 1

    # Get raw sample array of original sound
    oldArray = pygame.sndarray.array(sound)

    # Create silent sample array with desired length
    newSampleCount = int(seconds * frequency)
    newShape = (newSampleCount,) + oldArray.shape[1:]
    newArray = numpy.full(newShape, silence, dtype=oldArray.dtype)

    # Copy original sound to the beginning of the
    # silent array, clipping the sound if it is longer
    newArray[:oldArray.shape[0]] = oldArray[:newArray.shape[0]]

    return pygame.mixer.Sound(newArray)


pygame.mixer.init()
pygame.init()

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

resizedSound = getResizedSound(sound, 0.2)
resizedSound.play(loops=-1)

while True:
    pass
导入pygame
进口numpy
#辅助函数
def getResizedSound(声音,秒):
频率、位、通道=pygame.mixer.get_init()
#确定静默值
如果位小于0,则静音=0,否则(2**位/2)-1
#获取原始声音的原始样本数组
oldArray=pygame.sndarray.array(声音)
#创建具有所需长度的静默样本数组
newSampleCount=int(秒*频率)
newShape=(newSampleCount,)+oldArray.shape[1:]
newArray=numpy.full(newShape,silence,dtype=oldArray.dtype)
#将原始声音复制到音频的开头
#无声阵列,如果声音较长,则将其剪裁
newArray[:oldArray.shape[0]=oldArray[:newArray.shape[0]]
return pygame.mixer.Sound(新数组)
pygame.mixer.init()
pygame.init()
sound=pygame.mixer.sound('sound.wav'))
resizedSound=getResizedSound(声音,0.2)
resizedSound.play(循环=-1)
尽管如此:
通过

仅使用pygame(和numpy),这种方法应该有很好的机会实现精确播放。

对我来说,如果我这样做了,效果会更好:

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

在任何pygame
init
函数之前。

好的,您应该尝试使用另一种方式加载声音:

pygame.mixer.music.load(file=file_directory str)
要播放声音,请使用:

pygame.mixer.music.play(loops=*optional* int, start=*optional* float)
您的代码可能如下所示:

import pygame

pygame.init()
pygame.mixer.init()

sound = pygame.mixer.music.load('sound.wav')
def playSound():
    sound.pause()
    sound.play()

while True:
    pass

对我来说,这样做效果更好,但我使用的是python 3.7.2。我不了解Python3.5,但3.5和3.7.2之间没有太多区别。那应该行

现在不是在我的电脑上,但我猜如果pygame的计时器是建立在SDL的计时器上的,那么它的分辨率就不是很高。尝试使用python
time
模块,并在while循环中查询
time.time()
,比较之前和当前的时间,直到x ms过去。感谢您的回复,我也想到了这一点。我将在pygame存储库上提出一个问题。这并不能解决问题,请参阅上面的更新。我将
print()
放在
play\u sound
中,而对于我来说,此函数在正确的时间执行,但混音器在运行音乐时出现问题。据我所知,混音器在分开的线程中运行声音,可能它与线程通信有问题。问题不是声音延迟,问题是如果我每200毫秒发出一个声音,它会工作10次,但第11次需要450毫秒才能听到。现在,我已经将常规定时内容的播放移到simpleaudio,直到我在PyGame中对此进行了修复。