DirectSound是DirectX組件之一,提供了對音頻設備的捕獲和播放能力,同時它也是惟一幾個支持Xp系統的音頻技術之一。 DirectSound主要有如下特色:git
優勢:github
缺點:函數
這裏咱們說說設備操做這一起。oop
在DirectSound中,一個設備對象就表明一個音頻設備,播放設備對象對應播放設備,輸入設備對象對應輸入設備。由於DirectSound使用COM協議,所以每一個設備對象都用接口來表示。這裏IDirectSound8這個接口就表明了一個輸出設備對象,應用程序能夠對同一個音頻設備建立多個設備對象來進行音頻輸出操做。舊版本的DirectSound使用的是IDirectSound接口,相比前者少了一些功能。ui
HRESULT WINAPI DirectSoundEnumerateW(In LPDSENUMCALLBACKW pDSEnumCallback, In_opt LPVOID pContext);
typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID, LPCWSTR, LPCWSTR, LPVOID);this
咱們經過DirectSoundEnumerateW這個函數來枚舉,該函數須要傳入一個回調函數(原型見上),當枚舉到一個設備時該回調會被調用。若是咱們想繼續枚舉,須要在這個回調用中返回TRUE來告訴系統,不然返回FALSE。另外一個參數pContext
容許用戶傳入額外的參數,傳入回調函數的最後一個實參就是這個pContext
。枚舉時,DirectSound會將默認也認做一個單獨的設備來對待,所以默認設備會被重複枚舉一次。當設備被做爲默認設備枚舉時,它的GUID和設備描述字符串都爲空,須要當心處理,這裏我直接跳過了該次枚舉:code
if (DirectSoundEnumerateW(enumerateCallback, nullptr) != DS_OK) { ... } BOOL CALLBACK DirectSoundBasic::enumerateCallback(LPGUID guid, LPCWSTR deviceDescription, LPCWSTR deviceDriverModule, LPVOID context) { Q_UNUSED(context); // if primary device, skip it if (guid == nullptr) return TRUE; ... }
HRESULT WINAPI DirectSoundCreate8(In_opt LPCGUID pcGuidDevice, Outptr LPDIRECTSOUND8 *ppDS8, Pre_null LPUNKNOWN pUnkOuter);對象
調用DirectSoundCreate8函數,咱們能夠建立一個設備對象,經過傳入一個枚舉設備時得到的GUID,函數會返給咱們一個IDirectSound8接口表明設備對象:blog
IDirectSound8* directSound8; if (DirectSoundCreate8(guid, &directSound8, NULL) != DS_OK) { std::wcout << L"[error] DirectSoundCreate8 call error!"; return TRUE; // if error, skip this device }
HRESULT IDirectSound8::SetCooperativeLevel(HWND hwnd, DWORD dwLevel)接口
在使用設備對象建立緩衝區(用來捕獲、播放音頻)以前,咱們須要設置設備對象的協做級別。這個協做級別至關於用戶對設備進行操做的優先級,分爲:
DSSCL_EXCLUSIVE: 互斥級別。對於DirectX8.0之前版本,僅播放當前應用的音頻數據,其餘應用的聲音不會被播放;對於DirectX8.0級之後版本,同DSSCL_PRIORITY版本。
DSSCL_WRITEPRIMARY:寫主緩衝區級別,應用能夠直接寫入主緩衝區,此時全部次緩衝區不會被播放(若是設備的驅動是DirectSound模擬出來的,則不能設置該級別)。
注意該函數須要傳入一個窗口句柄,由於咱們今天只介紹DirectSound的基本操做,我直接傳入桌面窗口的句柄並設定位DSSCL_NORMAL優先級:
if (directSound8->SetCooperativeLevel(GetDesktopWindow(), DSSCL_NORMAL) != DS_OK) { std::wcout << L"[error] SetCooperativeLevel call error!"; return TRUE; }
HRESULT IDirectSound8::GetCaps(LPDSCAPS pDSCaps)
不一樣的音頻播放設備具備不一樣的能力,DirectSound容許咱們查詢設備的能力:
咱們傳給GetCaps一個DSCAPS結構體地址,而後系統就幫咱們填充相應的數據,調用GetCaps前須要將DSCAPS結構體的dwSize設置爲DSCAPS的大小:
DSCAPS deviceCapability = { sizeof(deviceCapability) }; if (directSound8->GetCaps(&deviceCapability) != DS_OK) { std::wcout << L"[error] GetCaps call error!"; return TRUE; }
HRESULT IDirectSound8::GetSpeakerConfig(LPDWORD pdwSpeakerConfig)
HRESULT IDirectSound8::SetSpeakerConfig(LPDWORD pdwSpeakerConfig)
播放器配置只能是如下之一:
雖然MSDN文檔沒有寫清楚,可是經過查以上宏定義咱們發現它們是按大小順序定義的,所以不可能經過OR|
來包含多種可能,例子中若是調用出錯直接返回TRUE表示咱們繼續枚舉設備並繼續查詢那些設備能力:
DWORD deviceSpeakerConfiguration; if (directSound8->GetSpeakerConfig(&deviceSpeakerConfiguration) != DS_OK) { std::wcout << L"[error] GetSpeakerConfig call error!"; return TRUE; }
此次咱們用GUI界面來顯示實例運行的結果(出於方便考慮,之後我會用控制檯來顯示示例),爲防止用戶誤操做更改顯示的數據我將大部分控件都disable了:
完整代碼見連接。