關鍵字: 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作為例子來說明問題(估計這個用的也是最多,效果最明顯的)還有很多,你參照微軟的例子,再改改上面的代碼就能輕松實現,我就不廢話了.
下一步.錄音