




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、利用Directsound編程實(shí)現(xiàn)實(shí)時混音開發(fā)者在線B更新時間:2007-10-作者:李強(qiáng)來源:天極開發(fā)本文關(guān)鍵詞:DirectSound編程實(shí)時混音摘要:將多個音頻文件或多路音頻數(shù)據(jù)同時輸出到音頻輸出設(shè)備上,就可同時聽到多個不同的聲音,這就 是混音。在游戲開發(fā),網(wǎng)絡(luò)視頻會議開發(fā)中都會用到混音技術(shù),本文詳細(xì)介紹如何利用Directsound實(shí)現(xiàn) 幾路不同的音頻進(jìn)行實(shí)時的混音。關(guān)鍵詞:Directsound混音在游戲開發(fā)中比較常用的音效素材都是比較短的,所以一般常用的API是playsound()函數(shù),比如 我們要在游戲背景中播放一個test.wav音效素材,只要簡單的調(diào)用下面的函數(shù)即可Play
2、Sound(test.wav”,NULL,SND_FILENAME|SND_ASYNC);如此簡單,事實(shí)上我們看到,國內(nèi)的游戲大致上都可以用PlaySound()搞定。但是既然是簡單,從 功能上就要受限了,如果遇到復(fù)雜的場景就沒法用playsound實(shí)現(xiàn)了,比如在場景中既有開門的聲音,又 有砍人的聲音,你如果用playsound就沒法同時聽到兩種聲音,只能是一個聲音完了再聽到另外一個聲音, 這時,就需要混音了。在網(wǎng)絡(luò)視頻會議開發(fā)中,如果不同的客戶端同時發(fā)言,如何將多個不同端點(diǎn)的話音數(shù)據(jù)經(jīng)網(wǎng)絡(luò)傳輸?shù)?達(dá)某一個端點(diǎn),經(jīng)該端點(diǎn)的Wave設(shè)備輸出,能同時聽到多個人的話音,從而實(shí)現(xiàn)局域網(wǎng)絡(luò)中多方的話音
3、交談,這也需要用到混音技術(shù)。在網(wǎng)絡(luò)上實(shí)現(xiàn)話音交談,特別強(qiáng)調(diào)實(shí)時性,要盡量保證話音的平滑、連續(xù),因此為了保證話音數(shù)據(jù)連 續(xù),減少話音數(shù)據(jù)存儲帶來的延時,在具體實(shí)現(xiàn)中,話音的錄制和播放都不采用文件的形式,錄制和播放 的話音數(shù)據(jù)都存在緩沖區(qū)中。在Windows系統(tǒng)中,一般情況下,高層Wave接口函數(shù)無法直接播放緩沖 區(qū)中的話音數(shù)據(jù),而必須用底層函數(shù)來實(shí)現(xiàn),常用的是Windows API中的Wave函數(shù)。將Wave數(shù)據(jù)在 Wave設(shè)備上輸出使用的是WaveOutWrite函數(shù),但是該函數(shù)不支持多路Wave數(shù)據(jù)的同時播放,為了 能達(dá)到多路Wave數(shù)據(jù)同時播放的效果,對緩沖區(qū)中多路Wave數(shù)據(jù)進(jìn)行必要的預(yù)
4、處理后,再提交給Wave 輸出設(shè)備播放,實(shí)現(xiàn)原理如圖1所示。圖1多路Wave混音的實(shí)現(xiàn)原理這種混音的方式效果跟你采用的算法有很大關(guān)系,但是如果我們采用Directsound進(jìn)行混音,就簡單 多了,我們只需要將我們要混音的內(nèi)容傳給它,Directsound會在內(nèi)部自動進(jìn)行混音的。下面我們就進(jìn)入 Directsound混音編程。在了解Directsound如何混音前我們先來看看DirectSound是如何播放一段wave音頻的。這里只是簡單的介紹一下播放聲音的步驟。第一步,創(chuàng)建一個設(shè)備對象。在你的代碼中你可以通過調(diào)用DirectSoundCreat8函數(shù)來創(chuàng)建一個支持IDirectSound8接口
5、的對 象,這個對象通常代表缺省的播放設(shè)備。當(dāng)然你可以枚舉可用的設(shè)備,然后將設(shè)備的GUID傳遞給 DirectSoundCreat8 函數(shù)。注意,Directsound雖然基于COM,但是你并不需要初始化com庫,這些Directsound都幫你做 好了,當(dāng)然,如果你使用DMOs特技,你就要自己初始化com庫了,切記。第二步,創(chuàng)建一個輔助Buffer,也叫后備緩沖區(qū)你可以通過IDirectSound8:CreateSoundBuffer來創(chuàng)建buffer對象,這個對象主要用來獲取處理 數(shù)據(jù),這種buffer稱作輔助緩沖區(qū),以和主緩沖區(qū)區(qū)別開來,Direcsound通過把幾個后備緩沖區(qū)的聲音 混合
6、到主緩沖區(qū)中,然后輸出到聲音輸出設(shè)備上,達(dá)到混音的效果。第三步,獲取PCM類型的數(shù)據(jù)將WAV文件或者其他資源的數(shù)據(jù)讀取到緩沖區(qū)中。第四步,將數(shù)據(jù)讀取到緩沖區(qū)你可以通過IDirectSoundBuffer8:Lock.方法來準(zhǔn)備一個輔助緩沖區(qū)來進(jìn)行寫操作,通常這個方法 返回一個內(nèi)存地址,見數(shù)據(jù)從你的私人buffer中復(fù)制到這個地址中,然后調(diào)用 IDirectSoundBuffer8:Unlock.第五步,播放緩沖區(qū)中的數(shù)據(jù)你可以通過IDirectSoundBuffer8:Play方法來播放緩沖區(qū)中的音頻數(shù)據(jù),你可以通過 IDirectSoundBuffer8:Stop來暫停播放數(shù)據(jù),你可以反復(fù)的
7、萊停止,播放,音頻數(shù)據(jù),如果你同時創(chuàng) 建了幾個buffer,那么你就可以同時來播放這些數(shù)據(jù),這些聲音會自動進(jìn)行混音的??吹搅税桑珼irectsound混音很簡單,我們只要在一個設(shè)備上創(chuàng)建幾個輔助的緩沖區(qū),然后將數(shù)據(jù)讀取到 緩沖區(qū)中,同時的播放,Directsound就會自動在主緩沖區(qū)自動混音的。至于同時可以播放幾個輔助緩沖 區(qū)則有硬件設(shè)備的性能決定。在WDM驅(qū)動模式下,混音的工作由核心混音器來完成,不同的輔助緩沖區(qū)可能具有不同的WAV格 式(例如,不同的采樣頻率),在必要的時候,輔助緩沖區(qū)的格式要轉(zhuǎn)換成主緩沖區(qū),或者核心混音器的 格式。在VXD驅(qū)動模式下,如果你的輔助緩沖區(qū)都采用相同的音頻格式
8、,并且硬件的音頻格式也和你的音頻 格式匹配,此時,混音器不用作任何的轉(zhuǎn)換。你的應(yīng)用程序可以創(chuàng)建一個主緩沖區(qū),然后通過 IDirectSoundBuffer8:SetFormat來設(shè)置硬件的輸出格式。要注意,只有你的協(xié)作度一定要是Priority Cooperative Level.,并且,一定要創(chuàng)建輔助緩沖區(qū)前設(shè)置主緩沖區(qū),DirectSound會將你的設(shè)置保存 下來。在WDM模式下,對主緩沖區(qū)的的設(shè)置沒有作用,因?yàn)橹骶彌_區(qū)的格式是由內(nèi)核混音器來決定的。 下面開始吧,讓我們看看如何進(jìn)行混音吧,假設(shè)我們的背景需要混音的素材是下面的三個wave文件, test1 .wav test2.wav te
9、st3.wav。首先定義一下我們需要的幾個變量:LPDIRECTSOUND8 g_pDS = NULL;LPDIRECTSOUNDBUFFER g_pDsbuffer3 = NULL;CWaveFile* g_pWaveFile;/WAVEFORMATEX g_wfxInput; 輸入的音頻格式這里簡單介紹一下CWaveFile類,Directsound里封裝了一個CWaveFile類用來操作wav文件,可以通過open來寫入文件的頭信息,write來寫入文件的數(shù)據(jù),Getsize函數(shù)獲取文件的長度,close關(guān) 閉文件。你可以在DirectSound的路徑下找到這個類的定義(SDKroot)
10、samplesC+CommonSrcDsutil.cpp。首先初始化DirectsoundBOOL InitDirectSound()if ( FAILED( hr = DirectSoundCreate(NULL, & g_pDS, NULL ) return FALSE;/ Set cooperative level.if ( FAILED( hr = g_pDS -SetCooperativeLevel( hwnd, DSSCL_PRIORITY ) return FALSE;return TRUE;在初始化Directsound的時候,創(chuàng)建設(shè)備對象最簡單的方法就是通過DirectSou
11、ndCreate8函數(shù), 這個函數(shù)的第一個參數(shù)指定了和這個對象邦定的設(shè)備的GUID,你可以通過枚舉設(shè)備來獲取這個設(shè)備的 GUID,如果這個參數(shù)也可以為NULL,缺省的系統(tǒng)的聲音輸出設(shè)備就是DSDEVID_DefaultPlayback。 當(dāng)你創(chuàng)建完設(shè)備對象后,一定要調(diào)用IDirectSound8:SetCooperativeLevel來設(shè)置協(xié)作度,否則,你 不會聽到聲音的。DirectSound 定義了三種水平,DSSCL_NORMAL, DSSCL_PRIORITY, and DSSCL_WRITEPRIMARY在Priority層次的協(xié)作度下,應(yīng)用程序可以有優(yōu)先權(quán)使用硬件資源,比如使用硬件
12、進(jìn)行混音,當(dāng)然也 可以設(shè)置主緩沖區(qū)的媒體格式,游戲程序應(yīng)該采用這個層次的協(xié)作度,這個層次的協(xié)作度在允許應(yīng)用程序 控制采用頻率和位深度的同時,也給應(yīng)用程序很大的權(quán)力,這個層次的協(xié)作度允許其他應(yīng)用程序的聲音和 游戲的音頻同時被聽到,不影響。下面的函數(shù)加載wave文件,然后將音頻數(shù)據(jù)讀取到緩沖區(qū)中,然后通過Directsound創(chuàng)建了的靜態(tài) 輔助緩沖區(qū),將音頻數(shù)據(jù)copy到Directsound的靜態(tài)輔助緩沖區(qū),然后就可以play 了。LPDIRECTSOUNDBUFFER LoadWaveFile(LPSTR IpzFileName)DSBUFFERDESC dsbdesc;HRESULT hr;
13、BYTE *pBuffer;DWORD dwSizeRead;LPDIRECTSOUNDBUFFER lpdsbStatic=NULL;if( FAILED( hr = g_pWaveFile-Open( lpzFileName, &g_wfxInput,WAVEFILE_WRITE )return NULL;DWORD dwSize = g_pWaveFile-GetSize();pBuffer = new BYTEdwSize;g_pWaveFile-Read(pBuffer,dwSize,&dwSizeRead);if(dwSizeRead 0)memset(dsbdesc,0,size
14、of(DSBUFFERDESC);dsbdesc.dwSize = sizeof(DSBUFFERDESC);dsbdesc.dwFlags =DSBCAPS_STATIC;dsbdesc.dwBufferBytes =dwSizeRead;dsbdesc.lpwfxFormat = g_wfxInput;if ( FAILED( g_pDS-CreateSoundBuffer(&dsbdesc, & lpdsbStatic, NULL )g_pWaveFile-Close();delete pBuffer;return NULLLPVOID lpvWrite;DWORD dwLength;i
15、f (DS_OK = lpdsbStatic -Lock(0, / Offset at which to start lock.0, / Size of lock; ignored because of flag.&lpvWrite, / Gets address of first part of lock.&dwLength, / Gets size of first part of lock. NULL, / Address of wraparound not needed. NULL, / Size of wraparound not needed. DSBLOCK_ENTIREBUFF
16、ER) / Flag.memcpy(lpvWrite, pBuffer, dwLength);lpdsbStatic -Unlock(lpvWrite, / Address of lock start.dwLength, / Size of lock.NULL, / No wraparound portion.0); / No wraparound size.delete pBuffer;return lpdsbStatic;這里我想簡單的講一下Directsound的輔助緩沖區(qū),在Directsound中,輔助緩沖區(qū)分兩類,一種 是Static Buffer,這種buffer主要用于播放那些
17、比較短的音頻,可以將文件中的音頻數(shù)據(jù)全部copy到 Static buffer中,如果音頻文件比較大,未了限制內(nèi)存的開銷,就要用到Streaming buffer,一般來說, Streaming buffer只能包含幾秒鐘的數(shù)據(jù)量,然后在播放的過程中不斷的更新streaming buffer中的 數(shù)據(jù)。靜態(tài)緩沖區(qū)的創(chuàng)建和管理和流緩沖區(qū)很相似,唯一的區(qū)別就是它們使用的方式不一樣,靜態(tài)緩沖區(qū) 只填充一次數(shù)據(jù),然后就可以play,然而,流緩沖區(qū)是一邊play,一邊填充數(shù)據(jù)。上面創(chuàng)建的就是得靜態(tài)的buffer,如果你要播放比較長的音頻文件,你就要使用streaming buffer 了。流緩沖區(qū)用來播放那些比較長的聲音,因?yàn)閿?shù)據(jù)比較長,沒法一次填充到緩沖區(qū)中,一邊播放,一邊 將新的數(shù)據(jù)填充到buffer中??梢酝ㄟ^IDirectSoundBuffer8:Play函授來播放緩沖區(qū)中的內(nèi)容,注意在該函數(shù)的參數(shù)中一定要 設(shè)置 DSBPLAY_LOOPING 標(biāo)志。通過IDirectSoundBuffer8:Stop方法中斷播放,該方法會立即停止緩沖區(qū)播放,因此你要確保所 有的數(shù)據(jù)都被播放,你可以通過拖動播放位置或者設(shè)置通
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 市政疏水管施工方案
- 公路平交施工方案
- 廠房石漆施工方案
- 河道駁坎施工方案
- 2025年度標(biāo)準(zhǔn)勞動關(guān)系解除與離職員工再就業(yè)服務(wù)協(xié)議
- 二零二五年度山場租賃承包與旅游開發(fā)協(xié)議
- 二零二五年度互聯(lián)網(wǎng)農(nóng)業(yè)合作入股協(xié)議
- 2025年度集體勞動合同到期續(xù)簽?zāi)0鍏f(xié)議
- 二零二五年度環(huán)境保護(hù)合作協(xié)議簽訂與審批流程
- 2025年度門面房租賃與商業(yè)形象設(shè)計(jì)合同
- 博物館跨界合作的趨勢與挑戰(zhàn)
- 抖音短視頻運(yùn)營整體策劃方案(完整版)
- 兒童文學(xué)概論(譚旭東第二版) 課件全套 第1-5章 兒童文學(xué)的基本內(nèi)涵- 兒童文學(xué)的各種文體
- 學(xué)習(xí)新思想做好接班人演講稿(5篇)
- 【甲醇液相催化法生產(chǎn)一氯甲烷的工藝設(shè)計(jì)13000字(論文)】
- DB32T3916-2020建筑地基基礎(chǔ)檢測規(guī)程
- 2024年演出經(jīng)紀(jì)人考試必背1000題及完整答案【歷年真題】
- 高壓電工證題庫電工培訓(xùn)試題及答案
- 2024年小汽車車牌指標(biāo)有償使用協(xié)議書
- 部編人教版六年級語文下冊全冊單元教材分析
- 新生兒單純皰疹病毒性腦炎的臨床診治要點(diǎn)詳解
評論
0/150
提交評論