聯系我們 - 廣告服務 - 聯系電話:
您的當前位置: > 關注 > > 正文

當前資訊!DirectSound能幫我們做什么?DirectSound開發指南

來源:CSDN 時間:2023-04-06 10:01:36

1DirectSound簡介(Introduction to DirectSound)

曾經學習過Directshow的開發,對于Dsound一直沒有仔細的萊學習,以前只是知道Dsound是做音頻開發的,我一直以為它和Dshow的結構體系差不多,經過仔細學習后,發現,其實他們完全 兩碼事。


(相關資料圖)

閑話少說,下面我們看看DirectSound到底能幫我們做些什么。

1播放WAVE格式的音頻文件或者資源。

2可以同時播放多個音頻。

3Assign high-priority sounds to hardware-controlled buffers

4播放3D立體聲音

5在聲音中添加特技效果,比如回聲,動態的改變特技的參數等

6將麥克風或者其他音頻輸入設備的聲音錄制成wave格式的文件

呵呵,DirectSound就能做這么多事情,讀到這里,我都有點懷疑DirectSound是不是就是封裝了mmio系列和wav系列的函數。因為這些底層的API也能夠完成這些事情。

2DirectSound初體驗(Getting Started with DirectSound)

在開始本節內容前,我會首先提醒一下,如果你想用Directsound開發,那么你首先要包含Dsound.h頭文件,其實我可以實話告訴你,你僅僅包含dsound.h你的工程肯定調補通,其實下面的一些頭文件也要包含,我第一次就搞了半天才搞好,

#include

#include

#include

#include

如果你還想使用Dsound的API的話,那么你就要在你的vc開發環境中添加Dsound..lib庫,

如果你的程序還提示有很多的外部鏈接找不到,那么我建議你可以將下面的庫都添加到你的工程中comctl32.lib dxerr9.lib winmm.lib dsound.lib dxguid.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib,這些是我從Dsound提供的例子中得到的,肯定夠你用的,ok,開發環境配置好了。

下面我們簡單的來學習一下如果通過Directsound的API播放聲音,既然是breif overview,那么詳細的內容你可以參考下面的一節內容,這里只是簡單的介紹一下播放聲音的步驟。

第一步,創建一個設備對象。

在你的代碼中你可以通過調用DirectSoundCreat8函數來創建一個支持IDirectSound8接口的對象,這個對象通常代表缺省的播放設備。當然你可以枚舉可用的設備,然后將設備的GUID傳遞給DirectSoundCreat8函數。

注意,Directsound雖然基于COM,但是你并不需要初始化com庫,這些Directsound都幫你做好了,當然,如果你使用DMOs特技,你就要自己初始化com庫了,切記。

第二步,創建一個輔助Buffer,也叫后備緩沖區

你可以通過IDirectSound8::CreateSoundBuffer來創建buffer對象,這個對象主要用來獲取處理數據,這種buffer稱作輔助緩沖區,以和主緩沖區區別開來,Direcsound通過把幾個后備緩沖區的聲音混合到主緩沖區中,然后輸出到聲音輸出設備上,達到混音的效果。

第三步,獲取PCM類型的數據

將WAV文件或者其他資源的數據讀取到緩沖區中。

第四步,將數據讀取到緩沖區

你可以通過IDirectSoundBuffer8::Lock.方法來準備一個輔助緩沖區來進行寫操作,通常這個方法返回一個內存地址,見數據從你的私人buffer中復制到這個地址中,然后調用IDirectSoundBuffer8::Unlock.

第五步,播放緩沖區中的數據

你可以通過IDirectSoundBuffer8::Play方法來播放緩沖區中的音頻數據,你可以通過IDirectSoundBuffer8::Stop來暫停播放數據,你可以反復的萊停止,播放,音頻數據,如果你同時創建了幾個buffer,那么你就可以同時來播放這些數據,這些聲音會自動進行混音的。

呵呵,簡單介紹到這里的,如果想深入了解,請繼續參考下一部分。

3DirectSound實用開發技巧Using DirectSound

在進行這部分之前,我們首先學習一下Directsound中常用的幾個對象,簡單學習一下哦

對象數量作用主要接口

設備每個應用程序只有一個設備對象用來管理設備,創建輔助緩沖區IDirectSound8

輔助緩沖區每一個聲音對應一個輔助緩沖區用來管理一個靜態的或者動態的聲音流,然后在主緩沖區中混音IDirectSoundBuffer8, IDirectSound3DBuffer8, IDirectSoundNotify8

主緩沖區一個應用程序只有一個主緩沖區將輔助緩沖區的數據進行混音,并且控制3D參數.IDirectSoundBuffer, IDirectSound3DListener8

特技沒有,或者來輔助緩沖的聲音數據進行處理Interface for the particular effect, such as IDirectSoundFXChorus8

首先,要創建一個設備對象,然后通過設備對象創建buffer對象。輔助緩沖區由應用程序創建和管理,DirectSound會自動地創建和管理主緩沖區,一般來說,應用程序即使沒有獲取這個對象的接口也可以播放音頻數據,但是,如果應用程序要想得到IDirectSound3DListener8接口,就必須要自己創建一個主緩沖區。

我們可以將短小的聲音文件全部讀取到輔助緩沖區中,然后通過一個簡單的命令來播放。如果聲音文件很長,就必須采用數據流了。

3.1Dsound設備對象(DirectSound Devices)

本節主要講述下面的幾個內容

1如何枚舉系統輸出聲音的設備

2創建設備對象

3設置聲音設備的協作度

下面首先看看如何枚舉系統中的聲音輸出設備

1如何枚舉系統輸出聲音的設備

如果你的應用程序使用用戶首選的輸出設備來輸出聲音,那么你就沒有必要來枚舉所有的輸出設備,如果你通過DirectSoundCreat8函數來創建一個設備對象的同時,就給這個對象指定了一個缺省的設備,當然如果遇到下面的一些情形,你就要來枚舉設備對象

例如,你的應用程序并不支持所有的輸出設備,或者你的應用程需要兩個或者多個設備,或者你希望用戶自己來選擇輸出設備。

枚舉設備,你首先要定義一個回調函數,這個回調函數可以被系統中的每個設備來調用,你可以在各函數做任何事情,這個函數的命名也沒有任何的限制,但是函數應該以DSEnumCallback為原型,如果枚舉沒有結束,這個回調函數就返回TRUE,如果枚舉結束,例如你找到合適的設備,這個函數就要返回FALSE。

下面是回調函數的一個例子,這個函數將枚舉的每一個設備都添加到一個combox中,將設備的GUID保存到一個item 中,這個函數的前三個參數由設備的驅動程序提供,第四個參數有DirectSoundEnumerate函數提供,這個參數可以是任意的32位值,這個例子里是combox的句柄,

BOOL CALLBACK DSEnumProc(LPGUID lpGUID,

LPCTSTR lpszDesc,

LPCTSTR lpszDrvName,

LPVOID lpContext )

{

HWND hCombo = (HWND)lpContext;

LPGUID lpTemp = NULL;

if (lpGUID != NULL)  //  NULL only for "Primary Sound Driver".

{

if ((lpTemp = (LPGUID)malloc(sizeof(GUID))) == NULL)

{

return(TRUE);

}

memcpy(lpTemp, lpGUID, sizeof(GUID));

}

ComboBox_AddString(hCombo, lpszDesc);

ComboBox_SetItemData(hCombo,

ComboBox_FindString(hCombo, 0, lpszDesc),

lpTemp );

free(lpTemp);

return(TRUE);

}

枚舉設備通常都是在對話框初始化的時候才進行的,我們假設hCombo就是combox句柄,hDlg就對話框的句柄,看看我們怎么來枚舉設備的吧

if (FAILED(DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc,

(VOID*)&hCombo)))

{

EndDialog(hDlg, TRUE);

return(TRUE);

}

在這個例子中,combox的句柄作為參數傳遞到DirectSoundEnumerate函數中,然后又被傳遞到回調函數中,這個參數你可以是你想傳遞的任意的32位值。

注:第一個被枚舉的設備通常稱為Primary sound driver,并且回調函數的lpGUID為NULL,這個設備就是用戶通過控制面板設置的缺省的輸出聲音設備,

2創建設備對象

創建設備對象最簡單的方法就是通過DirectSoundCreate8函數,這個函數的第一個參數指定了和這個對象邦定的設備的GUID,你可以通過枚舉設備來獲取這個設備的GUID,你可以傳遞一個下面的參數來指定一個缺省的設備

DSDEVID_DefaultPlayback 缺省的系統的聲音輸出設備,這個參數也可以為NULL

SDEVID_DefaultVoicePlayback,缺省的聲音輸出設備,通常指第二缺省設備,例如USB耳機麥克風

如果沒有聲音輸出設備,這個函數就返回error,或者,在VXD驅動程序下,如果聲音輸出設備正被某個應用程序通過waveform格式的api函數所控制,該函數也返回error,

下面是創建對象的代碼,及其簡單

LPDIRECTSOUND8 lpds;

HRESULT hr = DirectSoundCreate8(NULL, &lpds, NULL));

如果你想通過表準的COM調用來創建設備對象,下面我就給出代碼,你可以比較一下

HRESULT hr = CoInitializeEx(NULL, 0);

if (FAILED(hr))

{

ErrorHandler(hr);  // Add error-handling here.

}

LPDIRECTSOUND8 lpds;

hr = CoCreateInstance(&CLSID_DirectSound8,

NULL,

CLSCTX_INPROC_SERVER,

IID_IDirectSound8,

(LPVOID*) &lpds);

if (FAILED(hr))

{

ErrorHandler(hr);  // Add error-handling here.

}

hr = lpds->Initialize(NULL);

if (FAILED(hr))

{

ErrorHandler(hr);  // Add error-handling here.

}

CoUninitialize();

3設置聲音設備的協作度

因為Windows是一個多任務操作環境,在同一個時刻有可能多個應用程序共用同一個設備,通過協作水平,DirectX就可以保證這些應用程序在訪問設備的時候不會沖突,每個Directsound應用程序都有一個協作度,用來確定來接近設備的程度,

當你創建完設備對象后,一定要調用IDirectSound8::SetCooperativeLevel來設置協作度,否則,你不會聽到聲音的,

HRESULT hr = lpDirectSound->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);

if (FAILED(hr))

{

ErrorHandler(hr);  // Add error-handling here.

}

Hwnd參數代表了應用程序的窗口。

DirectSound定義了三種水平,DSSCL_NORMAL, DSSCL_PRIORITY, and DSSCL_WRITEPRIMARY

在NORMAL水平的協作度下,應用程序不能設置主緩沖區的格式,也不能對主緩沖區進行寫操作,所有在這個層次的應用程序使用的媒體格式都是22kHZ,立體聲,采樣精度8位,所以,設備可以在各個應用程序中任意的切換。

在Priority層次的協作度下,應用程序可以有優先權使用硬件資源,比如使用硬件進行混音,當然也可以設置主緩沖區的媒體格式,游戲程序應該采用這個層次的協作度,這個層次的協作度在允許應用程序控制采用頻率和位深度的同時,也給應用程序很大的權力,這個層次的協作度允許其他應用程序的聲音和游戲的音頻同時被聽到,不影響。

最高層次的協作度就是Write_primary,當采用這個層次的協作度來使用一個dsound設備時,在非WDM模式驅動下,你的應用程序可以直接操作主緩沖區,在這個模式下,應有程序必須直接的操作主緩沖區。如果你想直接把音頻數據直接寫入到主緩沖區,你就要將你的協作度模式設置為writeprimary,如果你的應用程序沒有設置到這個層次,那么所有的對主緩沖區的IDirectSoundBuffer::Lock都會失敗。

當你的應用程序的協作度設置為wirte_primary水平時,并且你的應用程序gains the foreground,那么其他應用程序的輔助緩沖區就會停止,并且標示為lost,當你的應用程序轉到background,那么它的主緩沖區就會標示為lost,當它再次回到foreground的時候會恢復到原來的狀態,如果你的設備沒有出現在你的系統中,那么你就沒法設置wirte primary協作度了,所以,在設置協作度之前,可以通過IDirectSound8::GetCaps方法來查詢一下設備是否可用。

4設置聲音設備(揚聲器)

在windowos98或者2000系統中,用戶可以通過控制面板來設置揚聲器的屬性,應用程序可以通過IDirectSound8::GetSpeakerConfig.函數來獲取這些屬性,我們不建議應用程序通過IDirectSound8::SetSpeakerConfig函授來設置揚聲器的屬性,因為這些設置的改動會影響到其他用戶或者應用程序。

5查詢輸出設備的性能

你的應用程序可以通過Directsound來檢查聲音設備的性能,然而許多應用程序并不需要這么做,因為Directsound會自動地利用硬件提供的較好的性能,并不需要你手動地來選擇。

但是,However, high-performance applications can use the information to scale their sound requirements to the available hardware. For example, an application might choose to play more sounds if hardware mixing is available than if it is not.

當你調用DirectSoundCreate8創建一個設備對象后,你的應用程序就可以通過IDirectSound8::GetCaps函數來獲取設備的性能屬性,下面的代碼演示了這個過程

DSCAPS dscaps;

dscaps.dwSize = sizeof(DSCAPS);

HRESULT hr = lpDirectSound->GetCaps(&dscaps);

if (FAILED(hr))

{

ErrorHandler(hr);  // Add error-handling here.

}

通過DSCAPS結構,該函數就給我返回硬件設備的一些性能,但是在調用這個函數之前一定要初始化這個結構的dwSize成員。

如果你的應用程序能夠操作硬件設備,比如你的協作度是Write_primory級別的,那么你在硬件設備上分配內存的時候,就要調用IDirectSoudn8::GetCaps來查看一下硬件的資源是否滿足你的要求。

責任編輯:

標簽: 應用程序

精彩放送:

新聞聚焦
Top 岛国精品在线