python - pygame.mixer.Sound.play 是不规则的,尽管是定期触发的

标签 python audio pygame

我目前尝试每隔 x 毫秒重复一次声音 - 其中 x 取决于我通过套接字接收的 UDP 数据包 - 我决定为此使用 pygame。我用这个 SO 答案每隔 x 毫秒重复一次:https://stackoverflow.com/a/18954902/3475778

但现在我遇到了问题,声音播放非常不规则,并做了一个问题仍然存在的最小工作示例:

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 从脚本中录制的波形:

enter image description here

您会看到,出于某种原因,某些样本的播放时间比其他样本长。对于我想要构建的某种节拍器来说不是很好。

编辑更新: 不是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、Python 3.5 64 位(Anaconda)和全新安装的 pygame 下。

最佳答案

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

如果只有少数几个有效区间,可能最容易 存储专用声音文件并加载合适的文件。

否则,pygame.sndarray模块提供访问 一个numpy原始声音数据的数组,这使得它成为可能 动态生成所需长度的声音对象:

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),这种方法应该有很好的机会进行准确的播放。

关于python - pygame.mixer.Sound.play 是不规则的,尽管是定期触发的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41321052/

相关文章:

python - 如何使用python显示弹丸的轨迹?

python - 如何让屏幕忽略某些图像的背景颜色?

python - 运算符python参数

python - 仅捕获特定属性上的 AttributeError

python - Django子目录查看并导入__init__.py中的所有文件

python regex unicode - 从 utf-8 文件中提取数据

android - 如何在 Android Studio 上集成外部 SDK?

swift - 音频流格式和数据类型与 Core Audio 的混淆

python - 如何在 python pygame 中减少掩码碰撞检测的延迟

javascript - 如何解决 audio.play() 的问题?