我该如何在pygame中实现声音的平移?

3

基本上,我想要实现的是在游戏运行时平移声音的方法。我希望根据玩家的位置改变音量(左右)。目前,我有一个简单的代码,我认为这将是一个很好的测试:

pygame.mixer.init()

self.sound = pygame.mixer.Sound("System Of A Down - DDevil #06.mp3")
print("I could get here")
self.music = self.sound.play()

self.music.set_volume(1.0, 0)

首先,我尝试使用pygame.mixer.music进行类似的操作,但我意识到这种方法无法分别更改音量,或者至少我是这么认为的,于是我改用了此处提供的代码。 现在似乎文件无法加载,我猜测这是因为文件太大了,在pygame中无法作为声音处理。有什么方法可以让这个工作吗?


你可能需要寻找另一个库来实现这个。试试 SoundDevice - Inyoung Kim 김인영
谢谢您的建议,但似乎所有这些库对于我想要的速度都太慢了,也许我做错了什么。 - Matheus Fernando
3个回答

5
你可以像这样在频道上进行平移操作:
from os import split, join
import pygame
import pygame.examples.aliens
pygame.init()
# get path to an example punch.wav file that comes with pygame.
sound_path = join(split(pygame.examples.aliens.__file__)[0], 'data', 'punch.wav')
sound = pygame.mixer.Sound(sound_path)
# mixer can mix several sounds together at once.
# Find a free channel to play the sound on.
channel = pygame.mixer.find_channel()
# pan volume full loudness on the left, and silent on right.
channel.set_volume(1.0, 0.0)
channel.play(sound)

https://www.pygame.org/docs/ref/mixer.html#pygame.mixer.Channel


你能解释一下第五行的作用吗? - Matheus Fernando
当然。添加了一些注释,并稍微清理了代码。 - René Dudfield

1

对于这个问题,也许值得考虑使用一个单独的音频库。一般来说,我建议使用PortAudio(它是C语言编写的),但使用由PyAudio提供的其Python绑定。这将使您对确切的音频流有更多的控制。

为了进一步简化此过程,有一个名为PyDub的库,它基于PyAudio构建了高级接口(甚至还具有特定的平移方法!)。


from pydub import AudioSegment
from pydub.playback import play

backgroundMusic = AudioSegment.from_wav("music.wav")

# pan the audio 15% to the right
panned_right = backgroundMusic.pan(+0.15)

# pan the audio 50% to the left
panned_left = backgroundMusic.pan(-0.50)

#Play audio
while True:
    try:
       play(panned_left)
      #play(panned_right)

如果这个过程太慢或者不能提供有效的实时实现,那么我建议你试试PyAudio,因为在这个过程中你也会学到更多关于音频处理方面的知识!
顺便说一句,如果你使用PyAudio,请确保查看回调技术,以便你正在运行的游戏可以使用不同的线程并行运行。

似乎使用pydub时,整个音乐文件都会被加载,然后平移重新计算并创建第二个要播放的文件,但这会消耗很多时间。你知道如何更改系统(Windows或Ubuntu)的音量吗? - Matheus Fernando
根据我的经验,我没有像使用纯PortAudio那样频繁地使用PyDub,但是它的接口似乎是一个不错的起点。在搜索了一番后,我发现了PySoundCard库,它以类似于PyAudio(使用PortAudio)的方式工作,但看起来更加高效(至少初步看来是这样)。如果您查看回调部分,可以看到您可以在Numpy数组中修改音频。也就是说,您应该能够在每个块传输时单独操纵每个音频“列”(值得学习线程技术)。如果可能的话,我建议避免系统音量调节。 - WoodyDev
谢谢你的帮助,我设法找到了问题出在哪里。似乎无法将 .mp3 文件加载到 pygame.mixer.Sound() 中,所以我基本上将文件转换为 .wav 格式。我还会深入研究 PyAudio,因为我对这种声音处理很感兴趣。 - Matheus Fernando

0

这个答案肯定能帮到你。

基本上,你需要获取屏幕宽度,然后根据 player.pos.x / screen_width 来移动左边界,根据 1 - player.pos.y / screen_width 来移动右边界,就像这样:


伪代码:

channel = music.play() # we will pan the music through the use of a channel
screen_width = screen.get_surface().get_width()

[main loop]:
    right = player.pos.x / screen_width
    left =  player.pos.x / screen_width

    channel.set_volume(left, right)

文档:


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