VB.NET 实现DirectSound9 (5) DS3D2

关键字: 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
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.Button2 = New System.Windows.Forms.Button
Me.PictureBox1 = New System.Windows.Forms.PictureBox
Me.Label1 = New System.Windows.Forms.Label
Me.Label2 = New System.Windows.Forms.Label
Me.Label3 = New System.Windows.Forms.Label
Me.Label4 = New System.Windows.Forms.Label
Me.TextBox1 = New System.Windows.Forms.TextBox
Me.TextBox2 = New System.Windows.Forms.TextBox
Me.TextBox3 = New System.Windows.Forms.TextBox
Me.TextBox4 = New System.Windows.Forms.TextBox
Me.Label5 = New System.Windows.Forms.Label
Me.TextBox5 = New System.Windows.Forms.TextBox
Me.Label6 = New System.Windows.Forms.Label
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(24, 8)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(88, 32)
Me.Button1.TabIndex = 0
Me.Button1.Text = "初始化"
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(24, 48)
Me.Button2.Name = "Button2"
Me.Button2.Size = New System.Drawing.Size(88, 32)
Me.Button2.TabIndex = 1
Me.Button2.Text = "播放"
'
'PictureBox1
'
Me.PictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
Me.PictureBox1.Location = New System.Drawing.Point(152, 48)
Me.PictureBox1.Name = "PictureBox1"
Me.PictureBox1.Size = New System.Drawing.Size(552, 432)
Me.PictureBox1.TabIndex = 2
Me.PictureBox1.TabStop = False
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(8, 104)
Me.Label1.Name = "Label1"
Me.Label1.TabIndex = 3
Me.Label1.Text = "多普勒效应0~10"
'
'Label2
'
Me.Label2.Location = New System.Drawing.Point(8, 160)
Me.Label2.Name = "Label2"
Me.Label2.TabIndex = 4
Me.Label2.Text = "衰减因子 0~10"
'
'Label3
'
Me.Label3.Location = New System.Drawing.Point(8, 216)
Me.Label3.Name = "Label3"
Me.Label3.TabIndex = 5
Me.Label3.Text = "最大距离 0~100"
'
'Label4
'
Me.Label4.Location = New System.Drawing.Point(8, 272)
Me.Label4.Name = "Label4"
Me.Label4.TabIndex = 6
Me.Label4.Text = "最小距离 0~100"
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(24, 128)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.TabIndex = 7
Me.TextBox1.Text = "0.0"
'
'TextBox2
'
Me.TextBox2.Location = New System.Drawing.Point(24, 184)
Me.TextBox2.Name = "TextBox2"
Me.TextBox2.TabIndex = 8
Me.TextBox2.Text = "0.0"
'
'TextBox3
'
Me.TextBox3.Location = New System.Drawing.Point(24, 240)
Me.TextBox3.Name = "TextBox3"
Me.TextBox3.TabIndex = 9
Me.TextBox3.Text = "0.9"
'
'TextBox4
'
Me.TextBox4.Location = New System.Drawing.Point(24, 296)
Me.TextBox4.Name = "TextBox4"
Me.TextBox4.TabIndex = 10
Me.TextBox4.Text = "20.0"
'
'Label5
'
Me.Label5.Location = New System.Drawing.Point(8, 328)
Me.Label5.Name = "Label5"
Me.Label5.TabIndex = 11
Me.Label5.Text = "Y轴"
'
'TextBox5
'
Me.TextBox5.Location = New System.Drawing.Point(24, 352)
Me.TextBox5.Name = "TextBox5"
Me.TextBox5.TabIndex = 12
Me.TextBox5.Text = "0.0"
'
'Label6
'
Me.Label6.Location = New System.Drawing.Point(152, 16)
Me.Label6.Name = "Label6"
Me.Label6.Size = New System.Drawing.Size(424, 24)
Me.Label6.TabIndex = 13
Me.Label6.Text = "Label6"
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
Me.ClientSize = New System.Drawing.Size(720, 501)
Me.Controls.Add(Me.Label6)
Me.Controls.Add(Me.TextBox5)
Me.Controls.Add(Me.Label5)
Me.Controls.Add(Me.TextBox4)
Me.Controls.Add(Me.TextBox3)
Me.Controls.Add(Me.TextBox2)
Me.Controls.Add(Me.TextBox1)
Me.Controls.Add(Me.Label4)
Me.Controls.Add(Me.Label3)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.Label1)
Me.Controls.Add(Me.PictureBox1)
Me.Controls.Add(Me.Button2)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub

#End Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'''加载的时候初始化一下PictureBox,把它变成黑色(没有颜色)
PictureBox1_DoubleClick(0, Nothing)
End Sub

Sub initDirectSound()
''加载DirectSound设备以及读取wav文件
'设置3D模式
Dim DSMode As Guid
DSMode = DSoundHelper.Guid3DAlgorithmHrtfFull '由于为了演示3D效果,所以用最高模式
'关联窗体
Dev = New Device
Dev.SetCooperativeLevel(Me.Handle, CooperativeLevel.Priority)
''加载wav '''注释掉了,原来测试用的
'Dim TmpDesc As New BufferDescription
'TmpDesc.Guid3DAlgorithm = DSMode
'TmpDesc.Control3D = True
'SBuff = New SecondaryBuffer(FN, TmpDesc, Dev)

'格式有比较严格的限制
Dim fmt As New WaveFormat
fmt.FormatTag = WaveFormatTag.Pcm
fmt.Channels = 2
fmt.SamplesPerSecond = 22050
fmt.BitsPerSample = 16
fmt.BlockAlign = CShort(fmt.BitsPerSample / 8 * fmt.Channels)
fmt.AverageBytesPerSecond = fmt.SamplesPerSecond * fmt.BlockAlign
'创建描述
descBuff = New BufferDescription
'descBuff.ControlVolume = True
descBuff.Control3D = True
'descBuff.GlobalFocus = True
'descBuff.StaticBuffer = True
'descBuff.LocateInHardware = True
descBuff.PrimaryBuffer = True
descBuff.Format = fmt
'descBuff.Guid3DAlgorithm = DSMode
'''以上可以自己去掉注释尝试一下,某些时候当Primary打开的时候,其他的不能用,有冲突,尤其是后面几个
'创建主缓冲
Try
'''捕获一下,防止descript的描述不正确(就是参数设置的不对)
Buff = New Buffer(descBuff, Dev)
Catch ex As Exception
MsgBox(ex.Message)
End '不对的话,就没有必要继续了
End Try
'创建听众
Listenner = New Listener3D(Buff)
ListennerSet = Listenner.AllParameters '使用主缓冲听众的设置

''WAV
Dim tmpDesc2 As New BufferDescription
tmpDesc2.Guid3DAlgorithm = DSMode
tmpDesc2.Control3D = True
''' 这里必须借助辅助缓冲给主缓冲提供实例,不知道微软怎么想的,也可能是我学艺不精,怎么尝试都要这样用
Buff = New SecondaryBuffer(FN, tmpDesc2, Dev)

'创建3D缓冲区
Buff3D = New Buffer3D(Buff)
Buff3DSet = Buff3D.AllParameters '使用默认的设置
Buff3DSet.Mode = Mode3D.HeadRelative '改变一个参数
Buff3D.AllParameters = Buff3DSet '应用新的设置

MsgBox("已经读取" + FN)
'ok,初始化完成

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Buff.Play(0, BufferPlayFlags.Looping)
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
initDirectSound()
End Sub

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
''' 当鼠标左键按下去的时候有效,我可不希望鼠标经过就改变
If e.Button <> MouseButtons.Left Then Exit Sub
Dim r = New Rectangle(e.X, e.Y, 3, 3)

Pic = PictureBox1.CreateGraphics()
Me.Text = e.X.ToString + "," + e.Y.ToString
Pic.DrawImage(BMP, 1, 1)
Pic.DrawEllipse(New Pen(Color.Red), r)
SetSoundPos(Convert.ToSingle(e.X), Convert.ToSingle(TextBox5.Text), Convert.ToSingle(e.Y))
'''这里坐标变换一下,因为y轴向上,我们需要的是远近,所以负值给Z轴(从上面俯视)
End Sub

Private Sub PictureBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.DoubleClick
''' 清除画板,只需双击一下,免得太乱
BMP = New Bitmap(400, 300)
PictureBox1.BackgroundImage = BMP
End Sub
Sub SetSoundPos(ByVal x As Single, ByVal y As Single, ByVal z As Single)
'''''''''用户改变位置以及速度之后,对Buff进行调整的代码
''' 很简单,就是更改参数而已
''' 定义域在-1 到 1 之间
Dim POS As Vector3
Dim Speed As Vector3

POS.X = (x - PictureBox1.Width / 2) / 100
POS.Y = y / 100
POS.Z = (z - PictureBox1.Height / 2) / 100

Speed.X = 1
Speed.Y = 1
Speed.Z = 1

Buff3D.Position = POS
Buff3D.Velocity = Speed

Label6.Text = "相对坐标:(x,y)=" + x.ToString + "," + z.ToString
End Sub
End Class

================================================================================

这里对y轴的操作不多,我无法用Picturebox描述3D的效果,也许学会了D3D就可以比较形象的描述了

而且对于多普勒也没有过多的使用(我的音箱很难分辨),最好用那种汽车的单一的声音最好

还有速度的改变需要检测鼠标两次的位置判断(需要研究公式的,懒)否则多普勒不够真实

对于表现DirectSound3D的性能,这个例子是不够完善的,但是对于介绍使用DS3D的步骤,我想还是

说得过去的.其他的部分大家自己完善就可以了.

下次就是最后的部分了,利用DirectSound进行混音,实现特效.

倒是想过自己做一个封装,用于声音引擎,但是似乎牵扯到3D的地方必须了解D3D,所以DS一般都包含在游戏引擎里面

单独拿出来就没有太大的意义了(除非不使用3D)

时间: 2024-11-08 19:05:41

VB.NET 实现DirectSound9 (5) DS3D2的相关文章

用VB.Net实现DirectSound9 (4) DS3D

关键字:VB DirectX9 DirectSound 3D 作者:董含君 昨天去百度搜索DirectSound3D的资料,真是一点都没有.惊讶啊. google有一些,还是微软的.看来真的要填补国内空白了. 高手门看来都很忙啊. ========以上是废话================ 一开始看微软DSound3D的例子很困难,主要是术语太多,如果准备工作做的不够,可以说几乎看不懂. 从家里翻出一本DirectX的速成教材,看来有解释的必要. =========以下是正文==========

VB.NET实现DirectSound9 (6) 声音特效

关键字: VB.NET DirectSound 9 声音特效 回声Echo 作者:董含君转载请注明来自:http://blog.csdn.net/a11s 实际上这个就是传说的混音,微软把各种效果添加起来变成了混音程序严格的讲,这个算作声音的特效. 微软的DirectX的例子还有一个特点,就是爱把简单的问题复杂化,我用了大量的时间搞清出中间的各种对象怎样协作的,明白之后再来考虑各自的用途.虽然相信微软这么做也许是有道理的,但是不适合初学者.经过尝试整理出了以下结果. 首先大体介绍一下步骤====

VB.NET实现DirectSound9 (7) 录音

关键字: VB.NET DirectX 9 DirectSound 录音 riff文件格式 作者:董含君 下午看了微软提供的例子,居然把录音定位成Beginner级别晕哦,虽说我认为这个例子是微软提供的最"直接"的例子,但是步骤超多.而且还牵扯到多线程开辟缓冲区回调riff文件格式 IO 输出等等.由于录音的复杂性,以及微软这个例子的直接性,坚持原创的我最终还是复制了大量的代码.(希望不要骂我....) OK,先来说录音的步骤,里面牵扯到riff或者使用技巧的地方,有注释.我仅仅说步骤

VB.NET基础语法

很久以来,VB因为缺乏完善的面向对象支持.缺乏高效的错误处理机制和性能表现不佳,因而一直受到某些人的嘲笑.VB.NET将彻底改变这种情况.然而,VB.NET在这些方面的改进也要付出代价,许多旧的代码需要手工进行转换才能在VB.NET下运行. 下面几个表格总结了VB.NET语言在语法上的改动之处.注意这些表格并没有完全列出所有改动之处,但列出了最重要的一些改动. 表A对比了VB6中一些熟悉的语法形式及其在VB.NET中类似功能最接近的语法形式. 表A:语法对比旧语法 新语法 说明窗体装载事件,类初

VB.NET中有用的通用对象列表

要使用List(of T),我们需要了解如何部署.NET框架所提供的多种方法.这也将是本文要介绍的内容.我已经编写好了三个示例--使用ForEach, FindAll,和Sort--来阐述同样列表类的工作原理. 第一步是要创建一个同用列表.你可以从多种途径获取数据,但是最简单的方法是添加.文本中,我们会编写代码以便为举例中的集来分类.因此,下面我们就来讲讲创建集的代码. 首先,我需要一个能代表集中的Bottle的对象.为此而编写的代码是完全符合标准的,而且事实上,VB.NET 2008 Expr

VB.NET多线程应用

开发者一直要求微软为VB加入更多的多线程功能,对于VB.NET也是这样.VB6已经支持建立多线程的EXE.DLL和OCX.不过使用多线程这个词语,可能也不太确切.因此VB6仅支持运行多个单线程的单元.一个单元实际上是代码执行的空间,而单元的边界限制了代码访问任何单元以外的事物. VB.NET就不同了,它支持建立自由线程(free-threaded)的应用.这意味着多个线程可以访问同样一套的共享数据.本文的以下部分将讨论一下多线程的一些基本点. 问题 虽然VB6支持多个单线程的单元,不过它并不支持

VB.NET局部静态变量介绍

经过长时间学习VB.NET局部静态变量,于是和大家分享一下,看完本文你肯定有不少收获,希望本文能教会你更多东西.VB.NET能够实现很多C#不能做到的功能,如When语句.Optional参数.局部Static变量.对象实例访问静态方法.Handles绑定事件.On Error处理异常.Object直接后期绑定等等.VB和C#同属.NET的语言,编译出来的是同样的CIL,但为什么VB支持很多有趣的特性呢.我们一起来探究一下VB.NET局部静态变量. VB.NET局部静态变量 VB支持用Stati

使用VB.NET加密文件

加密 本文介绍使用XOR加密算法对数据进行加密, 这是一种很简单的算法,使用了尽量简单的VB编程方法,通俗易懂.我们可以采用更安全的算法如DES算法,IDEA算法等.各位如有任何见解,请不吝赐教. 在窗体中添加一RichTextBox,设置其Name属性为SourceFile,Multiline属性为True,ScrollBars属性为3-both.添加一MainMenu,设置一菜单项"文件",其下有"打开","保存","加密"

编程-VB 引用同一根目录下的文件夹的Excel

问题描述 VB 引用同一根目录下的文件夹的Excel exe文件跟文件夹的根目录一样,要引用文件夹下面的Excel部分单元格的数据各位高手帮我解答下,新人的第一条提问 解决方案 '工程-引用-将Microsoft Excel 12.0 Object Library选中,'工程-部件-将Microsoft Common Dialog Control 6.0选中,'在窗体上添加一个按钮Command1对象,一个CommonDialog1通用对话框对象Private Sub Command1_Clic