声音(Sound)
开源的Panda3D使用一个商业声音库FMOD,但如果你的程序不用于商业目的,可以免费使用FMOD。
FMOD是一个强大的跨平台声音引擎,支持多种声音文件——MP3、WAV、AIFF、MIDI、MOD、WMA、OGG Vorbis。详情见http://www.fmod.org。
如果不想用FMOD,在panda的bin文件夹下删除fmod.dll和libfmod_audio.dll文件即可,这样Panda就不会发出任何声音了。但你可以使用另外的声音库,如Pygame或PyOpenAL。
载入、播放声音和音乐(Loading and Playing Sounds and Music)
结构
Panda3D声音系统把声音分成两种——音效( Sound Effect)和音乐(Music)。这种分组方式只为方便程序员的工作,因为Panda3D对2种声音分别处理。它们的区别稍后介绍。
基础
载入声音
我们通过Loader类载入声音。(不提倡通过“base builtin”来载入,它只用于兼容旧版本),在常规的Panda3D环境下,当你如下导入DirectStart时,loader就是一个builtin:
import direct.directbase.DirectStart
载入声音需要提供声音的路径,如下:
mySound1 = loader.loadSfx("SoundFile.wav")
这句代码将返回一个AudioSound类对象。声音文件的扩展名是必要的。
播放声音
mySound.play()
停止播放
mySound.stop()
查询声音状态
mySound.status()
如果该声音当前没有在播放,status()返回1,如果正在播放返回2。
音量
音量大小从0到1线性增长:
mySound.setVolume(0.5)
平衡
可以改变声音的平衡,设置的值在-1.0到1.0之间,-1.0只有左声道,1.0为右声道:
mySound.setBalance(-0.5)
注意!!!
如果在交互提示符下运行Panda,必须在播放一个声音之后用Update()命令。
base.sfxManagerList[n].update()
因为每一帧都会调用Update()命令来重置声道,在交互模式下Panda停止了帧刷新,所以不会自动运行。
操控声音(Manipulating Sounds)
基础
声音循环
要使一个声音循环播放(播放完后重新播放),可以这样做:
mySound.setLoop(True)
mySound.play()
要停止声音的循环,把False传给setLoop()函数:
mySound.setLoop(False)
也可以指定循环的次数:
mySound.setLoopCount(n)
“n”为大于0的任意整数,0表示无限循环。1只播放一次,>1播放数次。
注意设定循环次数为0或>1的数将自动将循环标志setLoop()为TRUE。
无缝循环注意事项:
无缝循环一段声音其实很简单——载入声音然后调用setLoop和play。但是,Panda初级用户经常感到很难做到无缝循环,问题的根源在于:
1、某些MP3编码器有bug,会在声音的末尾添加一段空白,因此循环时就产生间断。试试用wav来代替。
2、有些人尝试通过Sound Interval来创造循环。不幸的是,sound interval依赖Panda线程来重启声音,如果CPU忙碌的话就会产生停顿。一般来说,我们使用setLoop方法。
3、Miles声音系统有一个bug,需要在Panda3D中的一个workaround,这个workaround曾经和fmod产生冲突,直到我们做出一个新的workaround。这个bug已经不复存在了,你可以不管它。
综上可知,得到一个可靠的声音循环最简单的办法就是使用wav文件和setLoop方法,不要使用interval。当然,在游戏发布前可以把你的声音转化为mp3格式,但要确保mp3编码器不会添加空白段。
提示时间
对声音panda提供getTime()、setTime()和length()函数,它们分别报告当前的时间位置、设置当前的时间位置、报告声音时长。单位全都是秒。
mySound.length() 返回声音文件的长度,以秒为单位。
mySound.getTime() 得到当前播放的时间。
mySound.setTime(n) 设定播放时间为第n秒。
注意,声音在这些命令后立即播放,调用play()将重头开始播放声音。
改变播放速度
改变声音播放的速度使用:
mySound.setPlayRate(N)
N为任意浮点数。注意!!!负数将倒着播放,0将暂停播放。可以用
mySound.getPlayRate()
得到声音播放速度。
DSP效果(DSP Effects)
Panda3D 1.3.0 开始支持FMOD-EX的音频效果,目前提供的效果有:
Panda3D ID | 效果 |
DSPChorus | Chorus 齐声 |
DSPCompressor | Compression 压缩 |
DSPDistortion | Distortion 扭曲 |
DSPEcho | Echo [Delay] 回音[延迟] |
DSPFlange | Flange |
DSPHighpass | Highpass Filter 高通滤波 |
DSPItecho | Echo 回音 |
DSPItlowpass | Lowpass Filter低通滤波 |
DSPLowpass | Lowpass Filter |
DSPNormalize | Noramlize |
DSPParameq | Parametric EQ |
DSPPitchshift | Pitchshifter |
DSPReverb | Reverb |
如何使用效果
首先创建一个效果对象(我们以一个回音效果为例)
echo = base.sfxManagerList[0].createDsp(base.sfxManagerList[0].DSPEcho)
这个效果在sound manager类里是一个常量,因此需要指定base.sfxManagerList[n].<effect>, n代表某个音频manager(0为声音,1为音乐),<effect>为上面的表格里列出的某种效果。
得到一个DSP对象后,就可以把它附(attach)到一个声音上
mySound.addDsp(echo)
回音效果这样就准备好了。
一些有用的DSP命令
在交互提示符下得到DSP类型的参数:
dspEffect.listParameterInfo()
它列出所有的DSP参数以及你可以编辑的值。可以在代码中编辑参数:
dspEffect.setParameter("nameOfParameter", value)
参数名必须被引用。
可以取回当前的参数:
dspEffect.getParameter("nameOfParameter")
你可以打开或关掉一个参数:
dspEffect.setBypass(n)
n为一个布尔值。
重置一种效果的参数为默认值:
dspEffect.reset(n)
把效果从声音上卸下来(detach):
mySound.removeDsp(effect)
也可以在某个音频Manager下把一个效果附到所有的声音:
base.sfxManagerList[n].addDsp(effect)
注意!!!对一个Manager附上一个效果将影响这个manager的全部声音。
3D音效
正如前文所说,音效(Sound Effect)和音乐(Music)在Panda3D里是分开处理的。对每一种类,Panda都可以处理16个不同的声音。这个值在配置文件config.prc中由audio-cache-limit变量指定,可以修改。有时我们只需要音效,有时只需要音乐,有时两者都需要。下面这些命令影响所有的同类声音,后两个函数将根据参数值Ture或False来打开或关闭某类声音:
base.disableAllAudio()
base.enableAllAudio()
base.enableMusic(bEnableMusic)
base.enableSoundEffects(bEnableSoundEffects)
下面介绍一些高级的声音处理程序。在编程中,音效和音乐由AudioManager对象实现。可以通过下面的代码访问这2个manager:
soundEffectsMgr = base.sfxManagerList[0]
musicMgr = base.sfxManagerList[1]
注意音效是sfxManagerList第一个成员,音乐为第二个。
通过AudioManager对象,我们可以设置doppler因子和dropoff因子,位置相关声音就是由这些因子实现。Panda封装了一个Audio3DManager类帮助我们实现位置相关声音。Audio3DManager的输入参数是一个audioManager和一个listener,listener代表接收声音的位置,对Panda3D的玩家来说,该位置就是摄影机的位置。距离摄影机远的声音小,近的声音大。
from direct.showbase import Audio3DManager
audio3d = Audio3DManager.Audio3DManager(base.sfxManagerList[0], camera)
我们需要使用Audio3DManager里的loadSfx()函数创建一个位置相关的声音,而不是常规的loader.loadSfx()方法,后者用于与位置无关的声音,如:
mySound = audio3d.loadSfx('blue.wav')
声音可以附在物体上,随物体的移动而移动:
audio3d.attachSoundToObject( mySound, teapot )
你可以使用Audio3DManager提供的setSoundVelocity()和setListenerVelocity()来设定声源或接收者的速度,得到一个doppler pitch shifting(多普勒效应,音调变化)。如果想让Audio3DManager自动调整运动物体的速度,调用setSoundVelocityAuto()或setListenerVelocityAuto():
audio3d.setSoundVelocity(sound,velocityVector)
audio3d.setListenerVelocity(velocityVector)
base.cTrav = CollisionTraverser()
audio3d.setSoundVelocityAuto(sound)
audio3d.setListenerVelocityAuto()
如上面代码所示,CollisionTraverser必须附到base.cTrav上,如果已经分配了一个用于碰撞检测,那么就足够了。
声音随着距离衰减是基于现实世界的声音传播方式。默认情况下,panda的1个单位等同于现实的 1 英尺 。如果使用别的比例尺的话需要用setDistanceFactor来调整比例。如果想让某个位置发出的声音不受距离的影响,可以将它的距离因子设为0:
audio3d.setDistanceFactor(scale)
多声道(Multi-Channel)
(暂无内容)