关键字: VB .NET DirectX DirectSound 3D 作者:董含君
经过一下午的奋战,走了若干弯路,终于可以播放3D声音效果了
感动 ~ ~
大体按照下列的步骤来:
1 关联设备 SetCooperativeLevel
2 设置3D硬件效果 DSoundHelper.Guid3DAlgorithmHrtfFull
3 格式要求 SoundFormat 必须是单声道,不能是立体声
4 主要缓冲区描述
5 创建Listenner
6 辅助缓冲区读取wav
7 创建3D缓冲区
8 播放
9 控制空间位置,以及设置多普勒效应因子,衰减因子
10 停止播放
以下代码注释比较全,顺序比微软的例子简单不少
由于CSDN的Blog不能上传贴图以及RAR,只能帖代码了,有两个Button 一个Picturebox,还有若干Label
==================================================================================
Imports Microsoft.DirectX
Imports Microsoft.DirectX.DirectSound
Imports System.Drawing
Imports System.Drawing.Graphics
Public Class Form1
Inherits System.Windows.Forms.Form
Dim Dev As Device '设备
Dim Buff As Buffer '主要缓冲
Dim SBuff As SecondaryBuffer '二级缓冲
Dim Buff3D As Buffer3D '3D缓冲
Dim descBuff As BufferDescription '缓冲区描述
Dim Buff3DSet As Buffer3DSettings '3D缓冲设置
Dim Listenner As Listener3D '听众
Dim ListennerSet As Listener3DSettings '听众设置
Dim Pic As Graphics
Dim BMP As Bitmap
Const FN = "g:\media\wav\rod2m.wav" '要播放的文件,必须是单声道
#Region " Windows 窗体设计器生成的代码 "
Public Sub New()
MyBase.New()
'该调用是 Windows 窗体设计器所必需的。
InitializeComponent()
'在 InitializeComponent() 调用之后添加任何初始化
End Sub
'窗体重写 dispose 以清理组件列表。
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Windows 窗体设计器所必需的
Private components As System.ComponentModel.IContainer
'注意: 以下过程是 Windows 窗体设计器所必需的
'可以使用 Windows 窗体设计器修改此过程。
'不要使用代码编辑器修改它。
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents Button2 As System.Windows.Forms.Button
Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents Label3 As System.Windows.Forms.Label
Friend WithEvents Label4 As System.Windows.Forms.Label
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
Friend WithEvents TextBox3 As System.Windows.Forms.TextBox
Friend WithEvents TextBox4 As System.Windows.Forms.TextBox
Friend WithEvents Label5 As System.Windows.Forms.Label
Friend WithEvents TextBox5 As System.Windows.Forms.TextBox
Friend WithEvents Label6 As System.Windows.Forms.Label
1<system.diagnostics.debuggerstepthrough()> Private Sub InitializeComponent()
2Me.Button1 = New System.Windows.Forms.Button
3Me.Button2 = New System.Windows.Forms.Button
4Me.PictureBox1 = New System.Windows.Forms.PictureBox
5Me.Label1 = New System.Windows.Forms.Label
6Me.Label2 = New System.Windows.Forms.Label
7Me.Label3 = New System.Windows.Forms.Label
8Me.Label4 = New System.Windows.Forms.Label
9Me.TextBox1 = New System.Windows.Forms.TextBox
10Me.TextBox2 = New System.Windows.Forms.TextBox
11Me.TextBox3 = New System.Windows.Forms.TextBox
12Me.TextBox4 = New System.Windows.Forms.TextBox
13Me.Label5 = New System.Windows.Forms.Label
14Me.TextBox5 = New System.Windows.Forms.TextBox
15Me.Label6 = New System.Windows.Forms.Label
16Me.SuspendLayout()
17'
18'Button1
19'
20Me.Button1.Location = New System.Drawing.Point(24, 8)
21Me.Button1.Name = "Button1"
22Me.Button1.Size = New System.Drawing.Size(88, 32)
23Me.Button1.TabIndex = 0
24Me.Button1.Text = "初始化"
25'
26'Button2
27'
28Me.Button2.Location = New System.Drawing.Point(24, 48)
29Me.Button2.Name = "Button2"
30Me.Button2.Size = New System.Drawing.Size(88, 32)
31Me.Button2.TabIndex = 1
32Me.Button2.Text = "播放"
33'
34'PictureBox1
35'
36Me.PictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
37Me.PictureBox1.Location = New System.Drawing.Point(152, 48)
38Me.PictureBox1.Name = "PictureBox1"
39Me.PictureBox1.Size = New System.Drawing.Size(552, 432)
40Me.PictureBox1.TabIndex = 2
41Me.PictureBox1.TabStop = False
42'
43'Label1
44'
45Me.Label1.Location = New System.Drawing.Point(8, 104)
46Me.Label1.Name = "Label1"
47Me.Label1.TabIndex = 3
48Me.Label1.Text = "多普勒效应0~10"
49'
50'Label2
51'
52Me.Label2.Location = New System.Drawing.Point(8, 160)
53Me.Label2.Name = "Label2"
54Me.Label2.TabIndex = 4
55Me.Label2.Text = "衰减因子 0~10"
56'
57'Label3
58'
59Me.Label3.Location = New System.Drawing.Point(8, 216)
60Me.Label3.Name = "Label3"
61Me.Label3.TabIndex = 5
62Me.Label3.Text = "最大距离 0~100"
63'
64'Label4
65'
66Me.Label4.Location = New System.Drawing.Point(8, 272)
67Me.Label4.Name = "Label4"
68Me.Label4.TabIndex = 6
69Me.Label4.Text = "最小距离 0~100"
70'
71'TextBox1
72'
73Me.TextBox1.Location = New System.Drawing.Point(24, 128)
74Me.TextBox1.Name = "TextBox1"
75Me.TextBox1.TabIndex = 7
76Me.TextBox1.Text = "0.0"
77'
78'TextBox2
79'
80Me.TextBox2.Location = New System.Drawing.Point(24, 184)
81Me.TextBox2.Name = "TextBox2"
82Me.TextBox2.TabIndex = 8
83Me.TextBox2.Text = "0.0"
84'
85'TextBox3
86'
87Me.TextBox3.Location = New System.Drawing.Point(24, 240)
88Me.TextBox3.Name = "TextBox3"
89Me.TextBox3.TabIndex = 9
90Me.TextBox3.Text = "0.9"
91'
92'TextBox4
93'
94Me.TextBox4.Location = New System.Drawing.Point(24, 296)
95Me.TextBox4.Name = "TextBox4"
96Me.TextBox4.TabIndex = 10
97Me.TextBox4.Text = "20.0"
98'
99'Label5
100'
101Me.Label5.Location = New System.Drawing.Point(8, 328)
102Me.Label5.Name = "Label5"
103Me.Label5.TabIndex = 11
104Me.Label5.Text = "Y轴"
105'
106'TextBox5
107'
108Me.TextBox5.Location = New System.Drawing.Point(24, 352)
109Me.TextBox5.Name = "TextBox5"
110Me.TextBox5.TabIndex = 12
111Me.TextBox5.Text = "0.0"
112'
113'Label6
114'
115Me.Label6.Location = New System.Drawing.Point(152, 16)
116Me.Label6.Name = "Label6"
117Me.Label6.Size = New System.Drawing.Size(424, 24)
118Me.Label6.TabIndex = 13
119Me.Label6.Text = "Label6"
120'
121'Form1
122'
123Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
124Me.ClientSize = New System.Drawing.Size(720, 501)
125Me.Controls.Add(Me.Label6)
126Me.Controls.Add(Me.TextBox5)
127Me.Controls.Add(Me.Label5)
128Me.Controls.Add(Me.TextBox4)
129Me.Controls.Add(Me.TextBox3)
130Me.Controls.Add(Me.TextBox2)
131Me.Controls.Add(Me.TextBox1)
132Me.Controls.Add(Me.Label4)
133Me.Controls.Add(Me.Label3)
134Me.Controls.Add(Me.Label2)
135Me.Controls.Add(Me.Label1)
136Me.Controls.Add(Me.PictureBox1)
137Me.Controls.Add(Me.Button2)
138Me.Controls.Add(Me.Button1)
139Me.Name = "Form1"
140Me.Text = "Form1"
141Me.ResumeLayout(False)
142
143End Sub
144
145#End Region
146
147Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
148'''加载的时候初始化一下PictureBox,把它变成黑色(没有颜色)
149PictureBox1_DoubleClick(0, Nothing)
150End Sub
151
152Sub initDirectSound()
153''加载DirectSound设备以及读取wav文件
154'设置3D模式
155Dim DSMode As Guid
156DSMode = DSoundHelper.Guid3DAlgorithmHrtfFull '由于为了演示3D效果,所以用最高模式
157'关联窗体
158Dev = New Device
159Dev.SetCooperativeLevel(Me.Handle, CooperativeLevel.Priority)
160''加载wav '''注释掉了,原来测试用的
161'Dim TmpDesc As New BufferDescription
162'TmpDesc.Guid3DAlgorithm = DSMode
163'TmpDesc.Control3D = True
164'SBuff = New SecondaryBuffer(FN, TmpDesc, Dev)
165
166'格式有比较严格的限制
167Dim fmt As New WaveFormat
168fmt.FormatTag = WaveFormatTag.Pcm
169fmt.Channels = 2
170fmt.SamplesPerSecond = 22050
171fmt.BitsPerSample = 16
172fmt.BlockAlign = CShort(fmt.BitsPerSample / 8 * fmt.Channels)
173fmt.AverageBytesPerSecond = fmt.SamplesPerSecond * fmt.BlockAlign
174'创建描述
175descBuff = New BufferDescription
176'descBuff.ControlVolume = True
177descBuff.Control3D = True
178'descBuff.GlobalFocus = True
179'descBuff.StaticBuffer = True
180'descBuff.LocateInHardware = True
181descBuff.PrimaryBuffer = True
182descBuff.Format = fmt
183'descBuff.Guid3DAlgorithm = DSMode
184'''以上可以自己去掉注释尝试一下,某些时候当Primary打开的时候,其他的不能用,有冲突,尤其是后面几个
185'创建主缓冲
186Try
187'''捕获一下,防止descript的描述不正确(就是参数设置的不对)
188Buff = New Buffer(descBuff, Dev)
189Catch ex As Exception
190MsgBox(ex.Message)
191End '不对的话,就没有必要继续了
192End Try
193'创建听众
194Listenner = New Listener3D(Buff)
195ListennerSet = Listenner.AllParameters '使用主缓冲听众的设置
196
197''WAV
198Dim tmpDesc2 As New BufferDescription
199tmpDesc2.Guid3DAlgorithm = DSMode
200tmpDesc2.Control3D = True
201''' 这里必须借助辅助缓冲给主缓冲提供实例,不知道微软怎么想的,也可能是我学艺不精,怎么尝试都要这样用
202Buff = New SecondaryBuffer(FN, tmpDesc2, Dev)
203
204'创建3D缓冲区
205Buff3D = New Buffer3D(Buff)
206Buff3DSet = Buff3D.AllParameters '使用默认的设置
207Buff3DSet.Mode = Mode3D.HeadRelative '改变一个参数
208Buff3D.AllParameters = Buff3DSet '应用新的设置
209
210MsgBox("已经读取" + FN)
211'ok,初始化完成
212
213End Sub
214
215Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
216Buff.Play(0, BufferPlayFlags.Looping)
217End Sub
218
219Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
220initDirectSound()
221End Sub
222
223Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
224''' 当鼠标左键按下去的时候有效,我可不希望鼠标经过就改变
225If e.Button <> MouseButtons.Left Then Exit Sub
226Dim r = New Rectangle(e.X, e.Y, 3, 3)
227
228Pic = PictureBox1.CreateGraphics()
229Me.Text = e.X.ToString + "," + e.Y.ToString
230Pic.DrawImage(BMP, 1, 1)
231Pic.DrawEllipse(New Pen(Color.Red), r)
232SetSoundPos(Convert.ToSingle(e.X), Convert.ToSingle(TextBox5.Text), Convert.ToSingle(e.Y))
233'''这里坐标变换一下,因为y轴向上,我们需要的是远近,所以负值给Z轴(从上面俯视)
234End Sub
235
236Private Sub PictureBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.DoubleClick
237''' 清除画板,只需双击一下,免得太乱
238BMP = New Bitmap(400, 300)
239PictureBox1.BackgroundImage = BMP
240End Sub
241Sub SetSoundPos(ByVal x As Single, ByVal y As Single, ByVal z As Single)
242'''''''''用户改变位置以及速度之后,对Buff进行调整的代码
243''' 很简单,就是更改参数而已
244''' 定义域在-1 到 1 之间
245Dim POS As Vector3
246Dim Speed As Vector3
247
248POS.X = (x - PictureBox1.Width / 2) / 100
249POS.Y = y / 100
250POS.Z = (z - PictureBox1.Height / 2) / 100
251
252Speed.X = 1
253Speed.Y = 1
254Speed.Z = 1
255
256Buff3D.Position = POS
257Buff3D.Velocity = Speed
258
259Label6.Text = "相对坐标:(x,y)=" + x.ToString + "," + z.ToString
260End Sub
261End Class
262
263================================================================================
264
265这里对y轴的操作不多,我无法用Picturebox描述3D的效果,也许学会了D3D就可以比较形象的描述了
266
267而且对于多普勒也没有过多的使用(我的音箱很难分辨),最好用那种汽车的单一的声音最好
268
269还有速度的改变需要检测鼠标两次的位置判断(需要研究公式的,懒)否则多普勒不够真实
270
271对于表现DirectSound3D的性能,这个例子是不够完善的,但是对于介绍使用DS3D的步骤,我想还是
272
273说得过去的.其他的部分大家自己完善就可以了.
274
275下次就是最后的部分了,利用DirectSound进行混音,实现特效.
276
277倒是想过自己做一个封装,用于声音引擎,但是似乎牵扯到3D的地方必须了解D3D,所以DS一般都包含在游戏引擎里面
278
279单独拿出来就没有太大的意义了(除非不使用3D)</system.diagnostics.debuggerstepthrough()>