最终的托管 DirectSound 9 教程。第一部分:完整介绍播放






4.72/5 (44投票s)
使用托管 DirectSound 9 如何播放声音、应用效果等。
引言
托管 DirectSound 9 是托管 DirectX 9 库的一部分。在本教程中,我将解释如何使用 Microsoft 托管 DirectSound 9 播放声音,如何应用效果,选择输出音频设备以及一些其他技巧。我希望你会发现 DirectSound 并不像看起来那么难。
要求
为了开发和运行使用托管 DirectSound 9(以及所有托管 DirectX 9)的应用程序,你必须在系统中安装 DirectX 9 标准可再发行包,并在命令行中指定参数 /InstallManagedDX(例如,D:\Download\dxsetup /InstallManagedDX)。你也可以从 Microsoft 网站下载名为“DirectX 9.0c 可再发行包(适用于软件开发人员 - 包含更新的托管代码 DirectX 和 D3DX)”的包,该包会自动包含并安装托管 DirectX 库。显然,你必须在项目中添加对 Microsoft.DirectX
和 Microsoft.DirectX.DirectSound
的引用。
这里有一个重要的说明:为了运行应用程序,用户不必安装 Managed DX9,但将引用的程序集复制到应用程序的根文件夹就足够了。为此,将程序集的 LocalCopy
属性设置为 true
或手动复制它们。我建议第一种方法,因为如果你使用 Visual Studio 为应用程序创建安装程序,它将检测到引用并将程序集复制到安装目的地。第二种方法你必须记住手动添加它们。为了简化你的生活,请将这些 using
子句添加到你的源文件中
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;
代码的第一行:播放 Wave 文件
你需要做的第一件事是创建一个 DirectSound Device
private Device dSound;
之后,对其进行设置
dSound = new Device();
dSound.SetCooperartiveLevel(handle,
CooperativeLevel.Priority);
说明:handle
是你主窗口的句柄(IntPtr
),所以写 this.Handle
。CooperativeLevel
设置播放的硬件管理。有三种可能性,但你应该使用 Priority
,因为它尽可能使用硬件加速。Device
构造函数是重载的:我们稍后会看到其他选项。
下一步是使用 Buffer 和其描述符创建一个 sound
private SecondaryBuffer sound;
private BufferDescription d = new BufferDescription();
// Set descriptor’s flags
d.ControlPan = true;
d.ControlVolume = true;
d.ControlFrequency = true;
d.ControlEffects = true;
标志是
ControlPan
:允许你控制声音的平衡(左右)。ControlVolume
:允许你控制声音的音量。ControlFrequency
:允许你控制声音的采样频率(很少使用)。ControlEffects
:允许你为声音应用效果。
还有一些其他标志,但我们不关心它们。
// Create the sound
sound = new SecondaryBuffer(filePath, d, dSound);
filePath
是 .wav 文件的完整路径,d
是上面创建的描述符,dSound
是将播放 sound
的 Device
。之后,sound
就准备好播放了。作为第一个参数,你也可以指定 System.IO.Stream
,例如,如果你正在从 Internet 接收声音(在这种情况下,你必须管理数据消耗和接收速率之间的差异:想象一下你的媒体播放器在停止播放以从服务器检索更多数据时)。
你可以对 SecondaryBuffer
执行的操作有
sound.Play(priority, flags)
:priority
是播放的优先级(0 是默认值,表示最低优先级),flags
是enum
BufferPlayFlags
的一个值。最重要的值是BufferPlayFlags.Default
(声音播放完时停止)和BufferPlayFlags.Looping
(循环播放声音)。sound.Stop()
:暂停声音。之后,如果你调用 Play,声音将从暂停的位置开始播放。要真正停止声音,你可以使用以下方法。sound.SetCurrentPosition(pos)
:以字节为单位设置声音中的位置。你可以使用sound.Caps.BufferBytes
属性检索声音的总长度(以字节为单位!)。如果 pos 为零,则表示将声音倒带。sound.PlayPosition
:返回声音中当前播放的位置(以字节为单位!)。sound.Volume
:声音的音量。允许的值范围是零到 -10000 分贝(对数衰减)。0 是最大音量,-10000 是零音量。在 -2500 左右的值,声音会静音。它需要将标志sound.ControlVolume
设置为true
。sound.Pan
:声音的平衡。值范围是 -10000(全部向左)到 10000(全部向右)。零是平衡值。需要将标志sound.ControlPan
设置为true
。sound.Frequency
:声音的采样频率(每秒采样数)。零是默认值,但允许的值范围是 100 到 10000。此属性很少使用。需要将标志sound.ControlFrequency
设置为true
。sound.Status.*
:提供有关声音状态的信息。Playing
(bool
)指示声音当前是否正在播放,Looping
(bool
)指示声音是否设置为循环播放。sound.Format.*
:关于声音的更多有趣信息。重要成员是AverageBytesPerSecond
、BitsPerSample
、Channels
、SamplesPerSecond
。它们不言自明,并且由于它们,我们可以计算声音的持续时间(任何其他属性都不会显示!)。你可以按以下方式计算:int totalSeconds = sound.Caps.BufferBytes / sound.Format.AverageBytesPerSecond;
使用扬声器
你还可以做的另一件惊人的事情是设置连接到输出声卡的正确类型的扬声器。此选项允许你在每个输出系统上获得更好的声音。你需要设置的属性是 dSound.SpeakerConfig
// Create new Speakers
Speakers s = new Speakers();
// Set properties
s.Mono = false; // Sets as a mono speaker
s.Headphone = false; // Sets as headphones
s.Stereo = false; // Sets as generic stereo speakers
s.Quad = false; // Sets as quad system (two front, two rear)
s.FiveDotOne = false; // Sets as a 5.1 surround system
s.SevenDotOne = true; // Sets as a 7.1 surround system
s.Surround = false; // Sets as a generic surround system
dSound.SpeakerConfig = s;
说明:如果你每次都通过创建新的 Speakers
对象来设置 Speakers
,就可以避免重置旧属性。因此,只需替换旧的 Speakers
对象即可。
在声卡之间进行选择
在许多系统中都有不止一个声卡。DirectSound 9 允许你选择正确的声卡,安排一个选择默认声卡的方法,或者选择用户想要的声卡。要枚举并向用户显示已安装的声卡,请执行以下操作(假设声卡列表已放入名为 cmbAudioCards
的 ComboBox
中):
private DevicesCollection devList = new DevicesCollection();
cmbAudioCards.Items.Clear();
for(int i = 0; i < devList.Count; i++) {
cmbAudioCards.Items.Add(devList[i].Description);
}
第一个元素是默认音频卡,它始终列出。其他项目是“物理”音频卡。例如,你可以看到
- 主音频驱动程序
- Audio SB Live! [400]
- 蓝牙音频
当用户选择特定卡时,你可以按照以下方式重建 Device(在 ComboBox
事件处理程序中):
dSound = new Device(devList[cmbAudioCards.SelectedIndex].DriverGuid);
dSound.SetCooperativeLevel(this.Handle, CooperativeLevel.Priority);
// You have to recreate the sound (the descriptor d can be reused)
sound = new SecondaryBuffer(filePath, d, dSound);
DriverGuid
是所选声卡驱动程序实例的全局唯一标识符。首次启动时,或者如果用户未选择特定声卡,你可以使用 Device
的默认构造函数,或通过代码选择 devList
中的第一个元素,即默认音频卡。
选择不同的声卡可能会影响系统性能:在上面的示例中,SoundBlaster Live! 具有硬件加速功能,并支持高达 5.1 的系统。蓝牙音频效果较差,在应用效果或管理 3D 音频时可能会增加 CPU 负载。
对音频播放应用效果
DirectSound 9 最重要的功能之一是能够实时地将音频效果应用于播放中的声音。你还可以应用几乎无限的效果链(取决于系统功能)。所有效果尽可能在硬件中应用,否则通过软件模拟(导致性能大幅下降!)。请记住将标志 sound.ControlEffects
设置为 true
!
在 DirectSound 9 中,有——无需多说:)——9 种效果:Chorus、Compressor、Distortion、Echo、Flanger、Gargle、Interactive3DLevel2Reverb、ParamEqualizer、WavesReverb。我想说的是,关于这些效果的文档并不多,特别是因为它们中的每一种都有不同的设置。第一件事是创建一个 EffectDescription
数组
EffectDescription[] fx = new EffectDescription[1];
在此示例中,我们只使用一种效果,但如果你愿意,可以通过创建足够长的数组并为每个元素插入一种效果来使用更多效果。假设你想应用 Echo 效果
fx[0].GuidEffectClass = DSoundHelper.StandardEchoGuid;
sound.SetEffects(fx);
假设现在你想应用 Parametric Equalizer 效果
fx[0].GuidEffectClass = DSoundHelper.StandardParamEqGuid;
sound.SetEffects(fx);
说明:你只能在声音未播放时应用效果。如上所述,每种效果都有不同的选项。我将在此解释如何设置 Parametric Equalizer 效果
fx[0].GuidEffectClass = DSoundHelper.StandardParamEqGuid;
sound.SetEffects(fx);
ParamEqEffect eqEffect = (ParamEqEffect)sound.GetEffects(0);
EffectsParamEq eqParams = eqEffect.AllParameters;
// Specific properties!
eqParams.Bandwidth = 36; // Apply a gain on the highest frequency
eqParams.Gain = ParamEqEffect.GainMax;
eqEffect.AllParameters = eqParams;
抽象化这个过程,你必须首先创建一个包含 StandardEFFECTNAMEGuid
的效果数组,然后使用 EFFECTNAMEEffect
和 EffectsEFFECTNAME
对象设置参数,其中 EFFECTNAME 是效果的名称。始终记住执行正确的转换。要重置声音上的效果,你必须覆盖它
sound = new SecondaryBuffer(filePath, d, dSound);
有关效果的更多信息,请查阅 MSDN Library。
结论
到目前为止,你应该已经对 DirectSound 设备、效果和其他选项有了一些了解。DirectSound 适合播放短声音,如爆炸声、枪声等。如果你想播放长 Wave 音频,你应该使用 Microsoft.DirectX.AudioVideoPlayback
命名空间,我将在未来进行解释。在 下一篇教程中,我将解释如何使用 DirectSound 的 3D 音频。