pygame.Sound.get_num_channels不准确

4

我正在使用pygame + Twisted。我创建了一个Sound包装类,以下是相关部分:

class Sound(object):
    def __init__(self, sound):
        self.sound = sound

        self._status_task = task.LoopingCall(self._check_status)
        self._status_task.start(0.05)

    def _check_status(self):
        chans = self.sound.get_num_channels()
        if chans > 0:
            logger.debug("'%s' playing on %d channels",
                         self.filename, chans)

    def play(self):
        self.sound.play()

然而,经常发生的情况是,即使声音播放完毕,.get_num_channels() 仍会返回一个正数,例如:

2013-07-08 15:13:30,502-DEBUG-engine.sound - 'sounds/foo.wav' playing on 2 channels
2013-07-08 15:13:30,503-DEBUG-engine.sound - 'sounds/bar.wav' playing on 1 channels
2013-07-08 15:13:30,546-DEBUG-engine.sound - 'sounds/foo.wav' playing on 2 channels
2013-07-08 15:13:30,558-DEBUG-engine.sound - 'sounds/bar.wav' playing on 1 channels
2013-07-08 15:13:30,602-DEBUG-engine.sound - 'sounds/foo.wav' playing on 2 channels

为什么会这样呢?我问这个问题是因为有时候当我告诉它播放声音时,它根本就不播放,我正在努力找出原因。我想了解这个问题可能有助于解决该错误。

对于好奇的人:声音无法播放的原因是我同时运行了两个pygame程序,只有当前聚焦的程序会发出声音。然而,这似乎与这个错误无关。 - Claudiu
我在想这是不是因为样本长度与循环间隔接近,有时它还没有完全播放,循环就开始再次播放它了?哦,如果输出是真实的,那么似乎foo.wav总是在两个通道上。也许foo.wav比循环间隔略长,但bar.wav足够短? - Jean-Paul Calderone
你能发一下你的整个代码吗?我猜测问题可能出在 Pygame 内部事件队列没有被正确更新,导致声音无法播放。请参考 pygame.event.pump - spirulence
声音末端是否有很多杂音? - Luke B
1个回答

0
在我的经验中,get_num_channels() 计算已分配音频的所有通道的数量,即使它们已完成播放。
一种解决方法是去检查这些通道是否仍然“忙碌”。 您可以将您的_check_status方法更改为此,以考虑通道是否处于活动状态:
def _check_status(self):
    chans = self.sound.get_num_channels()
    if chans > 0:
        logger.debug("'%s' assigned to %d channels", self.filename, chans)              
        active_chans = 0
        for i in range(pygame.mixer.get_num_channels()):
            channel = pygame.mixer.Channel(i)
            if channel.get_sound() == self.sound and channel.get_busy():
                active_chans += 1
        logger.debug("'%s' actively playing on %d channels", self.filename, active_chans)

还有两个辅助函数,可能对其他遇到这个问题的人有所帮助:

def get_num_active_channels(sound):
    """
    Returns the number of pygame.mixer.Channel that are actively playing the sound.
    """
    active_channels = 0
    if sound.get_num_channels() > 0:
        for i in range(pygame.mixer.get_num_channels()):
            channel = pygame.mixer.Channel(i)
            if channel.get_sound() == sound and channel.get_busy():
                active_channels += 1
    return active_channels

def get_active_channel(sound):
    """
    Returns the first pygame.mixer.Channel that we find that is actively playing the sound.
    """
    if sound.get_num_channels() > 0:
        for i in range(pygame.mixer.get_num_channels()):
            channel = pygame.mixer.Channel(i)
            if channel.get_sound() == sound and channel.get_busy()
                return channel
    return None

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接