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

原创 2005年02月27日 15:30:00

关键字: VB.NET DirectSound 9 声音特效 回声Echo                       作者:董含君
转载请注明来自:http://blog.csdn.net/a11s

实际上这个就是传说的混音,微软把各种效果添加起来变成了混音程序
严格的讲,这个算作声音的特效.

微软的DirectX的例子还有一个特点,就是爱把简单的问题复杂化,我用了大量的时间搞清出中间的各种对象怎样协作的,明白之后再来考虑各自的用途.虽然相信微软这么做也许是有道理的,但是不适合初学者.经过尝试整理出了以下结果.

首先大体介绍一下步骤
============================================================
加载
1 需要设备以及一个缓冲用于播放声音(具体请参见前文的介绍)

2 描述这个缓冲区的时候,记得加上ControlEffects=true的属性(跟ControlVolume是一个道理)

读取
3  new SecondaryBuffer读取文件,这个文件如果太小,则会出现错误.无法体现效果,需要try catch一下

设置效果
4 设置效果需要介绍一些对象,稍后再说

5 播放,同时可以进行相关属性的操作

6 特效的移除
7 停止播放
=====================================

由此可见,大体步骤跟3D音效类似,只不过中间多了效果设置而已

以下是对象的介绍.

1 首先需要了解,一个声音(Buffer)可以同时应用多种效果
这样就产生了一个问题,如何才能设置我们的SecondaryBuffer有这些效果

DirectSound是用一个数组来表示的,添加一个效果,这个数组就有一个元素.两个效果,这个数组就有两个元素.
依次类推.

我们的SecondaryBuffer应用的时候,是直接将这个数组一同传递给SecondaryBuffer的.
        SB.SetEffects(effd)

2 不要以为什么特效都要自己做(天!千万别这么想,否则需要专门研究计算机声学的)
微软DirectSound内置了几种特效,可以参见微软SDK最后的那个例子,也可以用
DSoundHelper.StandardEchoGuid 类似的这种形式列出

3 每种特效的属性都是一个结构体(也可以理解为对象).我们有很多特效的对象
比如 Dim echo As EchoEffect

4 每种特效对象的属性是一个结构体(需要跟上面区分开来)
比如RchoEffect对象不能直接用这种方法修改echo.WetDryMix属性
需要利用一个结构体来完成echo属性的存储,这个结构体叫做
EffectsEcho  (微软真是作孽啊,名字取得都这么像,很难区分的)
        Dim eff As New EffectsEcho          '''结构
        eff = echo.AllParameters
        eff.WetDryMix = 0
        eff.Feedback = 0
        eff.LeftDelay = 1
        eff.RightDelay = 1
        eff.PanDelay = 0
设置完成之后,一次性传给特效对象echo
        echo.AllParameters = eff

5 Buffer播放的时候可以可以调整特效属性的,只要修改echo.allparameters就可以了

知道中间怎么做的了,然后看代码

代码分为几个部分,主要还是为了容易理解
第一步,初始化设备(实在太经典了,就不用看了)
第二步,加载wav(就是多了一个controlEffect,别的都一样)
第三步,设置音效(单独看)
第四步,播放(简单一个play)
第五步,停止播放

Imports Microsoft.DirectX.DirectSound

 

Public Class Form1

    Inherits System.Windows.Forms.Form

 

#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 TextBox1 As System.Windows.Forms.TextBox

    Friend WithEvents Button1 As System.Windows.Forms.Button

    Friend WithEvents Button2 As System.Windows.Forms.Button

    Friend WithEvents Button3 As System.Windows.Forms.Button

    Friend WithEvents Button4 As System.Windows.Forms.Button

    Friend WithEvents Button5 As System.Windows.Forms.Button

    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

        Me.TextBox1 = New System.Windows.Forms.TextBox

        Me.Button1 = New System.Windows.Forms.Button

        Me.Button2 = New System.Windows.Forms.Button

        Me.Button3 = New System.Windows.Forms.Button

        Me.Button4 = New System.Windows.Forms.Button

        Me.Button5 = New System.Windows.Forms.Button

        Me.SuspendLayout()

        '

        'TextBox1

        '

        Me.TextBox1.Location = New System.Drawing.Point(104, 40)

        Me.TextBox1.Name = "TextBox1"

        Me.TextBox1.Size = New System.Drawing.Size(160, 21)

        Me.TextBox1.TabIndex = 2

        Me.TextBox1.Text = "g:/media/wav/rod2.wav"

        '

        'Button1

        '

        Me.Button1.Location = New System.Drawing.Point(16, 8)

        Me.Button1.Name = "Button1"

        Me.Button1.Size = New System.Drawing.Size(80, 24)

        Me.Button1.TabIndex = 3

        Me.Button1.Text = "init"

        '

        'Button2

        '

        Me.Button2.Location = New System.Drawing.Point(16, 40)

        Me.Button2.Name = "Button2"

        Me.Button2.Size = New System.Drawing.Size(80, 24)

        Me.Button2.TabIndex = 4

        Me.Button2.Text = "load"

        '

        'Button3

        '

        Me.Button3.Location = New System.Drawing.Point(16, 72)

        Me.Button3.Name = "Button3"

        Me.Button3.Size = New System.Drawing.Size(80, 24)

        Me.Button3.TabIndex = 5

        Me.Button3.Text = "play"

        '

        'Button4

        '

        Me.Button4.Location = New System.Drawing.Point(16, 104)

        Me.Button4.Name = "Button4"

        Me.Button4.Size = New System.Drawing.Size(80, 24)

        Me.Button4.TabIndex = 6

        Me.Button4.Text = "stop"

        '

        'Button5

        '

        Me.Button5.Location = New System.Drawing.Point(280, 40)

        Me.Button5.Name = "Button5"

        Me.Button5.Size = New System.Drawing.Size(88, 24)

        Me.Button5.TabIndex = 7

        Me.Button5.Text = "Echo"

        '

        'Form1

        '

        Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)

        Me.ClientSize = New System.Drawing.Size(400, 269)

        Me.Controls.Add(Me.Button5)

        Me.Controls.Add(Me.Button4)

        Me.Controls.Add(Me.Button3)

        Me.Controls.Add(Me.Button2)

        Me.Controls.Add(Me.Button1)

        Me.Controls.Add(Me.TextBox1)

        Me.Name = "Form1"

        Me.Text = "Form1"

        Me.ResumeLayout(False)

 

    End Sub

 

#End Region

    Dim Dev As Device

    Dim PB As Buffer

    Dim SB As SecondaryBuffer

    Dim Desc1 As BufferDescription

    Dim desc2 As BufferDescription

    Dim eff As EffectDescription

 

    Private Structure EffectInfo

 

        Public description As EffectDescription

        Public EffectSettings As Object

        Public Effect As Object

    End Structure

 

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

        '''加载DirectSound

        Dev = New Device

        Dev.SetCooperativeLevel(Me, CooperativeLevel.Priority)

        Me.Text = "init ok"

    End Sub

 

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        '''读取wav

        Desc1 = New BufferDescription

        Desc1.ControlEffects = True

        SB = New SecondaryBuffer(TextBox1.Text, Desc1, Dev)

        Me.Text = "load ok"

    End Sub

 

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

        '''播放啊播放

        If SB Is Nothing Then Exit Sub

        SB.Play(0, BufferPlayFlags.Default)

        Me.Text = "playing"

    End Sub

 

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

        '''停止播放,释放当前的wav

        SB.Stop()

        SB.Dispose()

        Me.Text = "disposed"

    End Sub

 

    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click

'''主要看这个

        ''' 我的数组声明了一个元素,看起来没有必要,但是设置的时候要求必须是数组,哪怕元素只有一个

        ''' 如果需要更多的效果,设置相应的元素个数

        Dim effd(0) As EffectDescription        ''描述集合

        Dim eff As New EffectsEcho              '''结构,由于对象不能单独设置属性,只能用它间接修改

        '''关键步骤,指定特效的类型

        effd(0).GuidEffectClass = DSoundHelper.StandardEchoGuid     '''说明第一种效果是回声

        '''软件,你要是用硬件,我也不反对

        effd(0).LocateInSoftware = True

        '''直接一次性提交给Buffer,提交的是一个数组

        SB.SetEffects(effd)

        '''声明一个特效对象,别忘了我们需要修改参数滴

        Dim echo As EchoEffect

        '''得到当前Buffer的效果

        ''' 这个后面的0,正是你一次性传递过去的效果的index,忘了?就是刚才那个数组

        echo = SB.GetEffects(0)

        '''对象不能直接修改,所以用它来间接改

        eff = echo.AllParameters

        eff.WetDryMix = 50

        eff.Feedback = 50

        eff.LeftDelay = 500

        eff.RightDelay = 500

        eff.PanDelay = 0

        '''OK,就这样,你可以尝试用其他数据代替里面的数值,其中LeftDelay跟RightDelay的定义域在1~2000,

        ''' 你可以用echo的属性得到最大最小数值(方便了很多)

        echo.AllParameters = eff

 

        Me.Text = "echo ok"

    End Sub

End Class

 

好了,复制过去直接运行就可.

我用了Echo作为例子来说明问题(估计这个用的也是最多,效果最明显的)还有很多,你参照微软的例子,再改改上面的代码就能轻松实现,我就不废话了.

下一步.录音

相关文章推荐

VB.NET制作特效窗体

窗体是Windows应用程序的基础。新一代的开发工具Visual Basic.Net为设计制作窗体提供了更多简单而丰富的方法,无需再求助于复杂而易错的API函数,我们就可以轻松制作多种特效窗体: 1...

VB.NET 声音图形变化程序

  • 2005年11月15日 10:15
  • 66KB
  • 下载

vb.net 教程 4-9 二进制文件读写 游戏存档修改器

记得我的博客第一篇文章是写的《仙剑奇侠传3 外传》存档文件修改器(请参看:《[vb6]仙剑3外传的存档修改器》),当时是用vb6写的。 想想也是十多年过去了。 十多年过去已经很少在电脑上玩游戏了,还好...

vb.net 教程 5-9 屏幕范围内取色

屏幕范围内取色 在本博客 《vb:Cg色彩精灵》系列中,我们在vb6中使用Api函数对屏幕进行取色,在vb.net中,我们可以有更简单的方法完成此项工作。 延续使用我们在 《颜色》中的窗口界面,增加...

笔记9:vb.net的字符数据流TextReader、TextWriter

Imports System.IO Imports System.Text Public Class Form1 Private Sub Button1_Click(sender As Obj...

vb.net 教程 4-9 二进制文件读写 2

继续上一节讲解二进制文件的读写。 本节以实例的方式讲解二进制文件的读取。 请不要忘了加上 Imports System.IO 窗体设计如下: 按下“判断是否可执行文件”按钮时: Privat...

vb.net 教程 3-4 窗体编程 公共控件9 ListView 1

ListView:列表视图控件 使用ListView可以创建出类似于Windows资源管理器右侧的界面。 Items:获取ListView 中所有项的集合,这是一个ListViewItem...

vb.net 教程 4-9 二进制文件读写 3

在上一节的基础上,本节做一些扩展。 判断文件是什么类型,为了简化操作,仅仅只判断是否可执行文件、png文件、gif文件、jpeg文件。 上述文件对应的前面几个字节是: 可执行文件:4D 5A    P...

vb.net 教程 4-9 二进制文件读写 1

二进制文件的读写较文本文件读写复杂一些,但是搞清楚了当前读写 流 的位置,也很简单。 二进制文件读写是通过BinaryReader和BinaryWriter来执行的。 BinaryReader...

vb.net 教程 2-9 过程

过程 Sub过程(子过程)和Function(函数过程) 基本的语法: 访问级别 Sub 函数名称(ByVal/ByRef 参数 as 类型, ByVal/ByRef 参数2 as 类型……)  ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VB.NET实现DirectSound9 (6) 声音特效
举报原因:
原因补充:

(最多只允许输入30个字)