×

DirectX与VB.NET编程(六)声音特效

Kalet Kalet 发表于2009-03-20 12:00:14 浏览319 评论0

抢沙发发表评论

这次是声音特效的实现。
声音特效,简单地说就是对声音的特效处理工作,使声音听起来更加具有特殊效果。


===============华丽的分割线===============

DirectX与VB.NET编程(六)声音特效

·了解DirectSound中的所有声音特效、属性及其取值范围;
·掌握实现回声特效的原理和方法;
·能够举一反三地实现其它声音特效。


===============华丽的分割线===============


在DirectSound中,一共拥有如下特效、属性及其取值范围:
Chorus:
      Wet/Dry Mix:0-100(%)
      Depth:0-100(%)
      Feedback:-99-99(%)
      Frequency:0-10(Hz)
      Delay:0-20(ms)
Compressor:
      Gain:-60-60(dB)
      Attack:1-500(ms)
      Release:50-3000(ms)
      Threshold:-60-0(dB)
      Ratio:1-100(x:1)
      Predelay:0-4(ms)
Distortion:
      Gain:-60-0(dB)
      Edge:0-100(%)
      PostEQ Center Freq:100-3675(Hz)
      PostEQ Bandwidth:100-3675(Hz)
      PreLowpass Cutoff:100-3675(Hz)
Echo:
      Wet/Dry Mix:0-100(%)
      Feedback:0-100(%)
      Left Delay:1-2000(ms)
      Right Delay:1-2000(ms)
      Pan Delay:True;False(Boolean)
Flanger:
      Wet/Dry Mix:0-100(%)
      Depth:0-100(%)
      Feedback:-99-99(%)
      Frequency:0-10(Hz)
      Delay:0-4(ms)
Gargle:
      Rate:1-1000(Hz)
Waves Reverb:
      In Gain:-96-0(dB)
      Waves Reverb Mix:-96-0(dB)
      Waves Reverb Time:0.001-3000.000(ms)
      HighFreq RT Ratio:0.001-0.999(x:1)
ParamEq:
      Center Freq:80-7350(Hz)
      Bandwidth:1-36(Hz)
      Gain:-15-15(dB)
大家可以把这个表当作手册一样,可以随时查询特效的方法。


===============华丽的分割线===============


下面实现一个回声特效,其余的特效根据其对应属性,实现的方法大同小异。


===============华丽的分割线===============


DirectSound允许一个缓冲中驻留数个特效,这些特效储存在一个数组特效描述中,不过这些需要在播放之前就初始化好,在播放中途是不允许再修改特效的数量的。如果需要修改,必须首先停止声音的播放。


===============华丽的分割线===============


请在窗口上放置4个标签(Label)、4个文本框(TextBox)、一个按钮(Button)和一个复选框(CheckBox),窗口设计请参照图一或者后面的代码。



图1

===============华丽的分割线===============


首先声明需要使用到的类全局变量:
Dim Dev As Device
Dim SB As SecondaryBuffer
Dim SBDes As BufferDescription

要让缓冲区的特效可调,必须将缓冲区描述的ControlEffect属性设置为True,并使用它来初始化缓冲区:
SBDes.ControlEffects = True
SB = New SecondaryBuffer("D:\魔兽争霸2\DRIVERS\DIGTEST.WAV", SBDes, Dev)

由于声音特效以特效描述的形式储存在数组中,因此需要定义一个该类型数组,由于本例只有一个特效,数组最大下标被定义为0,如果您需要使用多个特效,则根据实际情况进行定义。
设置第一个特效为回声特效,回声特效的常数储存在DSoundHelper的枚举中:
Dim Eff(0) As EffectDescription
Eff(0).GuidEffectClass = DSoundHelper.StandardEchoGuid

设置好数组之后,开始将特效数组注入到缓冲区:
SB.SetEffects(Eff)
所有前期工作已经做好,开始播放声音:
SB.Play(0, BufferPlayFlags.Looping)


===============华丽的分割线===============


下面编写应用设置按钮的动作,这里按下按钮后是调用了Changed()子程序。
首先需要声明两个变量,类型是EchoEffect和EffectsEcho,这两个类型比较容易混淆,您可以根据英文含义理解,EchoEffect意为“回声类型的特效”,EffectsEcho意为“回声特效的效果(参数)”,请务必牢记。
因为我们使用的是回声特效,因此使用这两个类型的变量,如果使用其余特效,可以以此类推其类型名称。
声明语句如下:
Dim EF As EchoEffect
Dim FE As New EffectsEcho

要改变声音的效果,必须从缓冲区提取特效,然后改变音效的参数,这样才能达到改变的目的,而不是从数组来改变,因为数组只是中间的临时量而已。
因此,首先需要从缓冲区提取特效
EF = SB.GetEffects(0)
开始设置参数,因为参数不能直接修改,必须通过以前提到过的方法,即:
FE = EF.AllParameters
FE.WetDryMix = Val(TextBox1.Text)
FE.Feedback = Val(TextBox2.Text)
FE.LeftDelay = Val(TextBox3.Text)
FE.RightDelay = Val(TextBox4.Text)

'由于PanDelay是布尔型,所以如此设置
If CheckBox1.Checked Then
        FE.PanDelay = 1
Else
        FE.PanDelay = 0
End If
EF.AllParameters = FE

这样就已经将参数设置好了。


===============华丽的分割线===============


下面是程序的全部代码:
Imports Microsoft.DirectX.DirectSound
Imports Microsoft.DirectX


Public Class Form1
        Inherits System.Windows.Forms.Form


        Dim Dev As Device
        Dim SB As SecondaryBuffer
        Dim SBDes As BufferDescription


#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 Label1 As System.Windows.Forms.Label
        Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
        Friend WithEvents Label2 As System.Windows.Forms.Label
        Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
        Friend WithEvents Label3 As System.Windows.Forms.Label
        Friend WithEvents TextBox3 As System.Windows.Forms.TextBox
        Friend WithEvents Label4 As System.Windows.Forms.Label
        Friend WithEvents TextBox4 As System.Windows.Forms.TextBox
        Friend WithEvents CheckBox1 As System.Windows.Forms.CheckBox
        Friend WithEvents Button1 As System.Windows.Forms.Button
        <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
            Me.Label1 = New System.Windows.Forms.Label
            Me.TextBox1 = New System.Windows.Forms.TextBox
            Me.Label2 = New System.Windows.Forms.Label
            Me.TextBox2 = New System.Windows.Forms.TextBox
            Me.Label3 = New System.Windows.Forms.Label
            Me.TextBox3 = New System.Windows.Forms.TextBox
            Me.Label4 = New System.Windows.Forms.Label
            Me.TextBox4 = New System.Windows.Forms.TextBox
            Me.CheckBox1 = New System.Windows.Forms.CheckBoxDirectX与VB.NET编程(六)声音特效
            Me.Button1 = New System.Windows.Forms.Button
            Me.SuspendLayout()
            '
            'Label1
            '
            Me.Label1.Location = New System.Drawing.Point(8, 8)
            Me.Label1.Name = "Label1"
            Me.Label1.Size = New System.Drawing.Size(384, 16)
            Me.Label1.TabIndex = 0
            Me.Label1.Text = "Wet/Dry Mix(%):(0-100)"
            '
            'TextBox1
            '
            Me.TextBox1.Location = New System.Drawing.Point(8, 24)
            Me.TextBox1.Name = "TextBox1"
            Me.TextBox1.Size = New System.Drawing.Size(384, 21)
            Me.TextBox1.TabIndex = 1
            Me.TextBox1.Text = "50"
            '
            'Label2
            '
            Me.Label2.Location = New System.Drawing.Point(8, 48)
            Me.Label2.Name = "Label2"
            Me.Label2.Size = New System.Drawing.Size(384, 16)
            Me.Label2.TabIndex = 2
            Me.Label2.Text = "Feedback(%):(0-100)"
            '
            'TextBox2
            '
            Me.TextBox2.Location = New System.Drawing.Point(8, 64)
            Me.TextBox2.Name = "TextBox2"
            Me.TextBox2.Size = New System.Drawing.Size(384, 21)
            Me.TextBox2.TabIndex = 3
            Me.TextBox2.Text = "50"
            '
            'Label3
            '
            Me.Label3.Location = New System.Drawing.Point(8, 88)
            Me.Label3.Name = "Label3"
            Me.Label3.Size = New System.Drawing.Size(384, 16)
            Me.Label3.TabIndex = 4
            Me.Label3.Text = "Left Delay(ms):(1-2000)"
            '
            'TextBox3
            '
            Me.TextBox3.Location = New System.Drawing.Point(8, 104)
            Me.TextBox3.Name = "TextBox3"
            Me.TextBox3.Size = New System.Drawing.Size(384, 21)
            Me.TextBox3.TabIndex = 5
            Me.TextBox3.Text = "1000"
            '
            'Label4
            '
            Me.Label4.Location = New System.Drawing.Point(8, 128)
            Me.Label4.Name = "Label4"
            Me.Label4.Size = New System.Drawing.Size(384, 16)
            Me.Label4.TabIndex = 6
            Me.Label4.Text = "Right Delay(ms):(1-2000)"
            '
            'TextBox4
            '
            Me.TextBox4.Location = New System.Drawing.Point(8, 144)
            Me.TextBox4.Name = "TextBox4"
            Me.TextBox4.Size = New System.Drawing.Size(384, 21)
            Me.TextBox4.TabIndex = 7
            Me.TextBox4.Text = "1000"
            '
            'CheckBox1
            '
            Me.CheckBox1.Location = New System.Drawing.Point(8, 168)
            Me.CheckBox1.Name = "CheckBox1"
            Me.CheckBox1.Size = New System.Drawing.Size(384, 16)
            Me.CheckBox1.TabIndex = 8
            Me.CheckBox1.Text = "Pan Delay"
            '
            'Button1
            '
            Me.Button1.Location = New System.Drawing.Point(312, 184)
            Me.Button1.Name = "Button1"
            Me.Button1.Size = New System.Drawing.Size(80, 24)
            Me.Button1.TabIndex = 9
            Me.Button1.Text = "应用设置"
            '
            'Form1
            '
            Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
            Me.ClientSize = New System.Drawing.Size(400, 214)
            Me.Controls.Add(Me.Button1)
            Me.Controls.Add(Me.CheckBox1)
            Me.Controls.Add(Me.TextBox4)
            Me.Controls.Add(Me.Label4)
            Me.Controls.Add(Me.TextBox3)
            Me.Controls.Add(Me.Label3)
            Me.Controls.Add(Me.TextBox2)
            Me.Controls.Add(Me.Label2)
            Me.Controls.Add(Me.TextBox1)
            Me.Controls.Add(Me.Label1)
            Me.MaximizeBox = False
            Me.Name = "Form1"
            Me.Text = "声音特效:回声"
            Me.ResumeLayout(False)


        End Sub


#End Region


        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


            Dev = New Device
            Dev.SetCooperativeLevel(Me, CooperativeLevel.Normal)
            SBDes = New BufferDescription


            '设置为特效可调
            SBDes.ControlEffects = True
            SB = New SecondaryBuffer("D:\魔兽争霸2\DRIVERS\DIGTEST.WAV", SBDes, Dev)


            '设置第一个特效为回声特效
            Dim Eff(0) As EffectDescription
            Eff(0).GuidEffectClass = DSoundHelper.StandardEchoGuid
            '将特效数组注入缓冲区
            SB.SetEffects(Eff)
            '播放声音
            SB.Play(0, BufferPlayFlags.Looping)
            '应用设置
            Changed()
        End Sub


        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            '应用设置
            Changed()
        End Sub


        Private Sub Changed()
            Dim EF As EchoEffect
            Dim FE As New EffectsEcho


            '从缓冲区提取第一个特效(回声)
            EF = SB.GetEffects(0)
            '设置各参数
            FE = EF.AllParameters
            FE.WetDryMix = Val(TextBox1.Text)
            FE.Feedback = Val(TextBox2.Text)
            FE.LeftDelay = Val(TextBox3.Text)
            FE.RightDelay = Val(TextBox4.Text)
            '由于PanDelay是布尔型,所以如此设置
            If CheckBox1.Checked Then
                FE.PanDelay = 1
            Else
                FE.PanDelay = 0
            End If
            EF.AllParameters = FE
        End Sub
End Class


声音特效已经完毕了,希望您可以仿照他来实现其他特效。

DirectX与VB.NET编程(六)声音特效

下次是声音的混音,简单的声音引擎。



群贤毕至

访客