终极 Managed DirectSound 9 教程第二部分:管理 3D 音效






4.71/5 (10投票s)
如何播放带有 3D 音效管理的声音。
引言
DirectSound 9 最激动人心的功能是可以将声音和听者位置在 3D 空间中移动。音频在电子游戏等应用程序中非常重要,3D 音效简直是天赐之物,尤其是因为使用 DirectSound 9 实现 3D 音效系统非常简单。
要求
要理解本教程,重要的是要熟悉使用托管 DirectSound 9 进行简单音频播放以及所有关于托管 DirectX 的一般概念,因此请阅读上一篇关于声音播放的教程。在 DirectSound 9 中,声音源只有在单声道时才能在 3D 中使用。这一点很重要,因为即使是立体声文件也包含“3D 声音信息”。如果您尝试使用非单声道文件,DirectSound 将会抛出异常。
使用 3D 音源和听者
这项技术非常简单,我将用一个段落来解释它。第一步是创建一个 Device
和一个 sound
,并为此特定目的添加一些新对象
private Device dSound;
private SecondaryBuffer sound;
// New objects for 3D
private Buffer3D sound3D;
private Listener3D listener;
Buffer3D
是管理声音 3D 虚拟化的新缓冲区对象。该对象可以在空间中移动,其属性将在稍后进行考虑。Listener3D
是一个听者位置,顾名思义,代表一个“人”听者。该对象可以在空间中移动,并具有一些很酷的选项。现在您可以继续创建对象了
dSound = new Device(); // Using default audio card
dSound.SetCooperativeLevel(this.Handle,
CooperativeLevel.Priority);
BufferDescription d = new BufferDescription();
d.ControlVolume = true;
d.ControlPan = true;
d.ControlFrequency = true;
d.ControlEffects = true;
d.Control3D = true; // Important to enable 3D audio!
// See note below!
d.Guid3DAlgorithm =
DSoundHelper.Guid3DAlgorithmHrtfFull;
sound = new SecondaryBuffer(filePath, d, dSound);
最好在可能的情况下选择最强大的声卡,因此请使用 Device
的重载构造函数,如上一教程所示。关于 d.Guid3DAlgorithm
的说明:此属性指定系统将用于管理 3D 音效的算法。有多种可能性
Guid3DAlgorithmDefault
(声卡的默认设置,非常简单)Guid3DAlgorithmHrtfFull
(最高质量,即使需要软件仿真)Guid3DAlgorithmHrtfLight
(质量较低但资源占用较少)Guid3DAlgorithmNoVirtualization
(仅左右效果,在性能较差的系统、仅立体声输出或您不进行垂直声音移动时非常完美)
下一步是创建 3D 缓冲区
sound3D = new Buffer3D(sound);
sound3D.Mode = Mode3D.HeadRelative;
sound3D.Mode
属性指定系统将如何管理 3D 音效。有三种选项
HeadRelative
(将考虑声音和听者的位置)Normal
(听者将被虚拟地强制在 0, 0, 0 位置)Disable
(禁用 3D 音效,用于临时禁用它)
现在是时候设置听者了
Buffer b;
// Another primary buffer is needed
BufferDescription dp = new BufferDescription();
dp.PrimaryBuffer = true;
dp.Control3D = true;
b = new Buffer(dp, dSound);
// Create the Listener3D
listener = new Listener3D(b);
// Setup initial position and options
// for listener and sound3D
// Set the listener in the ‘zero’
// position of the space (origin)
listener.Position = new Vector3(0, 0, 0);
sound3D.Position = new Vector3(0, 0, 0);
// Make the listener ‘looking forward’ (see MSDN)
Listener3DOrientation o = new Listener3DOrientation();
o.Front = new Vector3(0, 0, 1);
o.Top = new Vector3(0, 1, 0);
listener.Orientation = o;
// Play the sound, if needed
sound.Play(0, BufferPlayFlags.Looping);
Vector3
是一个表示 3D 空间中某个点的 struct
。它位于 Microsoft.DirectX
命名空间内。现在您需要播放声音并移动它,或者移动听者。让我们看一些技巧。
Listener3D
具有以下重要成员
Position
:听者的位置(Vector3
)。Velocity
:(vx, vy, vz)听者的瞬时速度(Vector3
)。当听者移动并且您想应用多普勒效应时,应该使用此项。Orientation
:这是听者的“前方”方向。您必须使用Vector3
对象设置 Front 和 Top 方向。在本教程中,我将 Front 设置为正 Z 轴,将 Top 设置为正 Y 轴。DistanceFactor
:这是距离的测量单位。1 等于一米,因此 0.001 等于一毫米。RolloffFactor
:空间中的声音衰减(0 到 10,1 是现实世界的默认值)。DopplerFactor
:自动多普勒效应的因子(0 到 10,1 是现实世界的默认值)。如果您不知道多普勒效应是什么,我将通过一个例子来解释:想象一辆正在向您驶近的汽车。汽车驶近您时发出的噪音与它驶离您时发出的噪音不同。这种效应发生在各种波现象中,例如声音和光的传播。
Buffer3D
具有以下成员
Play
、Stop
等是从 Buffer 继承的,并且与SecondaryBuffer
的相同。Position
:声源位置(Vector3
),与Buffer3D.Position
相同。MinDistance
、MaxDistance
:第一个是从声音开始衰减的距离,第二个是从声音停止衰减的距离。换句话说,直到MinDistance
,声音处于最大音量;在MinDistance
和MaxDistance
之间,声音逐渐衰减;超过MaxDistance
,声音保持低音量并且不再衰减。对于这些选项,Listener3D.DistanceFactor
和Listener3D.RolloffFactor
很重要!不幸的是,要理解这些参数的实际行为的最佳方法是尝试并测试它们。Velocity
:声源的速度,如果它在移动,与Listener3D.Velocity
相同。ConeOrientation
:(Vector3
)此选项允许您指定声音传播的圆锥体。Vector3
是从声源位置开始的假想线的终点,定义了圆锥体的方向。ConeAngles
:(Angles
)内部圆锥体和外部圆锥体的角度:在第一个圆锥体内,音量将具有最大值;在第二个圆锥体内,音量将逐渐衰减(参见 MSDN)。ConeOutsideVolume
:指定上述外部圆锥体外的音量。
没有更多有趣的特性可以描述了。请参阅附带的演示应用程序,其中显示了一个移动的声源和一个固定的听者。您可以用鼠标移动声源,或者让它绕着听者旋转。一如既往,我建议查阅 MSDN 文档:在您理解了主要技术之后,扩展它们将非常简单。
性能注意事项
我们可以说 DirectSound 非常快。在大多数情况下,这个说法是有效的,但我们需要描述一些情况。例如,如果声卡不支持 3D 音效,DirectSound 将通过软件进行仿真。如果系统(或同一应用程序)不需要执行其他任务,用户将不会注意到差异。但是,如果您正在开发一款电子游戏,3D 音效将使 CPU 负担过重,从而减慢系统速度。因此,请做出正确的选择。在演示应用程序中,您可能会注意到声源移动时有些粗糙,尽管 CPU 负载仍低于 10%。
结论
现在您应该能够管理 3D 空间中的声音了。我个人认为这非常简单。在下一篇教程中,我将解释如何使用 DirectSound 的 CaptureDevice
进行录音。