如何使用Pygame执行基于时间的音频?

时间:2014-07-27 07:31:15

标签: python audio pygame python-3.3

这是我在StackOverflow上的第一个问题,所以这里是:

编辑:我已经编辑了几次,只是修复了输入错误并更新了代码。即使在对代码添加各种更改之后,问题仍然完全相同。 另外,pygame.mixer.music.fadeout()不是我想要的。此代码也适用于我希望将音乐音量降低到50%,比如暂停游戏或进入谈话场景。

使用Pygame,我正在尝试根据已经过了多长时间来执行音乐音量操作。我已经创建了一些不错的代码,但它并没有按照我的直觉思考。另外,我应该注意到我使用的是从PySDL2中删除的基于组件的EBS系统。以下是EBS模块的链接:https://bitbucket.org/marcusva/py-sdl2/src/02a4bc4f79d9440fe98e372e0ffaadacaefaa5c6/sdl2/ext/ebs.py?at=default

这是我最初的代码块:

import pygame
from pygame.locals import *

# Setup import paths for module.
pkg_dir = os.path.split(os.path.abspath(__file__))[0]
parent_dir, pkg_name = os.path.split(pkg_dir)
sys.path.insert(0, parent_dir)
sys.path.insert(0, os.path.join(parent_dir, "Game"))

import Game
from Porting.sdl2.ext import ebs

pygame.display.quit()
print("Counting down...")
for n in range(5):
    print(str(n + 1))
    pygame.time.delay(1000)
appworld = ebs.World()
audio_system = Game.audio.AudioSystem(44100, -16, 2, 4096)
appworld.add_system(audio_system)
test1 = Game.sprites.AudioSprite(appworld)
test2 = Game.sprites.AudioSprite(appworld)
test1.audio = Game.audio.Audio(database["BGMusic0"], True)
test2.audio = Game.audio.Audio(database["BGMusic1"], True)
game_clock = pygame.time.Clock()
volume_change_clock = pygame.time.Clock()
loop = True
time_passed = 0
while loop:
    game_clock.tick(60)
    appworld.process()
    time_passed += volume_change_clock.tick(60)
    if time_passed > (10 * 1000):
        print(time_passed)
        if not audio_system.music_volume_changed:
            audio_system.set_music_volume(0, True)

我的下一段代码:

import pygame
from Porting.sdl2.ext import ebs
class AudioSystem(ebs.System):
    def __init__(self, frequency, bit_size, channels, buffer):
        super(AudioSystem, self).__init__()
        self.componenttypes = Audio,
        pygame.mixer.init(frequency, bit_size, channels, buffer)
        pygame.mixer.set_num_channels(200)
        self.frequency = frequency
        self.bit_size = bit_size
        self.channels = channels
        self.buffer = buffer
        self.music_volume_change_clock = None
        self.music_volume_changed = False
        self.music_volume_current = 0
        self.music_volume_new = 0
        self.music_fade = False
        self.music_change_speed = 0
        self.time_passed_total = 0
        self.time_passed_remainder = 0

    def process(self, world, componentsets):
        for audio in componentsets:
            if audio.is_music:
                music = pygame.mixer.music
                if not pygame.mixer.music.get_busy():
                    music.load(audio.file)
                    music.play()
                if self.music_volume_changed:
                    self.music_volume_current = music.get_volume() * 100
                    if self.music_volume_current != self.music_volume_new and self.music_fade:
                        time_passed = self.music_volume_change_clock.tick(60)
                        self.time_passed_total += time_passed
                        self.time_passed_total += self.time_passed_remainder
                        self.time_passed_remainder = 0
                        if self.time_passed_total > self.music_change_speed:
                            self.time_passed_remainder = self.time_passed_total % self.music_change_speed
                            volume_change_amount = int(self.time_passed_total / self.music_change_speed)
                            self.time_passed_total = 0
                            if self.music_volume_current > self.music_volume_new:
                                self.music_volume_current -= volume_change_amount
                                music.set_volume(self.music_volume_current / 100)
                            elif self.music_current_volume < self.music_volume_new:
                                self.music_volume_current += volume_change_amount
                                music.set_volume(self.music_volume_current / 100)
                    elif self.music_volume_current != self.music_volume_new:
                        music.set_volume(self.music_volume_current / 100)
                    else:
                        self.music_volume_changed = False
                        self.music_fade = False
            else:
                if not audio.channel:
                    audio.channel = pygame.mixer.find_channel()
                    audio.channel.play()

    def set_music_volume(self, percent, fade = False, change_speed = 50):
        self.music_volume_changed = True
        self.music_volume_new = percent
        self.music_fade = fade
        self.music_change_speed = change_speed
        self.music_volume_change_clock = pygame.time.Clock()

class Audio(object):
    def __init__(self, file, is_music = False):
        self.is_music = is_music
        if self.is_music:
            self.file = file
        else:
            self.channel = None
            self.file = pygame.mixer.Sound(file)

我的测试表明,在我的Game.audio模块中以各种方式操作Clock.tick()的参数会影响音频播放从100下降到0的速度。将其留空会导致它几乎立即停止。在60,它在大约2秒内降到0,这让我感到困惑。在30,在1秒。在5,它下降缓慢,音量似乎永远不会达到0.我想完全从我的游戏帧速率中完全取消音频音量操作,但我不确定如何实现这一点。我希望尽可能避免线程和多处理。

提前致谢! :)

1 个答案:

答案 0 :(得分:0)

Clock.tick()的参数用于调用SDL睡眠函数来限制循环每秒运行的次数。

使用Clock.tick(5)调用它将其限制为每秒五个循环。

我也从未在相同的代码中使用过两个时钟,尤其是多个时钟(所有这些都将分别计算他们的睡眠时间)。而不是考虑使用tick的返回值(自上次调用以来的毫秒数),并使用它来跟踪整个应用程序的时间。

示例:

    timer = 0
    Do things
    timer += main_clock.tick(FPS)